@amqp-contract/client 0.8.0 → 0.10.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/dist/index.cjs CHANGED
@@ -63,10 +63,11 @@ async function compressBuffer(buffer, algorithm) {
63
63
  * Type-safe AMQP client for publishing messages
64
64
  */
65
65
  var TypedAmqpClient = class TypedAmqpClient {
66
- constructor(contract, amqpClient, logger) {
66
+ constructor(contract, amqpClient, logger, telemetry = _amqp_contract_core.defaultTelemetryProvider) {
67
67
  this.contract = contract;
68
68
  this.amqpClient = amqpClient;
69
69
  this.logger = logger;
70
+ this.telemetry = telemetry;
70
71
  }
71
72
  /**
72
73
  * Create a type-safe AMQP client from a contract.
@@ -78,11 +79,11 @@ var TypedAmqpClient = class TypedAmqpClient {
78
79
  * Connections are automatically shared across clients with the same URLs and
79
80
  * connection options, following RabbitMQ best practices.
80
81
  */
81
- static create({ contract, urls, connectionOptions, logger }) {
82
+ static create({ contract, urls, connectionOptions, logger, telemetry }) {
82
83
  const client = new TypedAmqpClient(contract, new _amqp_contract_core.AmqpClient(contract, {
83
84
  urls,
84
85
  connectionOptions
85
- }), logger);
86
+ }), logger, telemetry ?? _amqp_contract_core.defaultTelemetryProvider);
86
87
  return client.waitForConnectionReady().mapOk(() => client);
87
88
  }
88
89
  /**
@@ -100,10 +101,14 @@ var TypedAmqpClient = class TypedAmqpClient {
100
101
  * @returns Result.Ok(void) on success, or Result.Error with specific error on failure
101
102
  */
102
103
  publish(publisherName, message, options) {
104
+ const startTime = Date.now();
103
105
  const publishers = this.contract.publishers;
104
106
  if (!publishers) return _swan_io_boxed.Future.value(_swan_io_boxed.Result.Error(new TechnicalError("No publishers defined in contract")));
105
107
  const publisher = publishers[publisherName];
106
108
  if (!publisher) return _swan_io_boxed.Future.value(_swan_io_boxed.Result.Error(new TechnicalError(`Publisher "${String(publisherName)}" not found in contract`)));
109
+ const exchangeName = publisher.exchange.name;
110
+ const routingKey = publisher.routingKey;
111
+ const span = (0, _amqp_contract_core.startPublishSpan)(this.telemetry, exchangeName, routingKey, { "amqp.publisher.name": String(publisherName) });
107
112
  const validateMessage = () => {
108
113
  const validationResult = publisher.message.payload["~standard"].validate(message);
109
114
  return _swan_io_boxed.Future.fromPromise(validationResult instanceof Promise ? validationResult : Promise.resolve(validationResult)).mapError((error) => new TechnicalError(`Validation failed`, error)).mapOkToResult((validation) => {
@@ -133,7 +138,15 @@ var TypedAmqpClient = class TypedAmqpClient {
133
138
  return _swan_io_boxed.Result.Ok(void 0);
134
139
  }));
135
140
  };
136
- return validateMessage().flatMapOk((validatedMessage) => publishMessage(validatedMessage));
141
+ return validateMessage().flatMapOk((validatedMessage) => publishMessage(validatedMessage)).tapOk(() => {
142
+ const durationMs = Date.now() - startTime;
143
+ (0, _amqp_contract_core.endSpanSuccess)(span);
144
+ (0, _amqp_contract_core.recordPublishMetric)(this.telemetry, exchangeName, routingKey, true, durationMs);
145
+ }).tapError((error) => {
146
+ const durationMs = Date.now() - startTime;
147
+ (0, _amqp_contract_core.endSpanError)(span, error);
148
+ (0, _amqp_contract_core.recordPublishMetric)(this.telemetry, exchangeName, routingKey, false, durationMs);
149
+ });
137
150
  }
138
151
  /**
139
152
  * Close the channel and connection
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { Logger } from "@amqp-contract/core";
1
+ import { Logger, TelemetryProvider } from "@amqp-contract/core";
2
2
  import { AmqpConnectionManagerOptions, ConnectionUrl } from "amqp-connection-manager";
3
3
  import { CompressionAlgorithm, ContractDefinition, InferPublisherNames, PublisherDefinition } from "@amqp-contract/contract";
4
4
  import { Future, Result } from "@swan-io/boxed";
@@ -71,6 +71,12 @@ type CreateClientOptions<TContract extends ContractDefinition> = {
71
71
  urls: ConnectionUrl[];
72
72
  connectionOptions?: AmqpConnectionManagerOptions | undefined;
73
73
  logger?: Logger | undefined;
74
+ /**
75
+ * Optional telemetry provider for tracing and metrics.
76
+ * If not provided, uses the default provider which attempts to load OpenTelemetry.
77
+ * OpenTelemetry instrumentation is automatically enabled if @opentelemetry/api is installed.
78
+ */
79
+ telemetry?: TelemetryProvider | undefined;
74
80
  };
75
81
  /**
76
82
  * Type-safe AMQP client for publishing messages
@@ -79,6 +85,7 @@ declare class TypedAmqpClient<TContract extends ContractDefinition> {
79
85
  private readonly contract;
80
86
  private readonly amqpClient;
81
87
  private readonly logger?;
88
+ private readonly telemetry;
82
89
  private constructor();
83
90
  /**
84
91
  * Create a type-safe AMQP client from a contract.
@@ -94,7 +101,8 @@ declare class TypedAmqpClient<TContract extends ContractDefinition> {
94
101
  contract,
95
102
  urls,
96
103
  connectionOptions,
97
- logger
104
+ logger,
105
+ telemetry
98
106
  }: CreateClientOptions<TContract>): Future<Result<TypedAmqpClient<TContract>, TechnicalError>>;
99
107
  /**
100
108
  * Publish a message using a defined publisher
@@ -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,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"}
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,KETD,cAAA,GAAiB,OAAA,CAAQ,OFSO,GAAA;;;;AC7BkB;;EAM5D,WAAA,CAAA,ECoBc,oBDpBd,GAAA,SAAA;CAAgB;;AAAgB;;AAMhC,KCoBU,mBDpBV,CAAA,kBCoBgD,kBDpBhD,CAAA,GAAA;EADiE,QAAA,ECsBvD,SDtBuD;EAAgB,IAAA,ECuB3E,aDvB2E,EAAA;EAO9E,iBAAA,CAAe,ECiBE,4BDjBF,GAAA,SAAA;EAAmB,MAAA,CAAA,ECkB5B,MDlB4B,GAAA,SAAA;EAAkC;;;AAAD;;EAOpC,SAAA,CAAA,ECiBtB,iBDjBsB,GAAA,SAAA;CAApB;;;;AACoB,cCsBvB,eDtBuB,CAAA,kBCsBW,kBDtBX,CAAA,CAAA;EAKxB,iBAAA,QAAA;EACQ,iBAAA,UAAA;EACgB,iBAAA,MAAA;EAApB,iBAAA,SAAA;EACuB,QAAA,WAAA,CAAA;EAAW;;;;;;;ACdlD;AAYA;;EACY,OAAA,MAAA,CAAA,kBAiCsB,kBAjCtB,CAAA,CAAA;IAAA,QAAA;IAAA,IAAA;IAAA,iBAAA;IAAA,MAAA;IAAA;EAAA,CAAA,EAuCP,mBAvCO,CAuCa,SAvCb,CAAA,CAAA,EAuC0B,MAvC1B,CAuCiC,MAvCjC,CAuCwC,eAvCxC,CAuCwD,SAvCxD,CAAA,EAuCoE,cAvCpE,CAAA,CAAA;EACJ;;;;;AAcR;;;;;;;;;EAwBK,OAAA,CAAA,cAyBmB,mBAzBnB,CAyBuC,SAzBvC,CAAA,CAAA,CAAA,aAAA,EA0Bc,KA1Bd,EAAA,OAAA,EA2BQ,yBA3BR,CA2BkC,SA3BlC,EA2B6C,KA3B7C,CAAA,EAAA,OAAA,CAAA,EA4BS,cA5BT,CAAA,EA6BA,MA7BA,CA6BO,MA7BP,CAAA,IAAA,EA6BoB,cA7BpB,GA6BqC,sBA7BrC,CAAA,CAAA;EAA+D;;;EAAvB,KAAA,CAAA,CAAA,EA6IlC,MA7IkC,CA6I3B,MA7I2B,CAAA,IAAA,EA6Id,cA7Ic,CAAA,CAAA;EAAP,QAAA,sBAAA"}
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { Logger } from "@amqp-contract/core";
1
+ import { Logger, TelemetryProvider } from "@amqp-contract/core";
2
2
  import { Future, Result } from "@swan-io/boxed";
3
3
  import { AmqpConnectionManagerOptions, ConnectionUrl } from "amqp-connection-manager";
4
4
  import { CompressionAlgorithm, ContractDefinition, InferPublisherNames, PublisherDefinition } from "@amqp-contract/contract";
@@ -71,6 +71,12 @@ type CreateClientOptions<TContract extends ContractDefinition> = {
71
71
  urls: ConnectionUrl[];
72
72
  connectionOptions?: AmqpConnectionManagerOptions | undefined;
73
73
  logger?: Logger | undefined;
74
+ /**
75
+ * Optional telemetry provider for tracing and metrics.
76
+ * If not provided, uses the default provider which attempts to load OpenTelemetry.
77
+ * OpenTelemetry instrumentation is automatically enabled if @opentelemetry/api is installed.
78
+ */
79
+ telemetry?: TelemetryProvider | undefined;
74
80
  };
75
81
  /**
76
82
  * Type-safe AMQP client for publishing messages
@@ -79,6 +85,7 @@ declare class TypedAmqpClient<TContract extends ContractDefinition> {
79
85
  private readonly contract;
80
86
  private readonly amqpClient;
81
87
  private readonly logger?;
88
+ private readonly telemetry;
82
89
  private constructor();
83
90
  /**
84
91
  * Create a type-safe AMQP client from a contract.
@@ -94,7 +101,8 @@ declare class TypedAmqpClient<TContract extends ContractDefinition> {
94
101
  contract,
95
102
  urls,
96
103
  connectionOptions,
97
- logger
104
+ logger,
105
+ telemetry
98
106
  }: CreateClientOptions<TContract>): Future<Result<TypedAmqpClient<TContract>, TechnicalError>>;
99
107
  /**
100
108
  * Publish a message using a defined publisher
@@ -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,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"}
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,KETD,cAAA,GAAiB,OAAA,CAAQ,OFSO,GAAA;;;;AC7BkB;;EAM5D,WAAA,CAAA,ECoBc,oBDpBd,GAAA,SAAA;CAAgB;;AAAgB;;AAMhC,KCoBU,mBDpBV,CAAA,kBCoBgD,kBDpBhD,CAAA,GAAA;EADiE,QAAA,ECsBvD,SDtBuD;EAAgB,IAAA,ECuB3E,aDvB2E,EAAA;EAO9E,iBAAA,CAAe,ECiBE,4BDjBF,GAAA,SAAA;EAAmB,MAAA,CAAA,ECkB5B,MDlB4B,GAAA,SAAA;EAAkC;;;AAAD;;EAOpC,SAAA,CAAA,ECiBtB,iBDjBsB,GAAA,SAAA;CAApB;;;;AACoB,cCsBvB,eDtBuB,CAAA,kBCsBW,kBDtBX,CAAA,CAAA;EAKxB,iBAAA,QAAA;EACQ,iBAAA,UAAA;EACgB,iBAAA,MAAA;EAApB,iBAAA,SAAA;EACuB,QAAA,WAAA,CAAA;EAAW;;;;;;;ACdlD;AAYA;;EACY,OAAA,MAAA,CAAA,kBAiCsB,kBAjCtB,CAAA,CAAA;IAAA,QAAA;IAAA,IAAA;IAAA,iBAAA;IAAA,MAAA;IAAA;EAAA,CAAA,EAuCP,mBAvCO,CAuCa,SAvCb,CAAA,CAAA,EAuC0B,MAvC1B,CAuCiC,MAvCjC,CAuCwC,eAvCxC,CAuCwD,SAvCxD,CAAA,EAuCoE,cAvCpE,CAAA,CAAA;EACJ;;;;;AAcR;;;;;;;;;EAwBK,OAAA,CAAA,cAyBmB,mBAzBnB,CAyBuC,SAzBvC,CAAA,CAAA,CAAA,aAAA,EA0Bc,KA1Bd,EAAA,OAAA,EA2BQ,yBA3BR,CA2BkC,SA3BlC,EA2B6C,KA3B7C,CAAA,EAAA,OAAA,CAAA,EA4BS,cA5BT,CAAA,EA6BA,MA7BA,CA6BO,MA7BP,CAAA,IAAA,EA6BoB,cA7BpB,GA6BqC,sBA7BrC,CAAA,CAAA;EAA+D;;;EAAvB,KAAA,CAAA,CAAA,EA6IlC,MA7IkC,CA6I3B,MA7I2B,CAAA,IAAA,EA6Id,cA7Ic,CAAA,CAAA;EAAP,QAAA,sBAAA"}
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { AmqpClient } from "@amqp-contract/core";
1
+ import { AmqpClient, defaultTelemetryProvider, endSpanError, endSpanSuccess, recordPublishMetric, startPublishSpan } from "@amqp-contract/core";
2
2
  import { Future, Result } from "@swan-io/boxed";
3
3
  import { deflate, gzip } from "node:zlib";
4
4
  import { match } from "ts-pattern";
@@ -63,10 +63,11 @@ async function compressBuffer(buffer, algorithm) {
63
63
  * Type-safe AMQP client for publishing messages
64
64
  */
65
65
  var TypedAmqpClient = class TypedAmqpClient {
66
- constructor(contract, amqpClient, logger) {
66
+ constructor(contract, amqpClient, logger, telemetry = defaultTelemetryProvider) {
67
67
  this.contract = contract;
68
68
  this.amqpClient = amqpClient;
69
69
  this.logger = logger;
70
+ this.telemetry = telemetry;
70
71
  }
71
72
  /**
72
73
  * Create a type-safe AMQP client from a contract.
@@ -78,11 +79,11 @@ var TypedAmqpClient = class TypedAmqpClient {
78
79
  * Connections are automatically shared across clients with the same URLs and
79
80
  * connection options, following RabbitMQ best practices.
80
81
  */
81
- static create({ contract, urls, connectionOptions, logger }) {
82
+ static create({ contract, urls, connectionOptions, logger, telemetry }) {
82
83
  const client = new TypedAmqpClient(contract, new AmqpClient(contract, {
83
84
  urls,
84
85
  connectionOptions
85
- }), logger);
86
+ }), logger, telemetry ?? defaultTelemetryProvider);
86
87
  return client.waitForConnectionReady().mapOk(() => client);
87
88
  }
88
89
  /**
@@ -100,10 +101,14 @@ var TypedAmqpClient = class TypedAmqpClient {
100
101
  * @returns Result.Ok(void) on success, or Result.Error with specific error on failure
101
102
  */
102
103
  publish(publisherName, message, options) {
104
+ const startTime = Date.now();
103
105
  const publishers = this.contract.publishers;
104
106
  if (!publishers) return Future.value(Result.Error(new TechnicalError("No publishers defined in contract")));
105
107
  const publisher = publishers[publisherName];
106
108
  if (!publisher) return Future.value(Result.Error(new TechnicalError(`Publisher "${String(publisherName)}" not found in contract`)));
109
+ const exchangeName = publisher.exchange.name;
110
+ const routingKey = publisher.routingKey;
111
+ const span = startPublishSpan(this.telemetry, exchangeName, routingKey, { "amqp.publisher.name": String(publisherName) });
107
112
  const validateMessage = () => {
108
113
  const validationResult = publisher.message.payload["~standard"].validate(message);
109
114
  return Future.fromPromise(validationResult instanceof Promise ? validationResult : Promise.resolve(validationResult)).mapError((error) => new TechnicalError(`Validation failed`, error)).mapOkToResult((validation) => {
@@ -133,7 +138,15 @@ var TypedAmqpClient = class TypedAmqpClient {
133
138
  return Result.Ok(void 0);
134
139
  }));
135
140
  };
136
- return validateMessage().flatMapOk((validatedMessage) => publishMessage(validatedMessage));
141
+ return validateMessage().flatMapOk((validatedMessage) => publishMessage(validatedMessage)).tapOk(() => {
142
+ const durationMs = Date.now() - startTime;
143
+ endSpanSuccess(span);
144
+ recordPublishMetric(this.telemetry, exchangeName, routingKey, true, durationMs);
145
+ }).tapError((error) => {
146
+ const durationMs = Date.now() - startTime;
147
+ endSpanError(span, error);
148
+ recordPublishMetric(this.telemetry, exchangeName, routingKey, false, durationMs);
149
+ });
137
150
  }
138
151
  /**
139
152
  * Close the channel and connection
@@ -1 +1 @@
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":"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"}
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 {\n AmqpClient,\n type Logger,\n type TelemetryProvider,\n defaultTelemetryProvider,\n endSpanError,\n endSpanSuccess,\n recordPublishMetric,\n startPublishSpan,\n} 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 * Optional telemetry provider for tracing and metrics.\n * If not provided, uses the default provider which attempts to load OpenTelemetry.\n * OpenTelemetry instrumentation is automatically enabled if @opentelemetry/api is installed.\n */\n telemetry?: TelemetryProvider | 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 private readonly telemetry: TelemetryProvider = defaultTelemetryProvider,\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 telemetry,\n }: CreateClientOptions<TContract>): Future<Result<TypedAmqpClient<TContract>, TechnicalError>> {\n const client = new TypedAmqpClient(\n contract,\n new AmqpClient(contract, { urls, connectionOptions }),\n logger,\n telemetry ?? defaultTelemetryProvider,\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 startTime = Date.now();\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 exchangeName = publisher.exchange.name;\n const routingKey = publisher.routingKey;\n\n // Start telemetry span\n const span = startPublishSpan(this.telemetry, exchangeName, routingKey, {\n \"amqp.publisher.name\": String(publisherName),\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()\n .flatMapOk((validatedMessage) => publishMessage(validatedMessage))\n .tapOk(() => {\n const durationMs = Date.now() - startTime;\n endSpanSuccess(span);\n recordPublishMetric(this.telemetry, exchangeName, routingKey, true, durationMs);\n })\n .tapError((error) => {\n const durationMs = Date.now() - startTime;\n endSpanError(span, error);\n recordPublishMetric(this.telemetry, exchangeName, routingKey, false, durationMs);\n });\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":"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"}
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/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/errors.ts#L35)
11
+ Defined in: [packages/client/src/errors.ts:35](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/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/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/errors.ts#L36)
27
+ Defined in: [packages/client/src/errors.ts:36](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/packages/client/src/errors.ts#L36)
28
28
 
29
29
  ###### Parameters
30
30
 
@@ -48,10 +48,10 @@ 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/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/errors.ts#L38) |
51
+ | <a id="issues"></a> `issues` | `readonly` | `unknown` | - | - | [packages/client/src/errors.ts:38](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/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/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/errors.ts#L37) |
54
+ | <a id="publishername"></a> `publisherName` | `readonly` | `string` | - | - | [packages/client/src/errors.ts:37](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/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
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
 
@@ -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/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/errors.ts#L22)
162
+ Defined in: [packages/client/src/errors.ts:22](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/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/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/errors.ts#L23)
179
+ Defined in: [packages/client/src/errors.ts:23](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/packages/client/src/errors.ts#L23)
180
180
 
181
181
  ###### Parameters
182
182
 
@@ -199,7 +199,7 @@ 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/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/errors.ts#L25) |
202
+ | <a id="cause-1"></a> `cause?` | `readonly` | `unknown` | - | `ClientError.cause` | [packages/client/src/errors.ts:25](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/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 |
@@ -309,7 +309,7 @@ ClientError.prepareStackTrace
309
309
 
310
310
  ### TypedAmqpClient
311
311
 
312
- Defined in: [packages/client/src/client.ts:39](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/client.ts#L39)
312
+ Defined in: [packages/client/src/client.ts:54](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/packages/client/src/client.ts#L54)
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:181](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/client.ts#L181)
330
+ Defined in: [packages/client/src/client.ts:219](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/packages/client/src/client.ts#L219)
331
331
 
332
332
  Close the channel and connection
333
333
 
@@ -346,7 +346,7 @@ publish<TName>(
346
346
  | MessageValidationError>>;
347
347
  ```
348
348
 
349
- Defined in: [packages/client/src/client.ts:85](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/client.ts#L85)
349
+ Defined in: [packages/client/src/client.ts:103](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/packages/client/src/client.ts#L103)
350
350
 
351
351
  Publish a message using a defined publisher
352
352
 
@@ -384,7 +384,7 @@ value already in options will be overwritten by the compression algorithm.
384
384
  static create<TContract>(__namedParameters): Future<Result<TypedAmqpClient<TContract>, TechnicalError>>;
385
385
  ```
386
386
 
387
- Defined in: [packages/client/src/client.ts:56](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/client.ts#L56)
387
+ Defined in: [packages/client/src/client.ts:72](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/packages/client/src/client.ts#L72)
388
388
 
389
389
  Create a type-safe AMQP client from a contract.
390
390
 
@@ -419,7 +419,7 @@ connection options, following RabbitMQ best practices.
419
419
  type ClientInferPublisherInput<TContract, TName> = PublisherInferInput<InferPublisher<TContract, TName>>;
420
420
  ```
421
421
 
422
- Defined in: [packages/client/src/types.ts:37](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/types.ts#L37)
422
+ Defined in: [packages/client/src/types.ts:37](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/packages/client/src/types.ts#L37)
423
423
 
424
424
  Infer publisher input type (message payload) for a specific publisher in a contract
425
425
 
@@ -438,7 +438,7 @@ Infer publisher input type (message payload) for a specific publisher in a contr
438
438
  type CreateClientOptions<TContract> = object;
439
439
  ```
440
440
 
441
- Defined in: [packages/client/src/client.ts:29](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/client.ts#L29)
441
+ Defined in: [packages/client/src/client.ts:38](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/packages/client/src/client.ts#L38)
442
442
 
443
443
  Options for creating a client
444
444
 
@@ -450,12 +450,13 @@ Options for creating a client
450
450
 
451
451
  #### Properties
452
452
 
453
- | Property | Type | Defined in |
454
- | ------ | ------ | ------ |
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) |
453
+ | Property | Type | Description | Defined in |
454
+ | ------ | ------ | ------ | ------ |
455
+ | <a id="connectionoptions"></a> `connectionOptions?` | `AmqpConnectionManagerOptions` | - | [packages/client/src/client.ts:41](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/packages/client/src/client.ts#L41) |
456
+ | <a id="contract"></a> `contract` | `TContract` | - | [packages/client/src/client.ts:39](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/packages/client/src/client.ts#L39) |
457
+ | <a id="logger"></a> `logger?` | `Logger` | - | [packages/client/src/client.ts:42](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/packages/client/src/client.ts#L42) |
458
+ | <a id="telemetry"></a> `telemetry?` | `TelemetryProvider` | Optional telemetry provider for tracing and metrics. If not provided, uses the default provider which attempts to load OpenTelemetry. OpenTelemetry instrumentation is automatically enabled if @opentelemetry/api is installed. | [packages/client/src/client.ts:48](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/packages/client/src/client.ts#L48) |
459
+ | <a id="urls"></a> `urls` | `ConnectionUrl`[] | - | [packages/client/src/client.ts:40](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/packages/client/src/client.ts#L40) |
459
460
 
460
461
  ***
461
462
 
@@ -465,7 +466,7 @@ Options for creating a client
465
466
  type PublishOptions = Options.Publish & object;
466
467
  ```
467
468
 
468
- Defined in: [packages/client/src/client.ts:17](https://github.com/btravers/amqp-contract/blob/7897a0ef6745684800b11ec9bbc26bfab645f2a7/packages/client/src/client.ts#L17)
469
+ Defined in: [packages/client/src/client.ts:26](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/packages/client/src/client.ts#L26)
469
470
 
470
471
  Publish options that extend amqplib's Options.Publish with optional compression support.
471
472
 
@@ -473,4 +474,4 @@ Publish options that extend amqplib's Options.Publish with optional compression
473
474
 
474
475
  | Name | Type | Description | Defined in |
475
476
  | ------ | ------ | ------ | ------ |
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) |
477
+ | `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:32](https://github.com/btravers/amqp-contract/blob/00468eb63a019d6161c43f07dab8b68232bbb383/packages/client/src/client.ts#L32) |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amqp-contract/client",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "description": "Client utilities for publishing messages using amqp-contract",
5
5
  "keywords": [
6
6
  "amqp",
@@ -53,8 +53,8 @@
53
53
  "@standard-schema/spec": "1.1.0",
54
54
  "@swan-io/boxed": "3.2.1",
55
55
  "ts-pattern": "5.9.0",
56
- "@amqp-contract/contract": "0.8.0",
57
- "@amqp-contract/core": "0.8.0"
56
+ "@amqp-contract/contract": "0.10.0",
57
+ "@amqp-contract/core": "0.10.0"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@types/amqplib": "0.10.8",
@@ -68,7 +68,7 @@
68
68
  "typescript": "5.9.3",
69
69
  "vitest": "4.0.16",
70
70
  "zod": "4.3.5",
71
- "@amqp-contract/testing": "0.8.0",
71
+ "@amqp-contract/testing": "0.10.0",
72
72
  "@amqp-contract/tsconfig": "0.1.0",
73
73
  "@amqp-contract/typedoc": "0.1.0"
74
74
  },