@amqp-contract/client 0.6.0 → 0.8.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 +13 -26
- package/dist/index.cjs +46 -4
- package/dist/index.d.cts +25 -4
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +25 -4
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +46 -4
- package/dist/index.mjs.map +1 -1
- package/docs/index.md +54 -29
- package/package.json +20 -12
package/README.md
CHANGED
|
@@ -19,37 +19,24 @@ pnpm add @amqp-contract/client
|
|
|
19
19
|
## Usage
|
|
20
20
|
|
|
21
21
|
```typescript
|
|
22
|
-
import { TypedAmqpClient } from
|
|
23
|
-
import { contract } from
|
|
22
|
+
import { TypedAmqpClient } from "@amqp-contract/client";
|
|
23
|
+
import { contract } from "./contract";
|
|
24
24
|
|
|
25
25
|
// Create client from contract (automatically connects and waits for connection)
|
|
26
|
-
const
|
|
26
|
+
const client = await TypedAmqpClient.create({
|
|
27
27
|
contract,
|
|
28
|
-
urls: [
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
// Handle connection errors
|
|
32
|
-
if (clientResult.isError()) {
|
|
33
|
-
console.error('Failed to create client:', clientResult.error);
|
|
34
|
-
throw clientResult.error; // or handle appropriately
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const client = clientResult.get();
|
|
28
|
+
urls: ["amqp://localhost"],
|
|
29
|
+
}).resultToPromise();
|
|
38
30
|
|
|
39
31
|
// Publish message with explicit error handling
|
|
40
|
-
const result = await client
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
// result.error is either TechnicalError or MessageValidationError
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
console.log('Published successfully');
|
|
32
|
+
const result = await client
|
|
33
|
+
.publish("orderCreated", {
|
|
34
|
+
orderId: "ORD-123",
|
|
35
|
+
amount: 99.99,
|
|
36
|
+
})
|
|
37
|
+
.resultToPromise();
|
|
38
|
+
|
|
39
|
+
console.log("Published successfully");
|
|
53
40
|
|
|
54
41
|
// Clean up
|
|
55
42
|
await client.close();
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
let _amqp_contract_core = require("@amqp-contract/core");
|
|
2
2
|
let _swan_io_boxed = require("@swan-io/boxed");
|
|
3
|
+
let node_zlib = require("node:zlib");
|
|
4
|
+
let ts_pattern = require("ts-pattern");
|
|
5
|
+
let node_util = require("node:util");
|
|
3
6
|
|
|
4
7
|
//#region src/errors.ts
|
|
5
8
|
/**
|
|
@@ -36,6 +39,24 @@ var MessageValidationError = class extends ClientError {
|
|
|
36
39
|
}
|
|
37
40
|
};
|
|
38
41
|
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region src/compression.ts
|
|
44
|
+
const gzipAsync = (0, node_util.promisify)(node_zlib.gzip);
|
|
45
|
+
const deflateAsync = (0, node_util.promisify)(node_zlib.deflate);
|
|
46
|
+
/**
|
|
47
|
+
* Compress a buffer using the specified compression algorithm.
|
|
48
|
+
*
|
|
49
|
+
* @param buffer - The buffer to compress
|
|
50
|
+
* @param algorithm - The compression algorithm to use
|
|
51
|
+
* @returns A promise that resolves to the compressed buffer
|
|
52
|
+
* @throws Error if compression fails
|
|
53
|
+
*
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
async function compressBuffer(buffer, algorithm) {
|
|
57
|
+
return (0, ts_pattern.match)(algorithm).with("gzip", () => gzipAsync(buffer)).with("deflate", () => deflateAsync(buffer)).exhaustive();
|
|
58
|
+
}
|
|
59
|
+
|
|
39
60
|
//#endregion
|
|
40
61
|
//#region src/client.ts
|
|
41
62
|
/**
|
|
@@ -66,7 +87,17 @@ var TypedAmqpClient = class TypedAmqpClient {
|
|
|
66
87
|
}
|
|
67
88
|
/**
|
|
68
89
|
* Publish a message using a defined publisher
|
|
69
|
-
*
|
|
90
|
+
*
|
|
91
|
+
* @param publisherName - The name of the publisher to use
|
|
92
|
+
* @param message - The message to publish
|
|
93
|
+
* @param options - Optional publish options including compression, headers, priority, etc.
|
|
94
|
+
*
|
|
95
|
+
* @remarks
|
|
96
|
+
* If `options.compression` is specified, the message will be compressed before publishing
|
|
97
|
+
* and the `contentEncoding` property will be set automatically. Any `contentEncoding`
|
|
98
|
+
* value already in options will be overwritten by the compression algorithm.
|
|
99
|
+
*
|
|
100
|
+
* @returns Result.Ok(void) on success, or Result.Error with specific error on failure
|
|
70
101
|
*/
|
|
71
102
|
publish(publisherName, message, options) {
|
|
72
103
|
const publishers = this.contract.publishers;
|
|
@@ -81,15 +112,26 @@ var TypedAmqpClient = class TypedAmqpClient {
|
|
|
81
112
|
});
|
|
82
113
|
};
|
|
83
114
|
const publishMessage = (validatedMessage) => {
|
|
84
|
-
|
|
115
|
+
const { compression, ...restOptions } = options ?? {};
|
|
116
|
+
const publishOptions = { ...restOptions };
|
|
117
|
+
const preparePayload = () => {
|
|
118
|
+
if (compression) {
|
|
119
|
+
const messageBuffer = Buffer.from(JSON.stringify(validatedMessage));
|
|
120
|
+
publishOptions.contentEncoding = compression;
|
|
121
|
+
return _swan_io_boxed.Future.fromPromise(compressBuffer(messageBuffer, compression)).mapError((error) => new TechnicalError(`Failed to compress message`, error)).map((compressedBuffer) => _swan_io_boxed.Result.Ok(compressedBuffer));
|
|
122
|
+
}
|
|
123
|
+
return _swan_io_boxed.Future.value(_swan_io_boxed.Result.Ok(validatedMessage));
|
|
124
|
+
};
|
|
125
|
+
return preparePayload().flatMapOk((payload) => _swan_io_boxed.Future.fromPromise(this.amqpClient.channel.publish(publisher.exchange.name, publisher.routingKey ?? "", payload, publishOptions)).mapError((error) => new TechnicalError(`Failed to publish message`, error)).mapOkToResult((published) => {
|
|
85
126
|
if (!published) return _swan_io_boxed.Result.Error(new TechnicalError(`Failed to publish message for publisher "${String(publisherName)}": Channel rejected the message (buffer full or other channel issue)`));
|
|
86
127
|
this.logger?.info("Message published successfully", {
|
|
87
128
|
publisherName: String(publisherName),
|
|
88
129
|
exchange: publisher.exchange.name,
|
|
89
|
-
routingKey: publisher.routingKey
|
|
130
|
+
routingKey: publisher.routingKey,
|
|
131
|
+
compressed: !!compression
|
|
90
132
|
});
|
|
91
133
|
return _swan_io_boxed.Result.Ok(void 0);
|
|
92
|
-
});
|
|
134
|
+
}));
|
|
93
135
|
};
|
|
94
136
|
return validateMessage().flatMapOk((validatedMessage) => publishMessage(validatedMessage));
|
|
95
137
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Logger } from "@amqp-contract/core";
|
|
2
2
|
import { AmqpConnectionManagerOptions, ConnectionUrl } from "amqp-connection-manager";
|
|
3
|
-
import { ContractDefinition, InferPublisherNames, PublisherDefinition } from "@amqp-contract/contract";
|
|
3
|
+
import { CompressionAlgorithm, ContractDefinition, InferPublisherNames, PublisherDefinition } from "@amqp-contract/contract";
|
|
4
4
|
import { Future, Result } from "@swan-io/boxed";
|
|
5
5
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
6
6
|
import { Options } from "amqplib";
|
|
@@ -52,6 +52,17 @@ type InferPublisher<TContract extends ContractDefinition, TName extends InferPub
|
|
|
52
52
|
type ClientInferPublisherInput<TContract extends ContractDefinition, TName extends InferPublisherNames<TContract>> = PublisherInferInput<InferPublisher<TContract, TName>>;
|
|
53
53
|
//#endregion
|
|
54
54
|
//#region src/client.d.ts
|
|
55
|
+
/**
|
|
56
|
+
* Publish options that extend amqplib's Options.Publish with optional compression support.
|
|
57
|
+
*/
|
|
58
|
+
type PublishOptions = Options.Publish & {
|
|
59
|
+
/**
|
|
60
|
+
* Optional compression algorithm to use for the message payload.
|
|
61
|
+
* When specified, the message will be compressed using the chosen algorithm
|
|
62
|
+
* and the contentEncoding header will be set automatically.
|
|
63
|
+
*/
|
|
64
|
+
compression?: CompressionAlgorithm | undefined;
|
|
65
|
+
};
|
|
55
66
|
/**
|
|
56
67
|
* Options for creating a client
|
|
57
68
|
*/
|
|
@@ -87,9 +98,19 @@ declare class TypedAmqpClient<TContract extends ContractDefinition> {
|
|
|
87
98
|
}: CreateClientOptions<TContract>): Future<Result<TypedAmqpClient<TContract>, TechnicalError>>;
|
|
88
99
|
/**
|
|
89
100
|
* Publish a message using a defined publisher
|
|
90
|
-
*
|
|
101
|
+
*
|
|
102
|
+
* @param publisherName - The name of the publisher to use
|
|
103
|
+
* @param message - The message to publish
|
|
104
|
+
* @param options - Optional publish options including compression, headers, priority, etc.
|
|
105
|
+
*
|
|
106
|
+
* @remarks
|
|
107
|
+
* If `options.compression` is specified, the message will be compressed before publishing
|
|
108
|
+
* and the `contentEncoding` property will be set automatically. Any `contentEncoding`
|
|
109
|
+
* value already in options will be overwritten by the compression algorithm.
|
|
110
|
+
*
|
|
111
|
+
* @returns Result.Ok(void) on success, or Result.Error with specific error on failure
|
|
91
112
|
*/
|
|
92
|
-
publish<TName extends InferPublisherNames<TContract>>(publisherName: TName, message: ClientInferPublisherInput<TContract, TName>, options?:
|
|
113
|
+
publish<TName extends InferPublisherNames<TContract>>(publisherName: TName, message: ClientInferPublisherInput<TContract, TName>, options?: PublishOptions): Future<Result<void, TechnicalError | MessageValidationError>>;
|
|
93
114
|
/**
|
|
94
115
|
* Close the channel and connection
|
|
95
116
|
*/
|
|
@@ -97,5 +118,5 @@ declare class TypedAmqpClient<TContract extends ContractDefinition> {
|
|
|
97
118
|
private waitForConnectionReady;
|
|
98
119
|
}
|
|
99
120
|
//#endregion
|
|
100
|
-
export { type ClientInferPublisherInput, type CreateClientOptions, MessageValidationError, TechnicalError, TypedAmqpClient };
|
|
121
|
+
export { type ClientInferPublisherInput, type CreateClientOptions, MessageValidationError, type PublishOptions, TechnicalError, TypedAmqpClient };
|
|
101
122
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/errors.ts","../src/types.ts","../src/client.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;uBAGe,WAAA,SAAoB,KAAA;;;;;;AAkBnC;AAaa,cAbA,cAAA,SAAuB,WAAA,CAamB;;;;AC7BO;;;AAM5C,cDuBL,sBAAA,SAA+B,WAAA,CCvB1B;EAAgB,SAAA,aAAA,EAAA,MAAA;EAK7B,SAAA,MAAA,EAAA,OAAmB;EAAoB,WAAA,CAAA,aAAA,EAAA,MAAA,EAAA,MAAA,EAAA,OAAA;;;;;;;KANvC,iCAAiC,oBACpC,gBAAgB;;;;ADUlB,KCLK,mBDKuB,CAAA,mBCLgB,mBDKG,CAAA,GCLoB,gBDKpB,CCJ7C,UDI6C,CAAA,SAAA,CAAA,CAAA,SAAA,CAAA,CAAA;AAa/C;;;KCXK,kCAAkC,sBAAsB,YAAY;AAlBX;;;KAuBzD,cAjBa,CAAA,kBAkBE,kBAlBF,EAAA,cAmBF,mBAnBE,CAmBkB,SAnBlB,CAAA,CAAA,GAoBd,eApBc,CAoBE,SApBF,CAAA,CAoBa,KApBb,CAAA;;AAAgB;;AAMhC,KAmBU,yBAnBV,CAAA,kBAoBkB,kBApBlB,EAAA,cAqBc,mBArBd,CAqBkC,SArBlC,CAAA,CAAA,GAsBE,mBAtBF,CAsBsB,cAtBtB,CAsBqC,SAtBrC,EAsBgD,KAtBhD,CAAA,CAAA;;;;;ADIF;AAaa,
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/errors.ts","../src/types.ts","../src/client.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;uBAGe,WAAA,SAAoB,KAAA;;;;;;AAkBnC;AAaa,cAbA,cAAA,SAAuB,WAAA,CAamB;;;;AC7BO;;;AAM5C,cDuBL,sBAAA,SAA+B,WAAA,CCvB1B;EAAgB,SAAA,aAAA,EAAA,MAAA;EAK7B,SAAA,MAAA,EAAA,OAAmB;EAAoB,WAAA,CAAA,aAAA,EAAA,MAAA,EAAA,MAAA,EAAA,OAAA;;;;;;;KANvC,iCAAiC,oBACpC,gBAAgB;;;;ADUlB,KCLK,mBDKuB,CAAA,mBCLgB,mBDKG,CAAA,GCLoB,gBDKpB,CCJ7C,UDI6C,CAAA,SAAA,CAAA,CAAA,SAAA,CAAA,CAAA;AAa/C;;;KCXK,kCAAkC,sBAAsB,YAAY;AAlBX;;;KAuBzD,cAjBa,CAAA,kBAkBE,kBAlBF,EAAA,cAmBF,mBAnBE,CAmBkB,SAnBlB,CAAA,CAAA,GAoBd,eApBc,CAoBE,SApBF,CAAA,CAoBa,KApBb,CAAA;;AAAgB;;AAMhC,KAmBU,yBAnBV,CAAA,kBAoBkB,kBApBlB,EAAA,cAqBc,mBArBd,CAqBkC,SArBlC,CAAA,CAAA,GAsBE,mBAtBF,CAsBsB,cAtBtB,CAsBqC,SAtBrC,EAsBgD,KAtBhD,CAAA,CAAA;;;;;ADIF;AAaa,KElBD,cAAA,GAAiB,OAAA,CAAQ,OFkBO,GAAA;;;;AC7BkB;;EAM5D,WAAA,CAAA,ECWc,oBDXd,GAAA,SAAA;CAAgB;;AAAgB;;AAMhC,KCWU,mBDXV,CAAA,kBCWgD,kBDXhD,CAAA,GAAA;EADiE,QAAA,ECavD,SDbuD;EAAgB,IAAA,ECc3E,aDd2E,EAAA;EAO9E,iBAAA,CAAe,ECQE,4BDRF,GAAA,SAAA;EAAmB,MAAA,CAAA,ECS5B,MDT4B,GAAA,SAAA;CAAkC;;;AAAD;AAMpD,cCSP,eDTO,CAAA,kBCS2B,kBDT3B,CAAA,CAAA;EACgB,iBAAA,QAAA;EAApB,iBAAA,UAAA;EACI,iBAAA,MAAA;EAAhB,QAAA,WAAA,CAAA;EAA2B;;AAK/B;;;;;;;;EAGuB,OAAA,MAAA,CAAA,kBCgBW,kBDhBX,CAAA,CAAA;IAAA,QAAA;IAAA,IAAA;IAAA,iBAAA;IAAA;EAAA,CAAA,ECqBlB,mBDrBkB,CCqBE,SDrBF,CAAA,CAAA,ECqBe,MDrBf,CCqBsB,MDrBtB,CCqB6B,eDrB7B,CCqB6C,SDrB7C,CAAA,ECqByD,cDrBzD,CAAA,CAAA;;;;ACvBvB;AAYA;;;;;;;AAUA;;;EAkBI,OAAA,CAAA,cA4BoB,mBA5BpB,CA4BwC,SA5BxC,CAAA,CAAA,CAAA,aAAA,EA6Be,KA7Bf,EAAA,OAAA,EA8BS,yBA9BT,CA8BmC,SA9BnC,EA8B8C,KA9B9C,CAAA,EAAA,OAAA,CAAA,EA+BU,cA/BV,CAAA,EAgCC,MAhCD,CAgCQ,MAhCR,CAAA,IAAA,EAgCqB,cAhCrB,GAgCsC,sBAhCtC,CAAA,CAAA;EACA;;;EAGqB,KAAA,CAAA,CAAA,EAwHd,MAxHc,CAwHP,MAxHO,CAAA,IAAA,EAwHM,cAxHN,CAAA,CAAA;EAApB,QAAA,sBAAA"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Logger } from "@amqp-contract/core";
|
|
2
2
|
import { Future, Result } from "@swan-io/boxed";
|
|
3
3
|
import { AmqpConnectionManagerOptions, ConnectionUrl } from "amqp-connection-manager";
|
|
4
|
-
import { ContractDefinition, InferPublisherNames, PublisherDefinition } from "@amqp-contract/contract";
|
|
4
|
+
import { CompressionAlgorithm, ContractDefinition, InferPublisherNames, PublisherDefinition } from "@amqp-contract/contract";
|
|
5
5
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
6
6
|
import { Options } from "amqplib";
|
|
7
7
|
|
|
@@ -52,6 +52,17 @@ type InferPublisher<TContract extends ContractDefinition, TName extends InferPub
|
|
|
52
52
|
type ClientInferPublisherInput<TContract extends ContractDefinition, TName extends InferPublisherNames<TContract>> = PublisherInferInput<InferPublisher<TContract, TName>>;
|
|
53
53
|
//#endregion
|
|
54
54
|
//#region src/client.d.ts
|
|
55
|
+
/**
|
|
56
|
+
* Publish options that extend amqplib's Options.Publish with optional compression support.
|
|
57
|
+
*/
|
|
58
|
+
type PublishOptions = Options.Publish & {
|
|
59
|
+
/**
|
|
60
|
+
* Optional compression algorithm to use for the message payload.
|
|
61
|
+
* When specified, the message will be compressed using the chosen algorithm
|
|
62
|
+
* and the contentEncoding header will be set automatically.
|
|
63
|
+
*/
|
|
64
|
+
compression?: CompressionAlgorithm | undefined;
|
|
65
|
+
};
|
|
55
66
|
/**
|
|
56
67
|
* Options for creating a client
|
|
57
68
|
*/
|
|
@@ -87,9 +98,19 @@ declare class TypedAmqpClient<TContract extends ContractDefinition> {
|
|
|
87
98
|
}: CreateClientOptions<TContract>): Future<Result<TypedAmqpClient<TContract>, TechnicalError>>;
|
|
88
99
|
/**
|
|
89
100
|
* Publish a message using a defined publisher
|
|
90
|
-
*
|
|
101
|
+
*
|
|
102
|
+
* @param publisherName - The name of the publisher to use
|
|
103
|
+
* @param message - The message to publish
|
|
104
|
+
* @param options - Optional publish options including compression, headers, priority, etc.
|
|
105
|
+
*
|
|
106
|
+
* @remarks
|
|
107
|
+
* If `options.compression` is specified, the message will be compressed before publishing
|
|
108
|
+
* and the `contentEncoding` property will be set automatically. Any `contentEncoding`
|
|
109
|
+
* value already in options will be overwritten by the compression algorithm.
|
|
110
|
+
*
|
|
111
|
+
* @returns Result.Ok(void) on success, or Result.Error with specific error on failure
|
|
91
112
|
*/
|
|
92
|
-
publish<TName extends InferPublisherNames<TContract>>(publisherName: TName, message: ClientInferPublisherInput<TContract, TName>, options?:
|
|
113
|
+
publish<TName extends InferPublisherNames<TContract>>(publisherName: TName, message: ClientInferPublisherInput<TContract, TName>, options?: PublishOptions): Future<Result<void, TechnicalError | MessageValidationError>>;
|
|
93
114
|
/**
|
|
94
115
|
* Close the channel and connection
|
|
95
116
|
*/
|
|
@@ -97,5 +118,5 @@ declare class TypedAmqpClient<TContract extends ContractDefinition> {
|
|
|
97
118
|
private waitForConnectionReady;
|
|
98
119
|
}
|
|
99
120
|
//#endregion
|
|
100
|
-
export { type ClientInferPublisherInput, type CreateClientOptions, MessageValidationError, TechnicalError, TypedAmqpClient };
|
|
121
|
+
export { type ClientInferPublisherInput, type CreateClientOptions, MessageValidationError, type PublishOptions, TechnicalError, TypedAmqpClient };
|
|
101
122
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/errors.ts","../src/types.ts","../src/client.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;uBAGe,WAAA,SAAoB,KAAA;;;;;;AAkBnC;AAaa,cAbA,cAAA,SAAuB,WAAA,CAamB;;;;AC7BO;;;AAM5C,cDuBL,sBAAA,SAA+B,WAAA,CCvB1B;EAAgB,SAAA,aAAA,EAAA,MAAA;EAK7B,SAAA,MAAA,EAAA,OAAmB;EAAoB,WAAA,CAAA,aAAA,EAAA,MAAA,EAAA,MAAA,EAAA,OAAA;;;;;;;KANvC,iCAAiC,oBACpC,gBAAgB;;;;ADUlB,KCLK,mBDKuB,CAAA,mBCLgB,mBDKG,CAAA,GCLoB,gBDKpB,CCJ7C,UDI6C,CAAA,SAAA,CAAA,CAAA,SAAA,CAAA,CAAA;AAa/C;;;KCXK,kCAAkC,sBAAsB,YAAY;AAlBX;;;KAuBzD,cAjBa,CAAA,kBAkBE,kBAlBF,EAAA,cAmBF,mBAnBE,CAmBkB,SAnBlB,CAAA,CAAA,GAoBd,eApBc,CAoBE,SApBF,CAAA,CAoBa,KApBb,CAAA;;AAAgB;;AAMhC,KAmBU,yBAnBV,CAAA,kBAoBkB,kBApBlB,EAAA,cAqBc,mBArBd,CAqBkC,SArBlC,CAAA,CAAA,GAsBE,mBAtBF,CAsBsB,cAtBtB,CAsBqC,SAtBrC,EAsBgD,KAtBhD,CAAA,CAAA;;;;;ADIF;AAaa,
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/errors.ts","../src/types.ts","../src/client.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;uBAGe,WAAA,SAAoB,KAAA;;;;;;AAkBnC;AAaa,cAbA,cAAA,SAAuB,WAAA,CAamB;;;;AC7BO;;;AAM5C,cDuBL,sBAAA,SAA+B,WAAA,CCvB1B;EAAgB,SAAA,aAAA,EAAA,MAAA;EAK7B,SAAA,MAAA,EAAA,OAAmB;EAAoB,WAAA,CAAA,aAAA,EAAA,MAAA,EAAA,MAAA,EAAA,OAAA;;;;;;;KANvC,iCAAiC,oBACpC,gBAAgB;;;;ADUlB,KCLK,mBDKuB,CAAA,mBCLgB,mBDKG,CAAA,GCLoB,gBDKpB,CCJ7C,UDI6C,CAAA,SAAA,CAAA,CAAA,SAAA,CAAA,CAAA;AAa/C;;;KCXK,kCAAkC,sBAAsB,YAAY;AAlBX;;;KAuBzD,cAjBa,CAAA,kBAkBE,kBAlBF,EAAA,cAmBF,mBAnBE,CAmBkB,SAnBlB,CAAA,CAAA,GAoBd,eApBc,CAoBE,SApBF,CAAA,CAoBa,KApBb,CAAA;;AAAgB;;AAMhC,KAmBU,yBAnBV,CAAA,kBAoBkB,kBApBlB,EAAA,cAqBc,mBArBd,CAqBkC,SArBlC,CAAA,CAAA,GAsBE,mBAtBF,CAsBsB,cAtBtB,CAsBqC,SAtBrC,EAsBgD,KAtBhD,CAAA,CAAA;;;;;ADIF;AAaa,KElBD,cAAA,GAAiB,OAAA,CAAQ,OFkBO,GAAA;;;;AC7BkB;;EAM5D,WAAA,CAAA,ECWc,oBDXd,GAAA,SAAA;CAAgB;;AAAgB;;AAMhC,KCWU,mBDXV,CAAA,kBCWgD,kBDXhD,CAAA,GAAA;EADiE,QAAA,ECavD,SDbuD;EAAgB,IAAA,ECc3E,aDd2E,EAAA;EAO9E,iBAAA,CAAe,ECQE,4BDRF,GAAA,SAAA;EAAmB,MAAA,CAAA,ECS5B,MDT4B,GAAA,SAAA;CAAkC;;;AAAD;AAMpD,cCSP,eDTO,CAAA,kBCS2B,kBDT3B,CAAA,CAAA;EACgB,iBAAA,QAAA;EAApB,iBAAA,UAAA;EACI,iBAAA,MAAA;EAAhB,QAAA,WAAA,CAAA;EAA2B;;AAK/B;;;;;;;;EAGuB,OAAA,MAAA,CAAA,kBCgBW,kBDhBX,CAAA,CAAA;IAAA,QAAA;IAAA,IAAA;IAAA,iBAAA;IAAA;EAAA,CAAA,ECqBlB,mBDrBkB,CCqBE,SDrBF,CAAA,CAAA,ECqBe,MDrBf,CCqBsB,MDrBtB,CCqB6B,eDrB7B,CCqB6C,SDrB7C,CAAA,ECqByD,cDrBzD,CAAA,CAAA;;;;ACvBvB;AAYA;;;;;;;AAUA;;;EAkBI,OAAA,CAAA,cA4BoB,mBA5BpB,CA4BwC,SA5BxC,CAAA,CAAA,CAAA,aAAA,EA6Be,KA7Bf,EAAA,OAAA,EA8BS,yBA9BT,CA8BmC,SA9BnC,EA8B8C,KA9B9C,CAAA,EAAA,OAAA,CAAA,EA+BU,cA/BV,CAAA,EAgCC,MAhCD,CAgCQ,MAhCR,CAAA,IAAA,EAgCqB,cAhCrB,GAgCsC,sBAhCtC,CAAA,CAAA;EACA;;;EAGqB,KAAA,CAAA,CAAA,EAwHd,MAxHc,CAwHP,MAxHO,CAAA,IAAA,EAwHM,cAxHN,CAAA,CAAA;EAApB,QAAA,sBAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { AmqpClient } from "@amqp-contract/core";
|
|
2
2
|
import { Future, Result } from "@swan-io/boxed";
|
|
3
|
+
import { deflate, gzip } from "node:zlib";
|
|
4
|
+
import { match } from "ts-pattern";
|
|
5
|
+
import { promisify } from "node:util";
|
|
3
6
|
|
|
4
7
|
//#region src/errors.ts
|
|
5
8
|
/**
|
|
@@ -36,6 +39,24 @@ var MessageValidationError = class extends ClientError {
|
|
|
36
39
|
}
|
|
37
40
|
};
|
|
38
41
|
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region src/compression.ts
|
|
44
|
+
const gzipAsync = promisify(gzip);
|
|
45
|
+
const deflateAsync = promisify(deflate);
|
|
46
|
+
/**
|
|
47
|
+
* Compress a buffer using the specified compression algorithm.
|
|
48
|
+
*
|
|
49
|
+
* @param buffer - The buffer to compress
|
|
50
|
+
* @param algorithm - The compression algorithm to use
|
|
51
|
+
* @returns A promise that resolves to the compressed buffer
|
|
52
|
+
* @throws Error if compression fails
|
|
53
|
+
*
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
async function compressBuffer(buffer, algorithm) {
|
|
57
|
+
return match(algorithm).with("gzip", () => gzipAsync(buffer)).with("deflate", () => deflateAsync(buffer)).exhaustive();
|
|
58
|
+
}
|
|
59
|
+
|
|
39
60
|
//#endregion
|
|
40
61
|
//#region src/client.ts
|
|
41
62
|
/**
|
|
@@ -66,7 +87,17 @@ var TypedAmqpClient = class TypedAmqpClient {
|
|
|
66
87
|
}
|
|
67
88
|
/**
|
|
68
89
|
* Publish a message using a defined publisher
|
|
69
|
-
*
|
|
90
|
+
*
|
|
91
|
+
* @param publisherName - The name of the publisher to use
|
|
92
|
+
* @param message - The message to publish
|
|
93
|
+
* @param options - Optional publish options including compression, headers, priority, etc.
|
|
94
|
+
*
|
|
95
|
+
* @remarks
|
|
96
|
+
* If `options.compression` is specified, the message will be compressed before publishing
|
|
97
|
+
* and the `contentEncoding` property will be set automatically. Any `contentEncoding`
|
|
98
|
+
* value already in options will be overwritten by the compression algorithm.
|
|
99
|
+
*
|
|
100
|
+
* @returns Result.Ok(void) on success, or Result.Error with specific error on failure
|
|
70
101
|
*/
|
|
71
102
|
publish(publisherName, message, options) {
|
|
72
103
|
const publishers = this.contract.publishers;
|
|
@@ -81,15 +112,26 @@ var TypedAmqpClient = class TypedAmqpClient {
|
|
|
81
112
|
});
|
|
82
113
|
};
|
|
83
114
|
const publishMessage = (validatedMessage) => {
|
|
84
|
-
|
|
115
|
+
const { compression, ...restOptions } = options ?? {};
|
|
116
|
+
const publishOptions = { ...restOptions };
|
|
117
|
+
const preparePayload = () => {
|
|
118
|
+
if (compression) {
|
|
119
|
+
const messageBuffer = Buffer.from(JSON.stringify(validatedMessage));
|
|
120
|
+
publishOptions.contentEncoding = compression;
|
|
121
|
+
return Future.fromPromise(compressBuffer(messageBuffer, compression)).mapError((error) => new TechnicalError(`Failed to compress message`, error)).map((compressedBuffer) => Result.Ok(compressedBuffer));
|
|
122
|
+
}
|
|
123
|
+
return Future.value(Result.Ok(validatedMessage));
|
|
124
|
+
};
|
|
125
|
+
return preparePayload().flatMapOk((payload) => Future.fromPromise(this.amqpClient.channel.publish(publisher.exchange.name, publisher.routingKey ?? "", payload, publishOptions)).mapError((error) => new TechnicalError(`Failed to publish message`, error)).mapOkToResult((published) => {
|
|
85
126
|
if (!published) return Result.Error(new TechnicalError(`Failed to publish message for publisher "${String(publisherName)}": Channel rejected the message (buffer full or other channel issue)`));
|
|
86
127
|
this.logger?.info("Message published successfully", {
|
|
87
128
|
publisherName: String(publisherName),
|
|
88
129
|
exchange: publisher.exchange.name,
|
|
89
|
-
routingKey: publisher.routingKey
|
|
130
|
+
routingKey: publisher.routingKey,
|
|
131
|
+
compressed: !!compression
|
|
90
132
|
});
|
|
91
133
|
return Result.Ok(void 0);
|
|
92
|
-
});
|
|
134
|
+
}));
|
|
93
135
|
};
|
|
94
136
|
return validateMessage().flatMapOk((validatedMessage) => publishMessage(validatedMessage));
|
|
95
137
|
}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["cause?: unknown","publisherName: string","issues: unknown","contract: TContract","amqpClient: AmqpClient","logger?: Logger"],"sources":["../src/errors.ts","../src/client.ts"],"sourcesContent":["/**\n * Base error class for client errors\n */\nabstract class ClientError extends Error {\n protected constructor(message: string) {\n super(message);\n this.name = \"ClientError\";\n // Node.js specific stack trace capture\n const ErrorConstructor = Error as unknown as {\n captureStackTrace?: (target: object, constructor: Function) => void;\n };\n if (typeof ErrorConstructor.captureStackTrace === \"function\") {\n ErrorConstructor.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Error for technical/runtime failures that cannot be prevented by TypeScript\n * This includes validation failures and AMQP channel issues\n */\nexport class TechnicalError extends ClientError {\n constructor(\n message: string,\n public override readonly cause?: unknown,\n ) {\n super(message);\n this.name = \"TechnicalError\";\n }\n}\n\n/**\n * Error thrown when message validation fails\n */\nexport class MessageValidationError extends ClientError {\n constructor(\n public readonly publisherName: string,\n public readonly issues: unknown,\n ) {\n super(`Message validation failed for publisher \"${publisherName}\"`);\n this.name = \"MessageValidationError\";\n }\n}\n","import { AmqpClient, type Logger } from \"@amqp-contract/core\";\nimport type { AmqpConnectionManagerOptions, ConnectionUrl } from \"amqp-connection-manager\";\nimport type { ContractDefinition, InferPublisherNames } from \"@amqp-contract/contract\";\nimport { Future, Result } from \"@swan-io/boxed\";\nimport { MessageValidationError, TechnicalError } from \"./errors.js\";\nimport type { ClientInferPublisherInput } from \"./types.js\";\nimport type { Options } from \"amqplib\";\n\n/**\n * Options for creating a client\n */\nexport type CreateClientOptions<TContract extends ContractDefinition> = {\n contract: TContract;\n urls: ConnectionUrl[];\n connectionOptions?: AmqpConnectionManagerOptions | undefined;\n logger?: Logger | undefined;\n};\n\n/**\n * Type-safe AMQP client for publishing messages\n */\nexport class TypedAmqpClient<TContract extends ContractDefinition> {\n private constructor(\n private readonly contract: TContract,\n private readonly amqpClient: AmqpClient,\n private readonly logger?: Logger,\n ) {}\n\n /**\n * Create a type-safe AMQP client from a contract.\n *\n * Connection management (including automatic reconnection) is handled internally\n * by amqp-connection-manager via the {@link AmqpClient}. The client establishes\n * infrastructure asynchronously in the background once the connection is ready.\n *\n * Connections are automatically shared across clients with the same URLs and\n * connection options, following RabbitMQ best practices.\n */\n static create<TContract extends ContractDefinition>({\n contract,\n urls,\n connectionOptions,\n logger,\n }: CreateClientOptions<TContract>): Future<Result<TypedAmqpClient<TContract>, TechnicalError>> {\n const client = new TypedAmqpClient(\n contract,\n new AmqpClient(contract, { urls, connectionOptions }),\n logger,\n );\n\n return client.waitForConnectionReady().mapOk(() => client);\n }\n\n /**\n * Publish a message using a defined publisher\n * Returns Result.Ok(true) on success, or Result.Error with specific error on failure\n */\n publish<TName extends InferPublisherNames<TContract>>(\n publisherName: TName,\n message: ClientInferPublisherInput<TContract, TName>,\n options?: Options.Publish,\n ): Future<Result<void, TechnicalError | MessageValidationError>> {\n const publishers = this.contract.publishers;\n if (!publishers) {\n return Future.value(Result.Error(new TechnicalError(\"No publishers defined in contract\")));\n }\n\n const publisher = publishers[publisherName as string];\n if (!publisher) {\n return Future.value(\n Result.Error(\n new TechnicalError(`Publisher \"${String(publisherName)}\" not found in contract`),\n ),\n );\n }\n\n const validateMessage = () => {\n const validationResult = publisher.message.payload[\"~standard\"].validate(message);\n return Future.fromPromise(\n validationResult instanceof Promise ? validationResult : Promise.resolve(validationResult),\n )\n .mapError((error) => new TechnicalError(`Validation failed`, error))\n .mapOkToResult((validation) => {\n if (validation.issues) {\n return Result.Error(\n new MessageValidationError(String(publisherName), validation.issues),\n );\n }\n\n return Result.Ok(validation.value);\n });\n };\n\n const publishMessage = (validatedMessage: unknown): Future<Result<void, TechnicalError>> => {\n return Future.fromPromise(\n this.amqpClient.channel.publish(\n publisher.exchange.name,\n publisher.routingKey ?? \"\",\n validatedMessage,\n options,\n ),\n )\n .mapError((error) => new TechnicalError(`Failed to publish message`, error))\n .mapOkToResult((published) => {\n if (!published) {\n return Result.Error(\n new TechnicalError(\n `Failed to publish message for publisher \"${String(publisherName)}\": Channel rejected the message (buffer full or other channel issue)`,\n ),\n );\n }\n\n this.logger?.info(\"Message published successfully\", {\n publisherName: String(publisherName),\n exchange: publisher.exchange.name,\n routingKey: publisher.routingKey,\n });\n\n return Result.Ok(undefined);\n });\n };\n\n // Validate message using schema\n return validateMessage().flatMapOk((validatedMessage) => publishMessage(validatedMessage));\n }\n\n /**\n * Close the channel and connection\n */\n close(): Future<Result<void, TechnicalError>> {\n return Future.fromPromise(this.amqpClient.close())\n .mapError((error) => new TechnicalError(\"Failed to close AMQP connection\", error))\n .mapOk(() => undefined);\n }\n\n private waitForConnectionReady(): Future<Result<void, TechnicalError>> {\n return Future.fromPromise(this.amqpClient.channel.waitForConnect()).mapError(\n (error) => new TechnicalError(\"Failed to wait for connection ready\", error),\n );\n }\n}\n"],"mappings":";;;;;;;AAGA,IAAe,cAAf,cAAmC,MAAM;CACvC,AAAU,YAAY,SAAiB;AACrC,QAAM,QAAQ;AACd,OAAK,OAAO;EAEZ,MAAM,mBAAmB;AAGzB,MAAI,OAAO,iBAAiB,sBAAsB,WAChD,kBAAiB,kBAAkB,MAAM,KAAK,YAAY;;;;;;;AAShE,IAAa,iBAAb,cAAoC,YAAY;CAC9C,YACE,SACA,AAAyBA,OACzB;AACA,QAAM,QAAQ;EAFW;AAGzB,OAAK,OAAO;;;;;;AAOhB,IAAa,yBAAb,cAA4C,YAAY;CACtD,YACE,AAAgBC,eAChB,AAAgBC,QAChB;AACA,QAAM,4CAA4C,cAAc,GAAG;EAHnD;EACA;AAGhB,OAAK,OAAO;;;;;;;;;ACnBhB,IAAa,kBAAb,MAAa,gBAAsD;CACjE,AAAQ,YACN,AAAiBC,UACjB,AAAiBC,YACjB,AAAiBC,QACjB;EAHiB;EACA;EACA;;;;;;;;;;;;CAanB,OAAO,OAA6C,EAClD,UACA,MACA,mBACA,UAC6F;EAC7F,MAAM,SAAS,IAAI,gBACjB,UACA,IAAI,WAAW,UAAU;GAAE;GAAM;GAAmB,CAAC,EACrD,OACD;AAED,SAAO,OAAO,wBAAwB,CAAC,YAAY,OAAO;;;;;;CAO5D,QACE,eACA,SACA,SAC+D;EAC/D,MAAM,aAAa,KAAK,SAAS;AACjC,MAAI,CAAC,WACH,QAAO,OAAO,MAAM,OAAO,MAAM,IAAI,eAAe,oCAAoC,CAAC,CAAC;EAG5F,MAAM,YAAY,WAAW;AAC7B,MAAI,CAAC,UACH,QAAO,OAAO,MACZ,OAAO,MACL,IAAI,eAAe,cAAc,OAAO,cAAc,CAAC,yBAAyB,CACjF,CACF;EAGH,MAAM,wBAAwB;GAC5B,MAAM,mBAAmB,UAAU,QAAQ,QAAQ,aAAa,SAAS,QAAQ;AACjF,UAAO,OAAO,YACZ,4BAA4B,UAAU,mBAAmB,QAAQ,QAAQ,iBAAiB,CAC3F,CACE,UAAU,UAAU,IAAI,eAAe,qBAAqB,MAAM,CAAC,CACnE,eAAe,eAAe;AAC7B,QAAI,WAAW,OACb,QAAO,OAAO,MACZ,IAAI,uBAAuB,OAAO,cAAc,EAAE,WAAW,OAAO,CACrE;AAGH,WAAO,OAAO,GAAG,WAAW,MAAM;KAClC;;EAGN,MAAM,kBAAkB,qBAAoE;AAC1F,UAAO,OAAO,YACZ,KAAK,WAAW,QAAQ,QACtB,UAAU,SAAS,MACnB,UAAU,cAAc,IACxB,kBACA,QACD,CACF,CACE,UAAU,UAAU,IAAI,eAAe,6BAA6B,MAAM,CAAC,CAC3E,eAAe,cAAc;AAC5B,QAAI,CAAC,UACH,QAAO,OAAO,MACZ,IAAI,eACF,4CAA4C,OAAO,cAAc,CAAC,sEACnE,CACF;AAGH,SAAK,QAAQ,KAAK,kCAAkC;KAClD,eAAe,OAAO,cAAc;KACpC,UAAU,UAAU,SAAS;KAC7B,YAAY,UAAU;KACvB,CAAC;AAEF,WAAO,OAAO,GAAG,OAAU;KAC3B;;AAIN,SAAO,iBAAiB,CAAC,WAAW,qBAAqB,eAAe,iBAAiB,CAAC;;;;;CAM5F,QAA8C;AAC5C,SAAO,OAAO,YAAY,KAAK,WAAW,OAAO,CAAC,CAC/C,UAAU,UAAU,IAAI,eAAe,mCAAmC,MAAM,CAAC,CACjF,YAAY,OAAU;;CAG3B,AAAQ,yBAA+D;AACrE,SAAO,OAAO,YAAY,KAAK,WAAW,QAAQ,gBAAgB,CAAC,CAAC,UACjE,UAAU,IAAI,eAAe,uCAAuC,MAAM,CAC5E"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/errors.ts","../src/compression.ts","../src/client.ts"],"sourcesContent":["/**\n * Base error class for client errors\n */\nabstract class ClientError extends Error {\n protected constructor(message: string) {\n super(message);\n this.name = \"ClientError\";\n // Node.js specific stack trace capture\n const ErrorConstructor = Error as unknown as {\n captureStackTrace?: (target: object, constructor: Function) => void;\n };\n if (typeof ErrorConstructor.captureStackTrace === \"function\") {\n ErrorConstructor.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Error for technical/runtime failures that cannot be prevented by TypeScript\n * This includes validation failures and AMQP channel issues\n */\nexport class TechnicalError extends ClientError {\n constructor(\n message: string,\n public override readonly cause?: unknown,\n ) {\n super(message);\n this.name = \"TechnicalError\";\n }\n}\n\n/**\n * Error thrown when message validation fails\n */\nexport class MessageValidationError extends ClientError {\n constructor(\n public readonly publisherName: string,\n public readonly issues: unknown,\n ) {\n super(`Message validation failed for publisher \"${publisherName}\"`);\n this.name = \"MessageValidationError\";\n }\n}\n","import { deflate, gzip } from \"node:zlib\";\nimport type { CompressionAlgorithm } from \"@amqp-contract/contract\";\nimport { match } from \"ts-pattern\";\nimport { promisify } from \"node:util\";\n\nconst gzipAsync = promisify(gzip);\nconst deflateAsync = promisify(deflate);\n\n/**\n * Compress a buffer using the specified compression algorithm.\n *\n * @param buffer - The buffer to compress\n * @param algorithm - The compression algorithm to use\n * @returns A promise that resolves to the compressed buffer\n * @throws Error if compression fails\n *\n * @internal\n */\nexport async function compressBuffer(\n buffer: Buffer,\n algorithm: CompressionAlgorithm,\n): Promise<Buffer> {\n return match(algorithm)\n .with(\"gzip\", () => gzipAsync(buffer))\n .with(\"deflate\", () => deflateAsync(buffer))\n .exhaustive();\n}\n","import { AmqpClient, type Logger } from \"@amqp-contract/core\";\nimport type { AmqpConnectionManagerOptions, ConnectionUrl } from \"amqp-connection-manager\";\nimport type {\n CompressionAlgorithm,\n ContractDefinition,\n InferPublisherNames,\n} from \"@amqp-contract/contract\";\nimport { Future, Result } from \"@swan-io/boxed\";\nimport { MessageValidationError, TechnicalError } from \"./errors.js\";\nimport type { ClientInferPublisherInput } from \"./types.js\";\nimport type { Options } from \"amqplib\";\nimport { compressBuffer } from \"./compression.js\";\n\n/**\n * Publish options that extend amqplib's Options.Publish with optional compression support.\n */\nexport type PublishOptions = Options.Publish & {\n /**\n * Optional compression algorithm to use for the message payload.\n * When specified, the message will be compressed using the chosen algorithm\n * and the contentEncoding header will be set automatically.\n */\n compression?: CompressionAlgorithm | undefined;\n};\n\n/**\n * Options for creating a client\n */\nexport type CreateClientOptions<TContract extends ContractDefinition> = {\n contract: TContract;\n urls: ConnectionUrl[];\n connectionOptions?: AmqpConnectionManagerOptions | undefined;\n logger?: Logger | undefined;\n};\n\n/**\n * Type-safe AMQP client for publishing messages\n */\nexport class TypedAmqpClient<TContract extends ContractDefinition> {\n private constructor(\n private readonly contract: TContract,\n private readonly amqpClient: AmqpClient,\n private readonly logger?: Logger,\n ) {}\n\n /**\n * Create a type-safe AMQP client from a contract.\n *\n * Connection management (including automatic reconnection) is handled internally\n * by amqp-connection-manager via the {@link AmqpClient}. The client establishes\n * infrastructure asynchronously in the background once the connection is ready.\n *\n * Connections are automatically shared across clients with the same URLs and\n * connection options, following RabbitMQ best practices.\n */\n static create<TContract extends ContractDefinition>({\n contract,\n urls,\n connectionOptions,\n logger,\n }: CreateClientOptions<TContract>): Future<Result<TypedAmqpClient<TContract>, TechnicalError>> {\n const client = new TypedAmqpClient(\n contract,\n new AmqpClient(contract, { urls, connectionOptions }),\n logger,\n );\n\n return client.waitForConnectionReady().mapOk(() => client);\n }\n\n /**\n * Publish a message using a defined publisher\n *\n * @param publisherName - The name of the publisher to use\n * @param message - The message to publish\n * @param options - Optional publish options including compression, headers, priority, etc.\n *\n * @remarks\n * If `options.compression` is specified, the message will be compressed before publishing\n * and the `contentEncoding` property will be set automatically. Any `contentEncoding`\n * value already in options will be overwritten by the compression algorithm.\n *\n * @returns Result.Ok(void) on success, or Result.Error with specific error on failure\n */\n publish<TName extends InferPublisherNames<TContract>>(\n publisherName: TName,\n message: ClientInferPublisherInput<TContract, TName>,\n options?: PublishOptions,\n ): Future<Result<void, TechnicalError | MessageValidationError>> {\n const publishers = this.contract.publishers;\n if (!publishers) {\n return Future.value(Result.Error(new TechnicalError(\"No publishers defined in contract\")));\n }\n\n const publisher = publishers[publisherName as string];\n if (!publisher) {\n return Future.value(\n Result.Error(\n new TechnicalError(`Publisher \"${String(publisherName)}\" not found in contract`),\n ),\n );\n }\n\n const validateMessage = () => {\n const validationResult = publisher.message.payload[\"~standard\"].validate(message);\n return Future.fromPromise(\n validationResult instanceof Promise ? validationResult : Promise.resolve(validationResult),\n )\n .mapError((error) => new TechnicalError(`Validation failed`, error))\n .mapOkToResult((validation) => {\n if (validation.issues) {\n return Result.Error(\n new MessageValidationError(String(publisherName), validation.issues),\n );\n }\n\n return Result.Ok(validation.value);\n });\n };\n\n const publishMessage = (validatedMessage: unknown): Future<Result<void, TechnicalError>> => {\n // Extract compression from options and create publish options without it\n const { compression, ...restOptions } = options ?? {};\n const publishOptions: Options.Publish = { ...restOptions };\n\n // Prepare payload and options based on compression configuration\n const preparePayload = (): Future<Result<Buffer | unknown, TechnicalError>> => {\n if (compression) {\n // Compress the message payload\n const messageBuffer = Buffer.from(JSON.stringify(validatedMessage));\n publishOptions.contentEncoding = compression;\n\n return Future.fromPromise(compressBuffer(messageBuffer, compression))\n .mapError((error) => new TechnicalError(`Failed to compress message`, error))\n .map((compressedBuffer) => Result.Ok(compressedBuffer));\n }\n\n // No compression: use the channel's built-in JSON serialization\n return Future.value(Result.Ok(validatedMessage));\n };\n\n // Publish the prepared payload\n return preparePayload().flatMapOk((payload) =>\n Future.fromPromise(\n this.amqpClient.channel.publish(\n publisher.exchange.name,\n publisher.routingKey ?? \"\",\n payload,\n publishOptions,\n ),\n )\n .mapError((error) => new TechnicalError(`Failed to publish message`, error))\n .mapOkToResult((published) => {\n if (!published) {\n return Result.Error(\n new TechnicalError(\n `Failed to publish message for publisher \"${String(publisherName)}\": Channel rejected the message (buffer full or other channel issue)`,\n ),\n );\n }\n\n this.logger?.info(\"Message published successfully\", {\n publisherName: String(publisherName),\n exchange: publisher.exchange.name,\n routingKey: publisher.routingKey,\n compressed: !!compression,\n });\n\n return Result.Ok(undefined);\n }),\n );\n };\n\n // Validate message using schema\n return validateMessage().flatMapOk((validatedMessage) => publishMessage(validatedMessage));\n }\n\n /**\n * Close the channel and connection\n */\n close(): Future<Result<void, TechnicalError>> {\n return Future.fromPromise(this.amqpClient.close())\n .mapError((error) => new TechnicalError(\"Failed to close AMQP connection\", error))\n .mapOk(() => undefined);\n }\n\n private waitForConnectionReady(): Future<Result<void, TechnicalError>> {\n return Future.fromPromise(this.amqpClient.channel.waitForConnect()).mapError(\n (error) => new TechnicalError(\"Failed to wait for connection ready\", error),\n );\n }\n}\n"],"mappings":";;;;;;;;;;AAGA,IAAe,cAAf,cAAmC,MAAM;CACvC,AAAU,YAAY,SAAiB;AACrC,QAAM,QAAQ;AACd,OAAK,OAAO;EAEZ,MAAM,mBAAmB;AAGzB,MAAI,OAAO,iBAAiB,sBAAsB,WAChD,kBAAiB,kBAAkB,MAAM,KAAK,YAAY;;;;;;;AAShE,IAAa,iBAAb,cAAoC,YAAY;CAC9C,YACE,SACA,AAAyB,OACzB;AACA,QAAM,QAAQ;EAFW;AAGzB,OAAK,OAAO;;;;;;AAOhB,IAAa,yBAAb,cAA4C,YAAY;CACtD,YACE,AAAgB,eAChB,AAAgB,QAChB;AACA,QAAM,4CAA4C,cAAc,GAAG;EAHnD;EACA;AAGhB,OAAK,OAAO;;;;;;ACnChB,MAAM,YAAY,UAAU,KAAK;AACjC,MAAM,eAAe,UAAU,QAAQ;;;;;;;;;;;AAYvC,eAAsB,eACpB,QACA,WACiB;AACjB,QAAO,MAAM,UAAU,CACpB,KAAK,cAAc,UAAU,OAAO,CAAC,CACrC,KAAK,iBAAiB,aAAa,OAAO,CAAC,CAC3C,YAAY;;;;;;;;ACajB,IAAa,kBAAb,MAAa,gBAAsD;CACjE,AAAQ,YACN,AAAiB,UACjB,AAAiB,YACjB,AAAiB,QACjB;EAHiB;EACA;EACA;;;;;;;;;;;;CAanB,OAAO,OAA6C,EAClD,UACA,MACA,mBACA,UAC6F;EAC7F,MAAM,SAAS,IAAI,gBACjB,UACA,IAAI,WAAW,UAAU;GAAE;GAAM;GAAmB,CAAC,EACrD,OACD;AAED,SAAO,OAAO,wBAAwB,CAAC,YAAY,OAAO;;;;;;;;;;;;;;;;CAiB5D,QACE,eACA,SACA,SAC+D;EAC/D,MAAM,aAAa,KAAK,SAAS;AACjC,MAAI,CAAC,WACH,QAAO,OAAO,MAAM,OAAO,MAAM,IAAI,eAAe,oCAAoC,CAAC,CAAC;EAG5F,MAAM,YAAY,WAAW;AAC7B,MAAI,CAAC,UACH,QAAO,OAAO,MACZ,OAAO,MACL,IAAI,eAAe,cAAc,OAAO,cAAc,CAAC,yBAAyB,CACjF,CACF;EAGH,MAAM,wBAAwB;GAC5B,MAAM,mBAAmB,UAAU,QAAQ,QAAQ,aAAa,SAAS,QAAQ;AACjF,UAAO,OAAO,YACZ,4BAA4B,UAAU,mBAAmB,QAAQ,QAAQ,iBAAiB,CAC3F,CACE,UAAU,UAAU,IAAI,eAAe,qBAAqB,MAAM,CAAC,CACnE,eAAe,eAAe;AAC7B,QAAI,WAAW,OACb,QAAO,OAAO,MACZ,IAAI,uBAAuB,OAAO,cAAc,EAAE,WAAW,OAAO,CACrE;AAGH,WAAO,OAAO,GAAG,WAAW,MAAM;KAClC;;EAGN,MAAM,kBAAkB,qBAAoE;GAE1F,MAAM,EAAE,aAAa,GAAG,gBAAgB,WAAW,EAAE;GACrD,MAAM,iBAAkC,EAAE,GAAG,aAAa;GAG1D,MAAM,uBAAyE;AAC7E,QAAI,aAAa;KAEf,MAAM,gBAAgB,OAAO,KAAK,KAAK,UAAU,iBAAiB,CAAC;AACnE,oBAAe,kBAAkB;AAEjC,YAAO,OAAO,YAAY,eAAe,eAAe,YAAY,CAAC,CAClE,UAAU,UAAU,IAAI,eAAe,8BAA8B,MAAM,CAAC,CAC5E,KAAK,qBAAqB,OAAO,GAAG,iBAAiB,CAAC;;AAI3D,WAAO,OAAO,MAAM,OAAO,GAAG,iBAAiB,CAAC;;AAIlD,UAAO,gBAAgB,CAAC,WAAW,YACjC,OAAO,YACL,KAAK,WAAW,QAAQ,QACtB,UAAU,SAAS,MACnB,UAAU,cAAc,IACxB,SACA,eACD,CACF,CACE,UAAU,UAAU,IAAI,eAAe,6BAA6B,MAAM,CAAC,CAC3E,eAAe,cAAc;AAC5B,QAAI,CAAC,UACH,QAAO,OAAO,MACZ,IAAI,eACF,4CAA4C,OAAO,cAAc,CAAC,sEACnE,CACF;AAGH,SAAK,QAAQ,KAAK,kCAAkC;KAClD,eAAe,OAAO,cAAc;KACpC,UAAU,UAAU,SAAS;KAC7B,YAAY,UAAU;KACtB,YAAY,CAAC,CAAC;KACf,CAAC;AAEF,WAAO,OAAO,GAAG,OAAU;KAC3B,CACL;;AAIH,SAAO,iBAAiB,CAAC,WAAW,qBAAqB,eAAe,iBAAiB,CAAC;;;;;CAM5F,QAA8C;AAC5C,SAAO,OAAO,YAAY,KAAK,WAAW,OAAO,CAAC,CAC/C,UAAU,UAAU,IAAI,eAAe,mCAAmC,MAAM,CAAC,CACjF,YAAY,OAAU;;CAG3B,AAAQ,yBAA+D;AACrE,SAAO,OAAO,YAAY,KAAK,WAAW,QAAQ,gBAAgB,CAAC,CAAC,UACjE,UAAU,IAAI,eAAe,uCAAuC,MAAM,CAC5E"}
|
package/docs/index.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
### MessageValidationError
|
|
10
10
|
|
|
11
|
-
Defined in: [packages/client/src/errors.ts:35](https://github.com/btravers/amqp-contract/blob/
|
|
11
|
+
Defined in: [packages/client/src/errors.ts:35](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/errors.ts#L35)
|
|
12
12
|
|
|
13
13
|
Error thrown when message validation fails
|
|
14
14
|
|
|
@@ -24,7 +24,7 @@ Error thrown when message validation fails
|
|
|
24
24
|
new MessageValidationError(publisherName, issues): MessageValidationError;
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
Defined in: [packages/client/src/errors.ts:36](https://github.com/btravers/amqp-contract/blob/
|
|
27
|
+
Defined in: [packages/client/src/errors.ts:36](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/errors.ts#L36)
|
|
28
28
|
|
|
29
29
|
###### Parameters
|
|
30
30
|
|
|
@@ -48,12 +48,12 @@ ClientError.constructor
|
|
|
48
48
|
| Property | Modifier | Type | Description | Inherited from | Defined in |
|
|
49
49
|
| ------ | ------ | ------ | ------ | ------ | ------ |
|
|
50
50
|
| <a id="cause"></a> `cause?` | `public` | `unknown` | - | `ClientError.cause` | node\_modules/.pnpm/typescript@5.9.3/node\_modules/typescript/lib/lib.es2022.error.d.ts:26 |
|
|
51
|
-
| <a id="issues"></a> `issues` | `readonly` | `unknown` | - | - | [packages/client/src/errors.ts:38](https://github.com/btravers/amqp-contract/blob/
|
|
51
|
+
| <a id="issues"></a> `issues` | `readonly` | `unknown` | - | - | [packages/client/src/errors.ts:38](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/errors.ts#L38) |
|
|
52
52
|
| <a id="message"></a> `message` | `public` | `string` | - | `ClientError.message` | node\_modules/.pnpm/typescript@5.9.3/node\_modules/typescript/lib/lib.es5.d.ts:1077 |
|
|
53
53
|
| <a id="name"></a> `name` | `public` | `string` | - | `ClientError.name` | node\_modules/.pnpm/typescript@5.9.3/node\_modules/typescript/lib/lib.es5.d.ts:1076 |
|
|
54
|
-
| <a id="publishername"></a> `publisherName` | `readonly` | `string` | - | - | [packages/client/src/errors.ts:37](https://github.com/btravers/amqp-contract/blob/
|
|
54
|
+
| <a id="publishername"></a> `publisherName` | `readonly` | `string` | - | - | [packages/client/src/errors.ts:37](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/errors.ts#L37) |
|
|
55
55
|
| <a id="stack"></a> `stack?` | `public` | `string` | - | `ClientError.stack` | node\_modules/.pnpm/typescript@5.9.3/node\_modules/typescript/lib/lib.es5.d.ts:1078 |
|
|
56
|
-
| <a id="stacktracelimit"></a> `stackTraceLimit` | `static` | `number` | The `Error.stackTraceLimit` property specifies the number of stack frames collected by a stack trace (whether generated by `new Error().stack` or `Error.captureStackTrace(obj)`). The default value is `10` but may be set to any valid JavaScript number. Changes will affect any stack trace captured _after_ the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. | `ClientError.stackTraceLimit` | node\_modules/.pnpm/@types+node@25.0.
|
|
56
|
+
| <a id="stacktracelimit"></a> `stackTraceLimit` | `static` | `number` | The `Error.stackTraceLimit` property specifies the number of stack frames collected by a stack trace (whether generated by `new Error().stack` or `Error.captureStackTrace(obj)`). The default value is `10` but may be set to any valid JavaScript number. Changes will affect any stack trace captured _after_ the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. | `ClientError.stackTraceLimit` | node\_modules/.pnpm/@types+node@25.0.5/node\_modules/@types/node/globals.d.ts:67 |
|
|
57
57
|
|
|
58
58
|
#### Methods
|
|
59
59
|
|
|
@@ -63,7 +63,7 @@ ClientError.constructor
|
|
|
63
63
|
static captureStackTrace(targetObject, constructorOpt?): void;
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
-
Defined in: node\_modules/.pnpm/@types+node@25.0.
|
|
66
|
+
Defined in: node\_modules/.pnpm/@types+node@25.0.5/node\_modules/@types/node/globals.d.ts:51
|
|
67
67
|
|
|
68
68
|
Creates a `.stack` property on `targetObject`, which when accessed returns
|
|
69
69
|
a string representing the location in the code at which
|
|
@@ -132,7 +132,7 @@ ClientError.captureStackTrace
|
|
|
132
132
|
static prepareStackTrace(err, stackTraces): any;
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
-
Defined in: node\_modules/.pnpm/@types+node@25.0.
|
|
135
|
+
Defined in: node\_modules/.pnpm/@types+node@25.0.5/node\_modules/@types/node/globals.d.ts:55
|
|
136
136
|
|
|
137
137
|
###### Parameters
|
|
138
138
|
|
|
@@ -159,7 +159,7 @@ ClientError.prepareStackTrace
|
|
|
159
159
|
|
|
160
160
|
### TechnicalError
|
|
161
161
|
|
|
162
|
-
Defined in: [packages/client/src/errors.ts:22](https://github.com/btravers/amqp-contract/blob/
|
|
162
|
+
Defined in: [packages/client/src/errors.ts:22](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/errors.ts#L22)
|
|
163
163
|
|
|
164
164
|
Error for technical/runtime failures that cannot be prevented by TypeScript
|
|
165
165
|
This includes validation failures and AMQP channel issues
|
|
@@ -176,7 +176,7 @@ This includes validation failures and AMQP channel issues
|
|
|
176
176
|
new TechnicalError(message, cause?): TechnicalError;
|
|
177
177
|
```
|
|
178
178
|
|
|
179
|
-
Defined in: [packages/client/src/errors.ts:23](https://github.com/btravers/amqp-contract/blob/
|
|
179
|
+
Defined in: [packages/client/src/errors.ts:23](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/errors.ts#L23)
|
|
180
180
|
|
|
181
181
|
###### Parameters
|
|
182
182
|
|
|
@@ -199,11 +199,11 @@ ClientError.constructor
|
|
|
199
199
|
|
|
200
200
|
| Property | Modifier | Type | Description | Inherited from | Defined in |
|
|
201
201
|
| ------ | ------ | ------ | ------ | ------ | ------ |
|
|
202
|
-
| <a id="cause-1"></a> `cause?` | `readonly` | `unknown` | - | `ClientError.cause` | [packages/client/src/errors.ts:25](https://github.com/btravers/amqp-contract/blob/
|
|
202
|
+
| <a id="cause-1"></a> `cause?` | `readonly` | `unknown` | - | `ClientError.cause` | [packages/client/src/errors.ts:25](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/errors.ts#L25) |
|
|
203
203
|
| <a id="message-1"></a> `message` | `public` | `string` | - | `ClientError.message` | node\_modules/.pnpm/typescript@5.9.3/node\_modules/typescript/lib/lib.es5.d.ts:1077 |
|
|
204
204
|
| <a id="name-1"></a> `name` | `public` | `string` | - | `ClientError.name` | node\_modules/.pnpm/typescript@5.9.3/node\_modules/typescript/lib/lib.es5.d.ts:1076 |
|
|
205
205
|
| <a id="stack-1"></a> `stack?` | `public` | `string` | - | `ClientError.stack` | node\_modules/.pnpm/typescript@5.9.3/node\_modules/typescript/lib/lib.es5.d.ts:1078 |
|
|
206
|
-
| <a id="stacktracelimit-1"></a> `stackTraceLimit` | `static` | `number` | The `Error.stackTraceLimit` property specifies the number of stack frames collected by a stack trace (whether generated by `new Error().stack` or `Error.captureStackTrace(obj)`). The default value is `10` but may be set to any valid JavaScript number. Changes will affect any stack trace captured _after_ the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. | `ClientError.stackTraceLimit` | node\_modules/.pnpm/@types+node@25.0.
|
|
206
|
+
| <a id="stacktracelimit-1"></a> `stackTraceLimit` | `static` | `number` | The `Error.stackTraceLimit` property specifies the number of stack frames collected by a stack trace (whether generated by `new Error().stack` or `Error.captureStackTrace(obj)`). The default value is `10` but may be set to any valid JavaScript number. Changes will affect any stack trace captured _after_ the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. | `ClientError.stackTraceLimit` | node\_modules/.pnpm/@types+node@25.0.5/node\_modules/@types/node/globals.d.ts:67 |
|
|
207
207
|
|
|
208
208
|
#### Methods
|
|
209
209
|
|
|
@@ -213,7 +213,7 @@ ClientError.constructor
|
|
|
213
213
|
static captureStackTrace(targetObject, constructorOpt?): void;
|
|
214
214
|
```
|
|
215
215
|
|
|
216
|
-
Defined in: node\_modules/.pnpm/@types+node@25.0.
|
|
216
|
+
Defined in: node\_modules/.pnpm/@types+node@25.0.5/node\_modules/@types/node/globals.d.ts:51
|
|
217
217
|
|
|
218
218
|
Creates a `.stack` property on `targetObject`, which when accessed returns
|
|
219
219
|
a string representing the location in the code at which
|
|
@@ -282,7 +282,7 @@ ClientError.captureStackTrace
|
|
|
282
282
|
static prepareStackTrace(err, stackTraces): any;
|
|
283
283
|
```
|
|
284
284
|
|
|
285
|
-
Defined in: node\_modules/.pnpm/@types+node@25.0.
|
|
285
|
+
Defined in: node\_modules/.pnpm/@types+node@25.0.5/node\_modules/@types/node/globals.d.ts:55
|
|
286
286
|
|
|
287
287
|
###### Parameters
|
|
288
288
|
|
|
@@ -309,7 +309,7 @@ ClientError.prepareStackTrace
|
|
|
309
309
|
|
|
310
310
|
### TypedAmqpClient
|
|
311
311
|
|
|
312
|
-
Defined in: [packages/client/src/client.ts:
|
|
312
|
+
Defined in: [packages/client/src/client.ts:39](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/client.ts#L39)
|
|
313
313
|
|
|
314
314
|
Type-safe AMQP client for publishing messages
|
|
315
315
|
|
|
@@ -327,7 +327,7 @@ Type-safe AMQP client for publishing messages
|
|
|
327
327
|
close(): Future<Result<void, TechnicalError>>;
|
|
328
328
|
```
|
|
329
329
|
|
|
330
|
-
Defined in: [packages/client/src/client.ts:
|
|
330
|
+
Defined in: [packages/client/src/client.ts:181](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/client.ts#L181)
|
|
331
331
|
|
|
332
332
|
Close the channel and connection
|
|
333
333
|
|
|
@@ -346,10 +346,9 @@ publish<TName>(
|
|
|
346
346
|
| MessageValidationError>>;
|
|
347
347
|
```
|
|
348
348
|
|
|
349
|
-
Defined in: [packages/client/src/client.ts:
|
|
349
|
+
Defined in: [packages/client/src/client.ts:85](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/client.ts#L85)
|
|
350
350
|
|
|
351
351
|
Publish a message using a defined publisher
|
|
352
|
-
Returns Result.Ok(true) on success, or Result.Error with specific error on failure
|
|
353
352
|
|
|
354
353
|
###### Type Parameters
|
|
355
354
|
|
|
@@ -359,11 +358,11 @@ Returns Result.Ok(true) on success, or Result.Error with specific error on failu
|
|
|
359
358
|
|
|
360
359
|
###### Parameters
|
|
361
360
|
|
|
362
|
-
| Parameter | Type |
|
|
363
|
-
| ------ | ------ |
|
|
364
|
-
| `publisherName` | `TName` |
|
|
365
|
-
| `message` | [`ClientInferPublisherInput`](#clientinferpublisherinput)\<`TContract`, `TName`\> |
|
|
366
|
-
| `options?` | `
|
|
361
|
+
| Parameter | Type | Description |
|
|
362
|
+
| ------ | ------ | ------ |
|
|
363
|
+
| `publisherName` | `TName` | The name of the publisher to use |
|
|
364
|
+
| `message` | [`ClientInferPublisherInput`](#clientinferpublisherinput)\<`TContract`, `TName`\> | The message to publish |
|
|
365
|
+
| `options?` | [`PublishOptions`](#publishoptions) | Optional publish options including compression, headers, priority, etc. |
|
|
367
366
|
|
|
368
367
|
###### Returns
|
|
369
368
|
|
|
@@ -371,13 +370,21 @@ Returns Result.Ok(true) on success, or Result.Error with specific error on failu
|
|
|
371
370
|
\| [`TechnicalError`](#technicalerror)
|
|
372
371
|
\| [`MessageValidationError`](#messagevalidationerror)\>\>
|
|
373
372
|
|
|
373
|
+
Result.Ok(void) on success, or Result.Error with specific error on failure
|
|
374
|
+
|
|
375
|
+
###### Remarks
|
|
376
|
+
|
|
377
|
+
If `options.compression` is specified, the message will be compressed before publishing
|
|
378
|
+
and the `contentEncoding` property will be set automatically. Any `contentEncoding`
|
|
379
|
+
value already in options will be overwritten by the compression algorithm.
|
|
380
|
+
|
|
374
381
|
##### create()
|
|
375
382
|
|
|
376
383
|
```ts
|
|
377
384
|
static create<TContract>(__namedParameters): Future<Result<TypedAmqpClient<TContract>, TechnicalError>>;
|
|
378
385
|
```
|
|
379
386
|
|
|
380
|
-
Defined in: [packages/client/src/client.ts:
|
|
387
|
+
Defined in: [packages/client/src/client.ts:56](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/client.ts#L56)
|
|
381
388
|
|
|
382
389
|
Create a type-safe AMQP client from a contract.
|
|
383
390
|
|
|
@@ -412,7 +419,7 @@ connection options, following RabbitMQ best practices.
|
|
|
412
419
|
type ClientInferPublisherInput<TContract, TName> = PublisherInferInput<InferPublisher<TContract, TName>>;
|
|
413
420
|
```
|
|
414
421
|
|
|
415
|
-
Defined in: [packages/client/src/types.ts:37](https://github.com/btravers/amqp-contract/blob/
|
|
422
|
+
Defined in: [packages/client/src/types.ts:37](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/types.ts#L37)
|
|
416
423
|
|
|
417
424
|
Infer publisher input type (message payload) for a specific publisher in a contract
|
|
418
425
|
|
|
@@ -431,7 +438,7 @@ Infer publisher input type (message payload) for a specific publisher in a contr
|
|
|
431
438
|
type CreateClientOptions<TContract> = object;
|
|
432
439
|
```
|
|
433
440
|
|
|
434
|
-
Defined in: [packages/client/src/client.ts:
|
|
441
|
+
Defined in: [packages/client/src/client.ts:29](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/client.ts#L29)
|
|
435
442
|
|
|
436
443
|
Options for creating a client
|
|
437
444
|
|
|
@@ -445,7 +452,25 @@ Options for creating a client
|
|
|
445
452
|
|
|
446
453
|
| Property | Type | Defined in |
|
|
447
454
|
| ------ | ------ | ------ |
|
|
448
|
-
| <a id="connectionoptions"></a> `connectionOptions?` | `AmqpConnectionManagerOptions` | [packages/client/src/client.ts:
|
|
449
|
-
| <a id="contract"></a> `contract` | `TContract` | [packages/client/src/client.ts:
|
|
450
|
-
| <a id="logger"></a> `logger?` | `Logger` | [packages/client/src/client.ts:
|
|
451
|
-
| <a id="urls"></a> `urls` | `ConnectionUrl`[] | [packages/client/src/client.ts:
|
|
455
|
+
| <a id="connectionoptions"></a> `connectionOptions?` | `AmqpConnectionManagerOptions` | [packages/client/src/client.ts:32](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/client.ts#L32) |
|
|
456
|
+
| <a id="contract"></a> `contract` | `TContract` | [packages/client/src/client.ts:30](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/client.ts#L30) |
|
|
457
|
+
| <a id="logger"></a> `logger?` | `Logger` | [packages/client/src/client.ts:33](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/client.ts#L33) |
|
|
458
|
+
| <a id="urls"></a> `urls` | `ConnectionUrl`[] | [packages/client/src/client.ts:31](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/client.ts#L31) |
|
|
459
|
+
|
|
460
|
+
***
|
|
461
|
+
|
|
462
|
+
### PublishOptions
|
|
463
|
+
|
|
464
|
+
```ts
|
|
465
|
+
type PublishOptions = Options.Publish & object;
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
Defined in: [packages/client/src/client.ts:17](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/client.ts#L17)
|
|
469
|
+
|
|
470
|
+
Publish options that extend amqplib's Options.Publish with optional compression support.
|
|
471
|
+
|
|
472
|
+
#### Type Declaration
|
|
473
|
+
|
|
474
|
+
| Name | Type | Description | Defined in |
|
|
475
|
+
| ------ | ------ | ------ | ------ |
|
|
476
|
+
| `compression?` | `CompressionAlgorithm` | Optional compression algorithm to use for the message payload. When specified, the message will be compressed using the chosen algorithm and the contentEncoding header will be set automatically. | [packages/client/src/client.ts:23](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/client.ts#L23) |
|
package/package.json
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amqp-contract/client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Client utilities for publishing messages using amqp-contract",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"amqp",
|
|
7
7
|
"client",
|
|
8
8
|
"contract",
|
|
9
9
|
"rabbitmq",
|
|
10
|
-
"typescript"
|
|
10
|
+
"typescript",
|
|
11
|
+
"nodejs",
|
|
12
|
+
"messaging",
|
|
13
|
+
"type-safe",
|
|
14
|
+
"schema",
|
|
15
|
+
"validation",
|
|
16
|
+
"message-broker",
|
|
17
|
+
"message-queue",
|
|
18
|
+
"publisher"
|
|
11
19
|
],
|
|
12
20
|
"homepage": "https://github.com/btravers/amqp-contract#readme",
|
|
13
21
|
"bugs": {
|
|
@@ -44,32 +52,32 @@
|
|
|
44
52
|
"dependencies": {
|
|
45
53
|
"@standard-schema/spec": "1.1.0",
|
|
46
54
|
"@swan-io/boxed": "3.2.1",
|
|
47
|
-
"
|
|
48
|
-
"@amqp-contract/
|
|
55
|
+
"ts-pattern": "5.9.0",
|
|
56
|
+
"@amqp-contract/contract": "0.8.0",
|
|
57
|
+
"@amqp-contract/core": "0.8.0"
|
|
49
58
|
},
|
|
50
59
|
"devDependencies": {
|
|
51
60
|
"@types/amqplib": "0.10.8",
|
|
52
|
-
"@types/node": "25.0.
|
|
61
|
+
"@types/node": "25.0.5",
|
|
53
62
|
"@vitest/coverage-v8": "4.0.16",
|
|
54
63
|
"amqp-connection-manager": "5.0.0",
|
|
55
64
|
"amqplib": "0.10.9",
|
|
56
|
-
"tsdown": "0.
|
|
65
|
+
"tsdown": "0.19.0",
|
|
57
66
|
"typedoc": "0.28.15",
|
|
58
67
|
"typedoc-plugin-markdown": "4.9.0",
|
|
59
68
|
"typescript": "5.9.3",
|
|
60
69
|
"vitest": "4.0.16",
|
|
61
|
-
"zod": "4.
|
|
62
|
-
"@amqp-contract/testing": "0.
|
|
63
|
-
"@amqp-contract/tsconfig": "0.
|
|
64
|
-
"@amqp-contract/typedoc": "0.0
|
|
70
|
+
"zod": "4.3.5",
|
|
71
|
+
"@amqp-contract/testing": "0.8.0",
|
|
72
|
+
"@amqp-contract/tsconfig": "0.1.0",
|
|
73
|
+
"@amqp-contract/typedoc": "0.1.0"
|
|
65
74
|
},
|
|
66
75
|
"scripts": {
|
|
67
76
|
"build": "tsdown src/index.ts --format cjs,esm --dts --clean",
|
|
68
77
|
"build:docs": "typedoc",
|
|
69
78
|
"dev": "tsdown src/index.ts --format cjs,esm --dts --watch",
|
|
70
|
-
"test": "vitest run --project
|
|
79
|
+
"test": "vitest run --project unit",
|
|
71
80
|
"test:integration": "vitest run --project integration",
|
|
72
|
-
"test:watch": "vitest --project integration",
|
|
73
81
|
"typecheck": "tsc --noEmit"
|
|
74
82
|
}
|
|
75
83
|
}
|