@amqp-contract/client 0.0.4 → 0.0.6

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 CHANGED
@@ -7,21 +7,20 @@ Type-safe AMQP client for publishing messages using amqp-contract.
7
7
  ## Installation
8
8
 
9
9
  ```bash
10
- pnpm add @amqp-contract/client amqplib
10
+ pnpm add @amqp-contract/client
11
11
  ```
12
12
 
13
13
  ## Usage
14
14
 
15
15
  ```typescript
16
- import { createClient } from '@amqp-contract/client';
17
- import { connect } from 'amqplib';
16
+ import { TypedAmqpClient } from '@amqp-contract/client';
18
17
  import { contract } from './contract';
19
18
 
20
- // Connect to RabbitMQ
21
- const connection = await connect('amqp://localhost');
22
-
23
19
  // Create client from contract (automatically connects)
24
- const client = await createClient({ contract, connection });
20
+ const client = await TypedAmqpClient.create({
21
+ contract,
22
+ connection: 'amqp://localhost'
23
+ });
25
24
 
26
25
  // Publish message with type safety
27
26
  await client.publish('orderCreated', {
@@ -35,26 +34,20 @@ await client.close();
35
34
 
36
35
  ## API
37
36
 
38
- ### `createClient(options)`
37
+ ### `TypedAmqpClient.create(options)`
39
38
 
40
39
  Create a type-safe AMQP client from a contract. Automatically connects to RabbitMQ.
41
40
 
42
41
  **Parameters:**
43
42
 
44
43
  - `options.contract` - Contract definition
45
- - `options.connection` - amqplib Connection object
46
-
47
- ### `AmqpClient.connect(connection)`
48
-
49
- Connect to an AMQP broker and set up all exchanges, queues, and bindings defined in the contract.
50
-
51
- **Note:** When using `createClient()`, this is called automatically.
44
+ - `options.connection` - AMQP connection URL (string) or connection options (Options.Connect)
52
45
 
53
- ### `AmqpClient.publish(publisherName, message, options?)`
46
+ ### `TypedAmqpClient.publish(publisherName, message, options?)`
54
47
 
55
48
  Publish a message using a defined publisher. The message will be validated against the schema and type-checked at compile time.
56
49
 
57
- ### `AmqpClient.close()`
50
+ ### `TypedAmqpClient.close()`
58
51
 
59
52
  Close the channel and connection.
60
53
 
package/dist/index.cjs CHANGED
@@ -1,39 +1,30 @@
1
+ let amqplib = require("amqplib");
1
2
 
2
3
  //#region src/client.ts
3
4
  /**
4
5
  * Type-safe AMQP client for publishing messages
5
6
  */
6
- var AmqpClient = class {
7
+ var TypedAmqpClient = class TypedAmqpClient {
7
8
  channel = null;
8
9
  connection = null;
9
- constructor(contract) {
10
+ constructor(contract, connectionOptions) {
10
11
  this.contract = contract;
12
+ this.connectionOptions = connectionOptions;
11
13
  }
12
14
  /**
13
- * Connect to AMQP broker
15
+ * Create a type-safe AMQP client from a contract
16
+ * The client will automatically connect to the AMQP broker
14
17
  */
15
- async connect(connection) {
16
- this.connection = connection;
17
- this.channel = await connection.createChannel();
18
- if (this.contract.exchanges && this.channel) for (const exchange of Object.values(this.contract.exchanges)) await this.channel.assertExchange(exchange.name, exchange.type, {
19
- durable: exchange.durable,
20
- autoDelete: exchange.autoDelete,
21
- internal: exchange.internal,
22
- arguments: exchange.arguments
23
- });
24
- if (this.contract.queues && this.channel) for (const queue of Object.values(this.contract.queues)) await this.channel.assertQueue(queue.name, {
25
- durable: queue.durable,
26
- exclusive: queue.exclusive,
27
- autoDelete: queue.autoDelete,
28
- arguments: queue.arguments
29
- });
30
- if (this.contract.bindings && this.channel) for (const binding of Object.values(this.contract.bindings)) await this.channel.bindQueue(binding.queue, binding.exchange, binding.routingKey ?? "", binding.arguments);
18
+ static async create(options) {
19
+ const client = new TypedAmqpClient(options.contract, options.connection);
20
+ await client.init();
21
+ return client;
31
22
  }
32
23
  /**
33
24
  * Publish a message using a defined publisher
34
25
  */
35
26
  async publish(publisherName, message, options) {
36
- if (!this.channel) throw new Error("Client not connected. Call connect() first.");
27
+ if (!this.channel) throw new Error("Client not initialized. Create the client using TypedAmqpClient.create() to establish a connection.");
37
28
  const publishers = this.contract.publishers;
38
29
  if (!publishers) throw new Error("No publishers defined in contract");
39
30
  const publisher = publishers[publisherName];
@@ -47,7 +38,7 @@ var AmqpClient = class {
47
38
  return this.channel.publish(publisherDef.exchange, routingKey, content, options?.options);
48
39
  }
49
40
  /**
50
- * Close the connection
41
+ * Close the channel and connection
51
42
  */
52
43
  async close() {
53
44
  if (this.channel) {
@@ -59,17 +50,27 @@ var AmqpClient = class {
59
50
  this.connection = null;
60
51
  }
61
52
  }
53
+ /**
54
+ * Connect to AMQP broker
55
+ */
56
+ async init() {
57
+ this.connection = await (0, amqplib.connect)(this.connectionOptions);
58
+ this.channel = await this.connection.createChannel();
59
+ if (this.contract.exchanges) for (const exchange of Object.values(this.contract.exchanges)) await this.channel.assertExchange(exchange.name, exchange.type, {
60
+ durable: exchange.durable,
61
+ autoDelete: exchange.autoDelete,
62
+ internal: exchange.internal,
63
+ arguments: exchange.arguments
64
+ });
65
+ if (this.contract.queues) for (const queue of Object.values(this.contract.queues)) await this.channel.assertQueue(queue.name, {
66
+ durable: queue.durable,
67
+ exclusive: queue.exclusive,
68
+ autoDelete: queue.autoDelete,
69
+ arguments: queue.arguments
70
+ });
71
+ if (this.contract.bindings) for (const binding of Object.values(this.contract.bindings)) await this.channel.bindQueue(binding.queue, binding.exchange, binding.routingKey ?? "", binding.arguments);
72
+ }
62
73
  };
63
- /**
64
- * Create a type-safe AMQP client from a contract
65
- * The client will automatically connect to the AMQP broker
66
- */
67
- async function createClient(options) {
68
- const client = new AmqpClient(options.contract);
69
- await client.connect(options.connection);
70
- return client;
71
- }
72
74
 
73
75
  //#endregion
74
- exports.AmqpClient = AmqpClient;
75
- exports.createClient = createClient;
76
+ exports.TypedAmqpClient = TypedAmqpClient;
package/dist/index.d.cts CHANGED
@@ -1,8 +1,15 @@
1
- import { ChannelModel, Options } from "amqplib";
1
+ import { Options } from "amqplib";
2
2
  import { ClientInferPublisherInput, ContractDefinition, InferPublisherNames } from "@amqp-contract/contract";
3
3
 
4
4
  //#region src/client.d.ts
5
5
 
6
+ /**
7
+ * Options for creating a client
8
+ */
9
+ interface CreateClientOptions<TContract extends ContractDefinition> {
10
+ contract: TContract;
11
+ connection: string | Options.Connect;
12
+ }
6
13
  /**
7
14
  * Options for publishing a message
8
15
  */
@@ -13,36 +20,30 @@ interface PublishOptions {
13
20
  /**
14
21
  * Type-safe AMQP client for publishing messages
15
22
  */
16
- declare class AmqpClient<TContract extends ContractDefinition> {
23
+ declare class TypedAmqpClient<TContract extends ContractDefinition> {
17
24
  private readonly contract;
25
+ private readonly connectionOptions;
18
26
  private channel;
19
27
  private connection;
20
- constructor(contract: TContract);
28
+ private constructor();
21
29
  /**
22
- * Connect to AMQP broker
30
+ * Create a type-safe AMQP client from a contract
31
+ * The client will automatically connect to the AMQP broker
23
32
  */
24
- connect(connection: ChannelModel): Promise<void>;
33
+ static create<TContract extends ContractDefinition>(options: CreateClientOptions<TContract>): Promise<TypedAmqpClient<TContract>>;
25
34
  /**
26
35
  * Publish a message using a defined publisher
27
36
  */
28
37
  publish<TName extends InferPublisherNames<TContract>>(publisherName: TName, message: ClientInferPublisherInput<TContract, TName>, options?: PublishOptions): Promise<boolean>;
29
38
  /**
30
- * Close the connection
39
+ * Close the channel and connection
31
40
  */
32
41
  close(): Promise<void>;
42
+ /**
43
+ * Connect to AMQP broker
44
+ */
45
+ private init;
33
46
  }
34
- /**
35
- * Options for creating a client
36
- */
37
- interface CreateClientOptions<TContract extends ContractDefinition> {
38
- contract: TContract;
39
- connection: ChannelModel;
40
- }
41
- /**
42
- * Create a type-safe AMQP client from a contract
43
- * The client will automatically connect to the AMQP broker
44
- */
45
- declare function createClient<TContract extends ContractDefinition>(options: CreateClientOptions<TContract>): Promise<AmqpClient<TContract>>;
46
47
  //#endregion
47
- export { AmqpClient, type CreateClientOptions, type PublishOptions, createClient };
48
+ export { type CreateClientOptions, type PublishOptions, TypedAmqpClient };
48
49
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/client.ts"],"sourcesContent":[],"mappings":";;;;;;;AAUA;AAQa,UARI,cAAA,CAQM;EAAmB,UAAA,CAAA,EAAA,MAAA;EAID,OAAA,CAAA,EAV7B,OAAA,CAAQ,OAUqB;;;;;AAkDtB,cAtDN,UAsDM,CAAA,kBAtDuB,kBAsDvB,CAAA,CAAA;EACoB,iBAAA,QAAA;EAAW,QAAA,OAAA;EAArC,QAAA,UAAA;EACC,WAAA,CAAA,QAAA,EApD2B,SAoD3B;EACT;;;EA8DY,OAAA,CAAA,UAAA,EA9GW,YA8GQ,CAAA,EA9GO,OA8GP,CAAA,IAAA,CAAA;EAAmB;;;EAE7B,OAAA,CAAA,cApEI,mBAoEJ,CApEwB,SAoExB,CAAA,CAAA,CAAA,aAAA,EAnEP,KAmEO,EAAA,OAAA,EAlEb,yBAkEa,CAlEa,SAkEb,EAlEwB,KAkExB,CAAA,EAAA,OAAA,CAAA,EAjEZ,cAiEY,CAAA,EAhErB,OAgEqB,CAAA,OAAA,CAAA;EAOJ;;;EACX,KAAA,CAAA,CAAA,EAzBM,OAyBN,CAAA,IAAA,CAAA;;;;;UAVM,sCAAsC;YAC3C;cACE;;;;;;iBAOQ,+BAA+B,6BAC1C,oBAAoB,aAC5B,QAAQ,WAAW"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/client.ts"],"sourcesContent":[],"mappings":";;;;;;;AAWA;AAAuD,UAAtC,mBAAsC,CAAA,kBAAA,kBAAA,CAAA,CAAA;EAC3C,QAAA,EAAA,SAAA;EACW,UAAQ,EAAA,MAAA,GAAR,OAAA,CAAQ,OAAA;;AAM/B;AAQA;;AAawC,UArBvB,cAAA,CAqBuB;EACP,UAAA,CAAA,EAAA,MAAA;EAApB,OAAA,CAAA,EApBD,OAAA,CAAQ,OAoBP;;;;;AAUiB,cAxBjB,eAwBiB,CAAA,kBAxBiB,kBAwBjB,CAAA,CAAA;EACX,iBAAA,QAAA;EACoB,iBAAA,iBAAA;EAAW,QAAA,OAAA;EAArC,QAAA,UAAA;EACC,QAAA,WAAA,CAAA;EACT;;;;kCAfmC,6BAC3B,oBAAoB,aAC5B,QAAQ,gBAAgB;;;;wBASC,oBAAoB,2BAC/B,gBACN,0BAA0B,WAAW,kBACpC,iBACT;;;;WAiDY"}
package/dist/index.d.mts CHANGED
@@ -1,8 +1,15 @@
1
- import { ChannelModel, Options } from "amqplib";
1
+ import { Options } from "amqplib";
2
2
  import { ClientInferPublisherInput, ContractDefinition, InferPublisherNames } from "@amqp-contract/contract";
3
3
 
4
4
  //#region src/client.d.ts
5
5
 
6
+ /**
7
+ * Options for creating a client
8
+ */
9
+ interface CreateClientOptions<TContract extends ContractDefinition> {
10
+ contract: TContract;
11
+ connection: string | Options.Connect;
12
+ }
6
13
  /**
7
14
  * Options for publishing a message
8
15
  */
@@ -13,36 +20,30 @@ interface PublishOptions {
13
20
  /**
14
21
  * Type-safe AMQP client for publishing messages
15
22
  */
16
- declare class AmqpClient<TContract extends ContractDefinition> {
23
+ declare class TypedAmqpClient<TContract extends ContractDefinition> {
17
24
  private readonly contract;
25
+ private readonly connectionOptions;
18
26
  private channel;
19
27
  private connection;
20
- constructor(contract: TContract);
28
+ private constructor();
21
29
  /**
22
- * Connect to AMQP broker
30
+ * Create a type-safe AMQP client from a contract
31
+ * The client will automatically connect to the AMQP broker
23
32
  */
24
- connect(connection: ChannelModel): Promise<void>;
33
+ static create<TContract extends ContractDefinition>(options: CreateClientOptions<TContract>): Promise<TypedAmqpClient<TContract>>;
25
34
  /**
26
35
  * Publish a message using a defined publisher
27
36
  */
28
37
  publish<TName extends InferPublisherNames<TContract>>(publisherName: TName, message: ClientInferPublisherInput<TContract, TName>, options?: PublishOptions): Promise<boolean>;
29
38
  /**
30
- * Close the connection
39
+ * Close the channel and connection
31
40
  */
32
41
  close(): Promise<void>;
42
+ /**
43
+ * Connect to AMQP broker
44
+ */
45
+ private init;
33
46
  }
34
- /**
35
- * Options for creating a client
36
- */
37
- interface CreateClientOptions<TContract extends ContractDefinition> {
38
- contract: TContract;
39
- connection: ChannelModel;
40
- }
41
- /**
42
- * Create a type-safe AMQP client from a contract
43
- * The client will automatically connect to the AMQP broker
44
- */
45
- declare function createClient<TContract extends ContractDefinition>(options: CreateClientOptions<TContract>): Promise<AmqpClient<TContract>>;
46
47
  //#endregion
47
- export { AmqpClient, type CreateClientOptions, type PublishOptions, createClient };
48
+ export { type CreateClientOptions, type PublishOptions, TypedAmqpClient };
48
49
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/client.ts"],"sourcesContent":[],"mappings":";;;;;;;AAUA;AAQa,UARI,cAAA,CAQM;EAAmB,UAAA,CAAA,EAAA,MAAA;EAID,OAAA,CAAA,EAV7B,OAAA,CAAQ,OAUqB;;;;;AAkDtB,cAtDN,UAsDM,CAAA,kBAtDuB,kBAsDvB,CAAA,CAAA;EACoB,iBAAA,QAAA;EAAW,QAAA,OAAA;EAArC,QAAA,UAAA;EACC,WAAA,CAAA,QAAA,EApD2B,SAoD3B;EACT;;;EA8DY,OAAA,CAAA,UAAA,EA9GW,YA8GQ,CAAA,EA9GO,OA8GP,CAAA,IAAA,CAAA;EAAmB;;;EAE7B,OAAA,CAAA,cApEI,mBAoEJ,CApEwB,SAoExB,CAAA,CAAA,CAAA,aAAA,EAnEP,KAmEO,EAAA,OAAA,EAlEb,yBAkEa,CAlEa,SAkEb,EAlEwB,KAkExB,CAAA,EAAA,OAAA,CAAA,EAjEZ,cAiEY,CAAA,EAhErB,OAgEqB,CAAA,OAAA,CAAA;EAOJ;;;EACX,KAAA,CAAA,CAAA,EAzBM,OAyBN,CAAA,IAAA,CAAA;;;;;UAVM,sCAAsC;YAC3C;cACE;;;;;;iBAOQ,+BAA+B,6BAC1C,oBAAoB,aAC5B,QAAQ,WAAW"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/client.ts"],"sourcesContent":[],"mappings":";;;;;;;AAWA;AAAuD,UAAtC,mBAAsC,CAAA,kBAAA,kBAAA,CAAA,CAAA;EAC3C,QAAA,EAAA,SAAA;EACW,UAAQ,EAAA,MAAA,GAAR,OAAA,CAAQ,OAAA;;AAM/B;AAQA;;AAawC,UArBvB,cAAA,CAqBuB;EACP,UAAA,CAAA,EAAA,MAAA;EAApB,OAAA,CAAA,EApBD,OAAA,CAAQ,OAoBP;;;;;AAUiB,cAxBjB,eAwBiB,CAAA,kBAxBiB,kBAwBjB,CAAA,CAAA;EACX,iBAAA,QAAA;EACoB,iBAAA,iBAAA;EAAW,QAAA,OAAA;EAArC,QAAA,UAAA;EACC,QAAA,WAAA,CAAA;EACT;;;;kCAfmC,6BAC3B,oBAAoB,aAC5B,QAAQ,gBAAgB;;;;wBASC,oBAAoB,2BAC/B,gBACN,0BAA0B,WAAW,kBACpC,iBACT;;;;WAiDY"}
package/dist/index.mjs CHANGED
@@ -1,38 +1,30 @@
1
+ import { connect } from "amqplib";
2
+
1
3
  //#region src/client.ts
2
4
  /**
3
5
  * Type-safe AMQP client for publishing messages
4
6
  */
5
- var AmqpClient = class {
7
+ var TypedAmqpClient = class TypedAmqpClient {
6
8
  channel = null;
7
9
  connection = null;
8
- constructor(contract) {
10
+ constructor(contract, connectionOptions) {
9
11
  this.contract = contract;
12
+ this.connectionOptions = connectionOptions;
10
13
  }
11
14
  /**
12
- * Connect to AMQP broker
15
+ * Create a type-safe AMQP client from a contract
16
+ * The client will automatically connect to the AMQP broker
13
17
  */
14
- async connect(connection) {
15
- this.connection = connection;
16
- this.channel = await connection.createChannel();
17
- if (this.contract.exchanges && this.channel) for (const exchange of Object.values(this.contract.exchanges)) await this.channel.assertExchange(exchange.name, exchange.type, {
18
- durable: exchange.durable,
19
- autoDelete: exchange.autoDelete,
20
- internal: exchange.internal,
21
- arguments: exchange.arguments
22
- });
23
- if (this.contract.queues && this.channel) for (const queue of Object.values(this.contract.queues)) await this.channel.assertQueue(queue.name, {
24
- durable: queue.durable,
25
- exclusive: queue.exclusive,
26
- autoDelete: queue.autoDelete,
27
- arguments: queue.arguments
28
- });
29
- if (this.contract.bindings && this.channel) for (const binding of Object.values(this.contract.bindings)) await this.channel.bindQueue(binding.queue, binding.exchange, binding.routingKey ?? "", binding.arguments);
18
+ static async create(options) {
19
+ const client = new TypedAmqpClient(options.contract, options.connection);
20
+ await client.init();
21
+ return client;
30
22
  }
31
23
  /**
32
24
  * Publish a message using a defined publisher
33
25
  */
34
26
  async publish(publisherName, message, options) {
35
- if (!this.channel) throw new Error("Client not connected. Call connect() first.");
27
+ if (!this.channel) throw new Error("Client not initialized. Create the client using TypedAmqpClient.create() to establish a connection.");
36
28
  const publishers = this.contract.publishers;
37
29
  if (!publishers) throw new Error("No publishers defined in contract");
38
30
  const publisher = publishers[publisherName];
@@ -46,7 +38,7 @@ var AmqpClient = class {
46
38
  return this.channel.publish(publisherDef.exchange, routingKey, content, options?.options);
47
39
  }
48
40
  /**
49
- * Close the connection
41
+ * Close the channel and connection
50
42
  */
51
43
  async close() {
52
44
  if (this.channel) {
@@ -58,17 +50,28 @@ var AmqpClient = class {
58
50
  this.connection = null;
59
51
  }
60
52
  }
53
+ /**
54
+ * Connect to AMQP broker
55
+ */
56
+ async init() {
57
+ this.connection = await connect(this.connectionOptions);
58
+ this.channel = await this.connection.createChannel();
59
+ if (this.contract.exchanges) for (const exchange of Object.values(this.contract.exchanges)) await this.channel.assertExchange(exchange.name, exchange.type, {
60
+ durable: exchange.durable,
61
+ autoDelete: exchange.autoDelete,
62
+ internal: exchange.internal,
63
+ arguments: exchange.arguments
64
+ });
65
+ if (this.contract.queues) for (const queue of Object.values(this.contract.queues)) await this.channel.assertQueue(queue.name, {
66
+ durable: queue.durable,
67
+ exclusive: queue.exclusive,
68
+ autoDelete: queue.autoDelete,
69
+ arguments: queue.arguments
70
+ });
71
+ if (this.contract.bindings) for (const binding of Object.values(this.contract.bindings)) await this.channel.bindQueue(binding.queue, binding.exchange, binding.routingKey ?? "", binding.arguments);
72
+ }
61
73
  };
62
- /**
63
- * Create a type-safe AMQP client from a contract
64
- * The client will automatically connect to the AMQP broker
65
- */
66
- async function createClient(options) {
67
- const client = new AmqpClient(options.contract);
68
- await client.connect(options.connection);
69
- return client;
70
- }
71
74
 
72
75
  //#endregion
73
- export { AmqpClient, createClient };
76
+ export { TypedAmqpClient };
74
77
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["contract: TContract"],"sources":["../src/client.ts"],"sourcesContent":["import type { Channel, ChannelModel, Options } from \"amqplib\";\nimport type {\n ClientInferPublisherInput,\n ContractDefinition,\n InferPublisherNames,\n} from \"@amqp-contract/contract\";\n\n/**\n * Options for publishing a message\n */\nexport interface PublishOptions {\n routingKey?: string;\n options?: Options.Publish;\n}\n\n/**\n * Type-safe AMQP client for publishing messages\n */\nexport class AmqpClient<TContract extends ContractDefinition> {\n private channel: Channel | null = null;\n private connection: ChannelModel | null = null;\n\n constructor(private readonly contract: TContract) {}\n\n /**\n * Connect to AMQP broker\n */\n async connect(connection: ChannelModel): Promise<void> {\n this.connection = connection;\n this.channel = await connection.createChannel();\n\n // Setup exchanges\n if (this.contract.exchanges && this.channel) {\n for (const exchange of Object.values(this.contract.exchanges)) {\n await this.channel.assertExchange(exchange.name, exchange.type, {\n durable: exchange.durable,\n autoDelete: exchange.autoDelete,\n internal: exchange.internal,\n arguments: exchange.arguments,\n });\n }\n }\n\n // Setup queues\n if (this.contract.queues && this.channel) {\n for (const queue of Object.values(this.contract.queues)) {\n await this.channel.assertQueue(queue.name, {\n durable: queue.durable,\n exclusive: queue.exclusive,\n autoDelete: queue.autoDelete,\n arguments: queue.arguments,\n });\n }\n }\n\n // Setup bindings\n if (this.contract.bindings && this.channel) {\n for (const binding of Object.values(this.contract.bindings)) {\n await this.channel.bindQueue(\n binding.queue,\n binding.exchange,\n binding.routingKey ?? \"\",\n binding.arguments,\n );\n }\n }\n }\n\n /**\n * Publish a message using a defined publisher\n */\n async publish<TName extends InferPublisherNames<TContract>>(\n publisherName: TName,\n message: ClientInferPublisherInput<TContract, TName>,\n options?: PublishOptions,\n ): Promise<boolean> {\n if (!this.channel) {\n throw new Error(\"Client not connected. Call connect() first.\");\n }\n\n const publishers = this.contract.publishers as Record<string, unknown>;\n if (!publishers) {\n throw new Error(\"No publishers defined in contract\");\n }\n\n const publisher = publishers[publisherName as string];\n if (!publisher || typeof publisher !== \"object\") {\n throw new Error(`Publisher \"${String(publisherName)}\" not found in contract`);\n }\n\n const publisherDef = publisher as {\n exchange: string;\n routingKey?: string;\n message: { \"~standard\": { validate: (value: unknown) => unknown } };\n };\n\n // Validate message using schema\n const validation = publisherDef.message[\"~standard\"].validate(message);\n if (\n typeof validation === \"object\" &&\n validation !== null &&\n \"issues\" in validation &&\n validation.issues\n ) {\n throw new Error(`Message validation failed: ${JSON.stringify(validation.issues)}`);\n }\n\n const validatedMessage =\n typeof validation === \"object\" && validation !== null && \"value\" in validation\n ? validation.value\n : message;\n\n // Publish message\n const routingKey = options?.routingKey ?? publisherDef.routingKey ?? \"\";\n const content = Buffer.from(JSON.stringify(validatedMessage));\n\n return this.channel.publish(publisherDef.exchange, routingKey, content, options?.options);\n }\n\n /**\n * Close the connection\n */\n async close(): Promise<void> {\n if (this.channel) {\n await this.channel.close();\n this.channel = null;\n }\n if (this.connection) {\n await (this.connection as unknown as { close(): Promise<void> }).close();\n this.connection = null;\n }\n }\n}\n\n/**\n * Options for creating a client\n */\nexport interface CreateClientOptions<TContract extends ContractDefinition> {\n contract: TContract;\n connection: ChannelModel;\n}\n\n/**\n * Create a type-safe AMQP client from a contract\n * The client will automatically connect to the AMQP broker\n */\nexport async function createClient<TContract extends ContractDefinition>(\n options: CreateClientOptions<TContract>,\n): Promise<AmqpClient<TContract>> {\n const client = new AmqpClient(options.contract);\n await client.connect(options.connection);\n return client;\n}\n"],"mappings":";;;;AAkBA,IAAa,aAAb,MAA8D;CAC5D,AAAQ,UAA0B;CAClC,AAAQ,aAAkC;CAE1C,YAAY,AAAiBA,UAAqB;EAArB;;;;;CAK7B,MAAM,QAAQ,YAAyC;AACrD,OAAK,aAAa;AAClB,OAAK,UAAU,MAAM,WAAW,eAAe;AAG/C,MAAI,KAAK,SAAS,aAAa,KAAK,QAClC,MAAK,MAAM,YAAY,OAAO,OAAO,KAAK,SAAS,UAAU,CAC3D,OAAM,KAAK,QAAQ,eAAe,SAAS,MAAM,SAAS,MAAM;GAC9D,SAAS,SAAS;GAClB,YAAY,SAAS;GACrB,UAAU,SAAS;GACnB,WAAW,SAAS;GACrB,CAAC;AAKN,MAAI,KAAK,SAAS,UAAU,KAAK,QAC/B,MAAK,MAAM,SAAS,OAAO,OAAO,KAAK,SAAS,OAAO,CACrD,OAAM,KAAK,QAAQ,YAAY,MAAM,MAAM;GACzC,SAAS,MAAM;GACf,WAAW,MAAM;GACjB,YAAY,MAAM;GAClB,WAAW,MAAM;GAClB,CAAC;AAKN,MAAI,KAAK,SAAS,YAAY,KAAK,QACjC,MAAK,MAAM,WAAW,OAAO,OAAO,KAAK,SAAS,SAAS,CACzD,OAAM,KAAK,QAAQ,UACjB,QAAQ,OACR,QAAQ,UACR,QAAQ,cAAc,IACtB,QAAQ,UACT;;;;;CAQP,MAAM,QACJ,eACA,SACA,SACkB;AAClB,MAAI,CAAC,KAAK,QACR,OAAM,IAAI,MAAM,8CAA8C;EAGhE,MAAM,aAAa,KAAK,SAAS;AACjC,MAAI,CAAC,WACH,OAAM,IAAI,MAAM,oCAAoC;EAGtD,MAAM,YAAY,WAAW;AAC7B,MAAI,CAAC,aAAa,OAAO,cAAc,SACrC,OAAM,IAAI,MAAM,cAAc,OAAO,cAAc,CAAC,yBAAyB;EAG/E,MAAM,eAAe;EAOrB,MAAM,aAAa,aAAa,QAAQ,aAAa,SAAS,QAAQ;AACtE,MACE,OAAO,eAAe,YACtB,eAAe,QACf,YAAY,cACZ,WAAW,OAEX,OAAM,IAAI,MAAM,8BAA8B,KAAK,UAAU,WAAW,OAAO,GAAG;EAGpF,MAAM,mBACJ,OAAO,eAAe,YAAY,eAAe,QAAQ,WAAW,aAChE,WAAW,QACX;EAGN,MAAM,aAAa,SAAS,cAAc,aAAa,cAAc;EACrE,MAAM,UAAU,OAAO,KAAK,KAAK,UAAU,iBAAiB,CAAC;AAE7D,SAAO,KAAK,QAAQ,QAAQ,aAAa,UAAU,YAAY,SAAS,SAAS,QAAQ;;;;;CAM3F,MAAM,QAAuB;AAC3B,MAAI,KAAK,SAAS;AAChB,SAAM,KAAK,QAAQ,OAAO;AAC1B,QAAK,UAAU;;AAEjB,MAAI,KAAK,YAAY;AACnB,SAAO,KAAK,WAAqD,OAAO;AACxE,QAAK,aAAa;;;;;;;;AAiBxB,eAAsB,aACpB,SACgC;CAChC,MAAM,SAAS,IAAI,WAAW,QAAQ,SAAS;AAC/C,OAAM,OAAO,QAAQ,QAAQ,WAAW;AACxC,QAAO"}
1
+ {"version":3,"file":"index.mjs","names":["contract: TContract","connectionOptions: string | Options.Connect"],"sources":["../src/client.ts"],"sourcesContent":["import { connect } from \"amqplib\";\nimport type { Channel, ChannelModel, Options } from \"amqplib\";\nimport type {\n ClientInferPublisherInput,\n ContractDefinition,\n InferPublisherNames,\n} from \"@amqp-contract/contract\";\n\n/**\n * Options for creating a client\n */\nexport interface CreateClientOptions<TContract extends ContractDefinition> {\n contract: TContract;\n connection: string | Options.Connect;\n}\n\n/**\n * Options for publishing a message\n */\nexport interface PublishOptions {\n routingKey?: string;\n options?: Options.Publish;\n}\n\n/**\n * Type-safe AMQP client for publishing messages\n */\nexport class TypedAmqpClient<TContract extends ContractDefinition> {\n private channel: Channel | null = null;\n private connection: ChannelModel | null = null;\n\n private constructor(\n private readonly contract: TContract,\n private readonly connectionOptions: string | Options.Connect,\n ) {}\n\n /**\n * Create a type-safe AMQP client from a contract\n * The client will automatically connect to the AMQP broker\n */\n static async create<TContract extends ContractDefinition>(\n options: CreateClientOptions<TContract>,\n ): Promise<TypedAmqpClient<TContract>> {\n const client = new TypedAmqpClient(options.contract, options.connection);\n await client.init();\n return client;\n }\n\n /**\n * Publish a message using a defined publisher\n */\n async publish<TName extends InferPublisherNames<TContract>>(\n publisherName: TName,\n message: ClientInferPublisherInput<TContract, TName>,\n options?: PublishOptions,\n ): Promise<boolean> {\n if (!this.channel) {\n throw new Error(\n \"Client not initialized. Create the client using TypedAmqpClient.create() to establish a connection.\",\n );\n }\n\n const publishers = this.contract.publishers as Record<string, unknown>;\n if (!publishers) {\n throw new Error(\"No publishers defined in contract\");\n }\n\n const publisher = publishers[publisherName as string];\n if (!publisher || typeof publisher !== \"object\") {\n throw new Error(`Publisher \"${String(publisherName)}\" not found in contract`);\n }\n\n const publisherDef = publisher as {\n exchange: string;\n routingKey?: string;\n message: { \"~standard\": { validate: (value: unknown) => unknown } };\n };\n\n // Validate message using schema\n const validation = publisherDef.message[\"~standard\"].validate(message);\n if (\n typeof validation === \"object\" &&\n validation !== null &&\n \"issues\" in validation &&\n validation.issues\n ) {\n throw new Error(`Message validation failed: ${JSON.stringify(validation.issues)}`);\n }\n\n const validatedMessage =\n typeof validation === \"object\" && validation !== null && \"value\" in validation\n ? validation.value\n : message;\n\n // Publish message\n const routingKey = options?.routingKey ?? publisherDef.routingKey ?? \"\";\n const content = Buffer.from(JSON.stringify(validatedMessage));\n\n return this.channel.publish(publisherDef.exchange, routingKey, content, options?.options);\n }\n\n /**\n * Close the channel and connection\n */\n async close(): Promise<void> {\n if (this.channel) {\n await this.channel.close();\n this.channel = null;\n }\n if (this.connection) {\n await this.connection.close();\n this.connection = null;\n }\n }\n\n /**\n * Connect to AMQP broker\n */\n private async init(): Promise<void> {\n this.connection = await connect(this.connectionOptions);\n this.channel = await this.connection.createChannel();\n\n // Setup exchanges\n if (this.contract.exchanges) {\n for (const exchange of Object.values(this.contract.exchanges)) {\n await this.channel.assertExchange(exchange.name, exchange.type, {\n durable: exchange.durable,\n autoDelete: exchange.autoDelete,\n internal: exchange.internal,\n arguments: exchange.arguments,\n });\n }\n }\n\n // Setup queues\n if (this.contract.queues) {\n for (const queue of Object.values(this.contract.queues)) {\n await this.channel.assertQueue(queue.name, {\n durable: queue.durable,\n exclusive: queue.exclusive,\n autoDelete: queue.autoDelete,\n arguments: queue.arguments,\n });\n }\n }\n\n // Setup bindings\n if (this.contract.bindings) {\n for (const binding of Object.values(this.contract.bindings)) {\n await this.channel.bindQueue(\n binding.queue,\n binding.exchange,\n binding.routingKey ?? \"\",\n binding.arguments,\n );\n }\n }\n }\n}\n"],"mappings":";;;;;;AA2BA,IAAa,kBAAb,MAAa,gBAAsD;CACjE,AAAQ,UAA0B;CAClC,AAAQ,aAAkC;CAE1C,AAAQ,YACN,AAAiBA,UACjB,AAAiBC,mBACjB;EAFiB;EACA;;;;;;CAOnB,aAAa,OACX,SACqC;EACrC,MAAM,SAAS,IAAI,gBAAgB,QAAQ,UAAU,QAAQ,WAAW;AACxE,QAAM,OAAO,MAAM;AACnB,SAAO;;;;;CAMT,MAAM,QACJ,eACA,SACA,SACkB;AAClB,MAAI,CAAC,KAAK,QACR,OAAM,IAAI,MACR,sGACD;EAGH,MAAM,aAAa,KAAK,SAAS;AACjC,MAAI,CAAC,WACH,OAAM,IAAI,MAAM,oCAAoC;EAGtD,MAAM,YAAY,WAAW;AAC7B,MAAI,CAAC,aAAa,OAAO,cAAc,SACrC,OAAM,IAAI,MAAM,cAAc,OAAO,cAAc,CAAC,yBAAyB;EAG/E,MAAM,eAAe;EAOrB,MAAM,aAAa,aAAa,QAAQ,aAAa,SAAS,QAAQ;AACtE,MACE,OAAO,eAAe,YACtB,eAAe,QACf,YAAY,cACZ,WAAW,OAEX,OAAM,IAAI,MAAM,8BAA8B,KAAK,UAAU,WAAW,OAAO,GAAG;EAGpF,MAAM,mBACJ,OAAO,eAAe,YAAY,eAAe,QAAQ,WAAW,aAChE,WAAW,QACX;EAGN,MAAM,aAAa,SAAS,cAAc,aAAa,cAAc;EACrE,MAAM,UAAU,OAAO,KAAK,KAAK,UAAU,iBAAiB,CAAC;AAE7D,SAAO,KAAK,QAAQ,QAAQ,aAAa,UAAU,YAAY,SAAS,SAAS,QAAQ;;;;;CAM3F,MAAM,QAAuB;AAC3B,MAAI,KAAK,SAAS;AAChB,SAAM,KAAK,QAAQ,OAAO;AAC1B,QAAK,UAAU;;AAEjB,MAAI,KAAK,YAAY;AACnB,SAAM,KAAK,WAAW,OAAO;AAC7B,QAAK,aAAa;;;;;;CAOtB,MAAc,OAAsB;AAClC,OAAK,aAAa,MAAM,QAAQ,KAAK,kBAAkB;AACvD,OAAK,UAAU,MAAM,KAAK,WAAW,eAAe;AAGpD,MAAI,KAAK,SAAS,UAChB,MAAK,MAAM,YAAY,OAAO,OAAO,KAAK,SAAS,UAAU,CAC3D,OAAM,KAAK,QAAQ,eAAe,SAAS,MAAM,SAAS,MAAM;GAC9D,SAAS,SAAS;GAClB,YAAY,SAAS;GACrB,UAAU,SAAS;GACnB,WAAW,SAAS;GACrB,CAAC;AAKN,MAAI,KAAK,SAAS,OAChB,MAAK,MAAM,SAAS,OAAO,OAAO,KAAK,SAAS,OAAO,CACrD,OAAM,KAAK,QAAQ,YAAY,MAAM,MAAM;GACzC,SAAS,MAAM;GACf,WAAW,MAAM;GACjB,YAAY,MAAM;GAClB,WAAW,MAAM;GAClB,CAAC;AAKN,MAAI,KAAK,SAAS,SAChB,MAAK,MAAM,WAAW,OAAO,OAAO,KAAK,SAAS,SAAS,CACzD,OAAM,KAAK,QAAQ,UACjB,QAAQ,OACR,QAAQ,UACR,QAAQ,cAAc,IACtB,QAAQ,UACT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amqp-contract/client",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "Client utilities for publishing messages using amqp-contract",
5
5
  "keywords": [
6
6
  "amqp",
@@ -41,7 +41,7 @@
41
41
  "dist"
42
42
  ],
43
43
  "dependencies": {
44
- "@amqp-contract/contract": "0.0.4"
44
+ "@amqp-contract/contract": "0.0.6"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@types/amqplib": "0.10.8",
@@ -52,7 +52,7 @@
52
52
  "typescript": "5.9.3",
53
53
  "vitest": "4.0.16",
54
54
  "zod": "4.2.1",
55
- "@amqp-contract/testing": "0.0.4",
55
+ "@amqp-contract/testing": "0.0.6",
56
56
  "@amqp-contract/tsconfig": "0.0.0"
57
57
  },
58
58
  "peerDependencies": {