@amqp-contract/asyncapi 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,12 @@
1
1
  # @amqp-contract/asyncapi
2
2
 
3
- AsyncAPI 3.0.0 specification generator for amqp-contract.
3
+ **AsyncAPI 3.0.0 specification generator for amqp-contract.**
4
+
5
+ [![CI](https://github.com/btravers/amqp-contract/actions/workflows/ci.yml/badge.svg)](https://github.com/btravers/amqp-contract/actions/workflows/ci.yml)
6
+ [![npm version](https://img.shields.io/npm/v/@amqp-contract/asyncapi.svg?logo=npm)](https://www.npmjs.com/package/@amqp-contract/asyncapi)
7
+ [![npm downloads](https://img.shields.io/npm/dm/@amqp-contract/asyncapi.svg)](https://www.npmjs.com/package/@amqp-contract/asyncapi)
8
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue?logo=typescript)](https://www.typescriptlang.org/)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
10
 
5
11
  📖 **[Full documentation →](https://btravers.github.io/amqp-contract/api/asyncapi)**
6
12
 
@@ -68,6 +74,10 @@ Generate an AsyncAPI 3.0.0 specification from an AMQP contract.
68
74
  - ✅ Message schemas from Zod schemas
69
75
  - ✅ AMQP protocol bindings
70
76
 
77
+ ## Documentation
78
+
79
+ 📖 **[Read the full documentation →](https://btravers.github.io/amqp-contract)**
80
+
71
81
  ## License
72
82
 
73
83
  MIT
package/dist/index.cjs CHANGED
@@ -1,12 +1,89 @@
1
1
 
2
2
  //#region src/index.ts
3
+ /**
4
+ * Generator for creating AsyncAPI 3.0 documentation from AMQP contracts.
5
+ *
6
+ * This class converts contract definitions into AsyncAPI 3.0 specification documents,
7
+ * which can be used for API documentation, code generation, and tooling integration.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { AsyncAPIGenerator } from '@amqp-contract/asyncapi';
12
+ * import { zodToJsonSchema } from '@orpc/zod';
13
+ * import { z } from 'zod';
14
+ *
15
+ * const contract = defineContract({
16
+ * exchanges: {
17
+ * orders: defineExchange('orders', 'topic', { durable: true })
18
+ * },
19
+ * publishers: {
20
+ * orderCreated: definePublisher('orders', z.object({
21
+ * orderId: z.string(),
22
+ * amount: z.number()
23
+ * }), {
24
+ * routingKey: 'order.created'
25
+ * })
26
+ * }
27
+ * });
28
+ *
29
+ * const generator = new AsyncAPIGenerator({
30
+ * schemaConverters: [zodToJsonSchema]
31
+ * });
32
+ *
33
+ * const asyncapi = await generator.generate(contract, {
34
+ * id: 'urn:com:example:order-service',
35
+ * info: {
36
+ * title: 'Order Service API',
37
+ * version: '1.0.0',
38
+ * description: 'Async API for order processing'
39
+ * },
40
+ * servers: {
41
+ * production: {
42
+ * host: 'rabbitmq.example.com',
43
+ * protocol: 'amqp',
44
+ * protocolVersion: '0.9.1'
45
+ * }
46
+ * }
47
+ * });
48
+ * ```
49
+ */
3
50
  var AsyncAPIGenerator = class {
4
51
  converters;
52
+ /**
53
+ * Create a new AsyncAPI generator instance.
54
+ *
55
+ * @param options - Configuration options including schema converters
56
+ */
5
57
  constructor(options = {}) {
6
58
  this.converters = options.schemaConverters ?? [];
7
59
  }
8
60
  /**
9
- * Generate an AsyncAPI 3.0 document from a contract definition
61
+ * Generate an AsyncAPI 3.0 document from a contract definition.
62
+ *
63
+ * Converts AMQP exchanges, queues, publishers, and consumers into
64
+ * AsyncAPI channels, operations, and messages with proper JSON Schema
65
+ * validation definitions.
66
+ *
67
+ * @param contract - The AMQP contract definition to convert
68
+ * @param options - AsyncAPI document metadata (id, info, servers)
69
+ * @returns Promise resolving to a complete AsyncAPI 3.0 document
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * const asyncapi = await generator.generate(contract, {
74
+ * id: 'urn:com:example:api',
75
+ * info: {
76
+ * title: 'My API',
77
+ * version: '1.0.0'
78
+ * },
79
+ * servers: {
80
+ * dev: {
81
+ * host: 'localhost:5672',
82
+ * protocol: 'amqp'
83
+ * }
84
+ * }
85
+ * });
86
+ * ```
10
87
  */
11
88
  async generate(contract, options) {
12
89
  const convertedChannels = {};
@@ -68,8 +145,7 @@ var AsyncAPIGenerator = class {
68
145
  action: "receive",
69
146
  channel: { $ref: `#/channels/${queueName}` },
70
147
  messages: [{ $ref: `#/channels/${queueName}/messages/${messageName}` }],
71
- summary: `Consume from ${consumer.queue.name}`,
72
- ...consumer.prefetch && { description: `Prefetch: ${consumer.prefetch}` }
148
+ summary: `Consume from ${consumer.queue.name}`
73
149
  };
74
150
  }
75
151
  return {
package/dist/index.d.cts CHANGED
@@ -3,15 +3,114 @@ import { AsyncAPIObject } from "@asyncapi/parser/esm/spec-types/v3";
3
3
  import { ContractDefinition } from "@amqp-contract/contract";
4
4
 
5
5
  //#region src/index.d.ts
6
+
7
+ /**
8
+ * Options for configuring the AsyncAPI generator.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { AsyncAPIGenerator } from '@amqp-contract/asyncapi';
13
+ * import { zodToJsonSchema } from '@orpc/zod';
14
+ *
15
+ * const generator = new AsyncAPIGenerator({
16
+ * schemaConverters: [zodToJsonSchema]
17
+ * });
18
+ * ```
19
+ */
6
20
  interface AsyncAPIGeneratorOptions {
21
+ /**
22
+ * Schema converters for transforming validation schemas to JSON Schema.
23
+ * Supports Zod, Valibot, ArkType, and other Standard Schema v1 compatible libraries.
24
+ */
7
25
  schemaConverters?: ConditionalSchemaConverter[];
8
26
  }
27
+ /**
28
+ * Options for generating an AsyncAPI document.
29
+ * These correspond to the top-level AsyncAPI document fields.
30
+ */
9
31
  type AsyncAPIGeneratorGenerateOptions = Pick<AsyncAPIObject, "id" | "info" | "servers">;
32
+ /**
33
+ * Generator for creating AsyncAPI 3.0 documentation from AMQP contracts.
34
+ *
35
+ * This class converts contract definitions into AsyncAPI 3.0 specification documents,
36
+ * which can be used for API documentation, code generation, and tooling integration.
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * import { AsyncAPIGenerator } from '@amqp-contract/asyncapi';
41
+ * import { zodToJsonSchema } from '@orpc/zod';
42
+ * import { z } from 'zod';
43
+ *
44
+ * const contract = defineContract({
45
+ * exchanges: {
46
+ * orders: defineExchange('orders', 'topic', { durable: true })
47
+ * },
48
+ * publishers: {
49
+ * orderCreated: definePublisher('orders', z.object({
50
+ * orderId: z.string(),
51
+ * amount: z.number()
52
+ * }), {
53
+ * routingKey: 'order.created'
54
+ * })
55
+ * }
56
+ * });
57
+ *
58
+ * const generator = new AsyncAPIGenerator({
59
+ * schemaConverters: [zodToJsonSchema]
60
+ * });
61
+ *
62
+ * const asyncapi = await generator.generate(contract, {
63
+ * id: 'urn:com:example:order-service',
64
+ * info: {
65
+ * title: 'Order Service API',
66
+ * version: '1.0.0',
67
+ * description: 'Async API for order processing'
68
+ * },
69
+ * servers: {
70
+ * production: {
71
+ * host: 'rabbitmq.example.com',
72
+ * protocol: 'amqp',
73
+ * protocolVersion: '0.9.1'
74
+ * }
75
+ * }
76
+ * });
77
+ * ```
78
+ */
10
79
  declare class AsyncAPIGenerator {
11
80
  private readonly converters;
81
+ /**
82
+ * Create a new AsyncAPI generator instance.
83
+ *
84
+ * @param options - Configuration options including schema converters
85
+ */
12
86
  constructor(options?: AsyncAPIGeneratorOptions);
13
87
  /**
14
- * Generate an AsyncAPI 3.0 document from a contract definition
88
+ * Generate an AsyncAPI 3.0 document from a contract definition.
89
+ *
90
+ * Converts AMQP exchanges, queues, publishers, and consumers into
91
+ * AsyncAPI channels, operations, and messages with proper JSON Schema
92
+ * validation definitions.
93
+ *
94
+ * @param contract - The AMQP contract definition to convert
95
+ * @param options - AsyncAPI document metadata (id, info, servers)
96
+ * @returns Promise resolving to a complete AsyncAPI 3.0 document
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * const asyncapi = await generator.generate(contract, {
101
+ * id: 'urn:com:example:api',
102
+ * info: {
103
+ * title: 'My API',
104
+ * version: '1.0.0'
105
+ * },
106
+ * servers: {
107
+ * dev: {
108
+ * host: 'localhost:5672',
109
+ * protocol: 'amqp'
110
+ * }
111
+ * }
112
+ * });
113
+ * ```
15
114
  */
16
115
  generate(contract: ContractDefinition, options: AsyncAPIGeneratorGenerateOptions): Promise<AsyncAPIObject>;
17
116
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;UAiBiB,wBAAA;qBACI;AADrB;AAIY,KAAA,gCAAA,GAAmC,IAAK,CAAA,cAAL,EAAA,IAAI,GAAA,MAAA,GAAA,SAAA,CAAA;AAEtC,cAAA,iBAAA,CAAiB;EAGP,iBAAA,UAAA;EAQT,WAAA,CAAA,OAAA,CAAA,EARS,wBAQT;EACD;;;EACD,QAAA,CAAA,QAAA,EAFE,kBAEF,EAAA,OAAA,EADC,gCACD,CAAA,EAAP,OAAO,CAAC,cAAD,CAAA"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;AA8BA;AAYA;AAiDA;;;;;;;;;UA7DiB,wBAAA;;;;;qBAKI;;;;;;KAOT,gCAAA,GAAmC,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAiDvC,iBAAA;;;;;;;wBAQU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAiCT,6BACD,mCACR,QAAQ"}
package/dist/index.d.mts CHANGED
@@ -3,15 +3,114 @@ import { AsyncAPIObject } from "@asyncapi/parser/esm/spec-types/v3";
3
3
  import { ContractDefinition } from "@amqp-contract/contract";
4
4
 
5
5
  //#region src/index.d.ts
6
+
7
+ /**
8
+ * Options for configuring the AsyncAPI generator.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { AsyncAPIGenerator } from '@amqp-contract/asyncapi';
13
+ * import { zodToJsonSchema } from '@orpc/zod';
14
+ *
15
+ * const generator = new AsyncAPIGenerator({
16
+ * schemaConverters: [zodToJsonSchema]
17
+ * });
18
+ * ```
19
+ */
6
20
  interface AsyncAPIGeneratorOptions {
21
+ /**
22
+ * Schema converters for transforming validation schemas to JSON Schema.
23
+ * Supports Zod, Valibot, ArkType, and other Standard Schema v1 compatible libraries.
24
+ */
7
25
  schemaConverters?: ConditionalSchemaConverter[];
8
26
  }
27
+ /**
28
+ * Options for generating an AsyncAPI document.
29
+ * These correspond to the top-level AsyncAPI document fields.
30
+ */
9
31
  type AsyncAPIGeneratorGenerateOptions = Pick<AsyncAPIObject, "id" | "info" | "servers">;
32
+ /**
33
+ * Generator for creating AsyncAPI 3.0 documentation from AMQP contracts.
34
+ *
35
+ * This class converts contract definitions into AsyncAPI 3.0 specification documents,
36
+ * which can be used for API documentation, code generation, and tooling integration.
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * import { AsyncAPIGenerator } from '@amqp-contract/asyncapi';
41
+ * import { zodToJsonSchema } from '@orpc/zod';
42
+ * import { z } from 'zod';
43
+ *
44
+ * const contract = defineContract({
45
+ * exchanges: {
46
+ * orders: defineExchange('orders', 'topic', { durable: true })
47
+ * },
48
+ * publishers: {
49
+ * orderCreated: definePublisher('orders', z.object({
50
+ * orderId: z.string(),
51
+ * amount: z.number()
52
+ * }), {
53
+ * routingKey: 'order.created'
54
+ * })
55
+ * }
56
+ * });
57
+ *
58
+ * const generator = new AsyncAPIGenerator({
59
+ * schemaConverters: [zodToJsonSchema]
60
+ * });
61
+ *
62
+ * const asyncapi = await generator.generate(contract, {
63
+ * id: 'urn:com:example:order-service',
64
+ * info: {
65
+ * title: 'Order Service API',
66
+ * version: '1.0.0',
67
+ * description: 'Async API for order processing'
68
+ * },
69
+ * servers: {
70
+ * production: {
71
+ * host: 'rabbitmq.example.com',
72
+ * protocol: 'amqp',
73
+ * protocolVersion: '0.9.1'
74
+ * }
75
+ * }
76
+ * });
77
+ * ```
78
+ */
10
79
  declare class AsyncAPIGenerator {
11
80
  private readonly converters;
81
+ /**
82
+ * Create a new AsyncAPI generator instance.
83
+ *
84
+ * @param options - Configuration options including schema converters
85
+ */
12
86
  constructor(options?: AsyncAPIGeneratorOptions);
13
87
  /**
14
- * Generate an AsyncAPI 3.0 document from a contract definition
88
+ * Generate an AsyncAPI 3.0 document from a contract definition.
89
+ *
90
+ * Converts AMQP exchanges, queues, publishers, and consumers into
91
+ * AsyncAPI channels, operations, and messages with proper JSON Schema
92
+ * validation definitions.
93
+ *
94
+ * @param contract - The AMQP contract definition to convert
95
+ * @param options - AsyncAPI document metadata (id, info, servers)
96
+ * @returns Promise resolving to a complete AsyncAPI 3.0 document
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * const asyncapi = await generator.generate(contract, {
101
+ * id: 'urn:com:example:api',
102
+ * info: {
103
+ * title: 'My API',
104
+ * version: '1.0.0'
105
+ * },
106
+ * servers: {
107
+ * dev: {
108
+ * host: 'localhost:5672',
109
+ * protocol: 'amqp'
110
+ * }
111
+ * }
112
+ * });
113
+ * ```
15
114
  */
16
115
  generate(contract: ContractDefinition, options: AsyncAPIGeneratorGenerateOptions): Promise<AsyncAPIObject>;
17
116
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;UAiBiB,wBAAA;qBACI;AADrB;AAIY,KAAA,gCAAA,GAAmC,IAAK,CAAA,cAAL,EAAA,IAAI,GAAA,MAAA,GAAA,SAAA,CAAA;AAEtC,cAAA,iBAAA,CAAiB;EAGP,iBAAA,UAAA;EAQT,WAAA,CAAA,OAAA,CAAA,EARS,wBAQT;EACD;;;EACD,QAAA,CAAA,QAAA,EAFE,kBAEF,EAAA,OAAA,EADC,gCACD,CAAA,EAAP,OAAO,CAAC,cAAD,CAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;AA8BA;AAYA;AAiDA;;;;;;;;;UA7DiB,wBAAA;;;;;qBAKI;;;;;;KAOT,gCAAA,GAAmC,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAiDvC,iBAAA;;;;;;;wBAQU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAiCT,6BACD,mCACR,QAAQ"}
package/dist/index.mjs CHANGED
@@ -1,11 +1,88 @@
1
1
  //#region src/index.ts
2
+ /**
3
+ * Generator for creating AsyncAPI 3.0 documentation from AMQP contracts.
4
+ *
5
+ * This class converts contract definitions into AsyncAPI 3.0 specification documents,
6
+ * which can be used for API documentation, code generation, and tooling integration.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { AsyncAPIGenerator } from '@amqp-contract/asyncapi';
11
+ * import { zodToJsonSchema } from '@orpc/zod';
12
+ * import { z } from 'zod';
13
+ *
14
+ * const contract = defineContract({
15
+ * exchanges: {
16
+ * orders: defineExchange('orders', 'topic', { durable: true })
17
+ * },
18
+ * publishers: {
19
+ * orderCreated: definePublisher('orders', z.object({
20
+ * orderId: z.string(),
21
+ * amount: z.number()
22
+ * }), {
23
+ * routingKey: 'order.created'
24
+ * })
25
+ * }
26
+ * });
27
+ *
28
+ * const generator = new AsyncAPIGenerator({
29
+ * schemaConverters: [zodToJsonSchema]
30
+ * });
31
+ *
32
+ * const asyncapi = await generator.generate(contract, {
33
+ * id: 'urn:com:example:order-service',
34
+ * info: {
35
+ * title: 'Order Service API',
36
+ * version: '1.0.0',
37
+ * description: 'Async API for order processing'
38
+ * },
39
+ * servers: {
40
+ * production: {
41
+ * host: 'rabbitmq.example.com',
42
+ * protocol: 'amqp',
43
+ * protocolVersion: '0.9.1'
44
+ * }
45
+ * }
46
+ * });
47
+ * ```
48
+ */
2
49
  var AsyncAPIGenerator = class {
3
50
  converters;
51
+ /**
52
+ * Create a new AsyncAPI generator instance.
53
+ *
54
+ * @param options - Configuration options including schema converters
55
+ */
4
56
  constructor(options = {}) {
5
57
  this.converters = options.schemaConverters ?? [];
6
58
  }
7
59
  /**
8
- * Generate an AsyncAPI 3.0 document from a contract definition
60
+ * Generate an AsyncAPI 3.0 document from a contract definition.
61
+ *
62
+ * Converts AMQP exchanges, queues, publishers, and consumers into
63
+ * AsyncAPI channels, operations, and messages with proper JSON Schema
64
+ * validation definitions.
65
+ *
66
+ * @param contract - The AMQP contract definition to convert
67
+ * @param options - AsyncAPI document metadata (id, info, servers)
68
+ * @returns Promise resolving to a complete AsyncAPI 3.0 document
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * const asyncapi = await generator.generate(contract, {
73
+ * id: 'urn:com:example:api',
74
+ * info: {
75
+ * title: 'My API',
76
+ * version: '1.0.0'
77
+ * },
78
+ * servers: {
79
+ * dev: {
80
+ * host: 'localhost:5672',
81
+ * protocol: 'amqp'
82
+ * }
83
+ * }
84
+ * });
85
+ * ```
9
86
  */
10
87
  async generate(contract, options) {
11
88
  const convertedChannels = {};
@@ -67,8 +144,7 @@ var AsyncAPIGenerator = class {
67
144
  action: "receive",
68
145
  channel: { $ref: `#/channels/${queueName}` },
69
146
  messages: [{ $ref: `#/channels/${queueName}/messages/${messageName}` }],
70
- summary: `Consume from ${consumer.queue.name}`,
71
- ...consumer.prefetch && { description: `Prefetch: ${consumer.prefetch}` }
147
+ summary: `Consume from ${consumer.queue.name}`
72
148
  };
73
149
  }
74
150
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["convertedChannels: ChannelsObject","convertedOperations: OperationsObject","convertedMessages: MessagesObject","channelMessages: MessagesObject","channel: ChannelObject","result: Record<string, unknown>"],"sources":["../src/index.ts"],"sourcesContent":["import { ConditionalSchemaConverter, JSONSchema } from \"@orpc/openapi\";\nimport {\n AsyncAPIObject,\n ChannelsObject,\n OperationsObject,\n MessagesObject,\n MessageObject,\n ChannelObject,\n} from \"@asyncapi/parser/esm/spec-types/v3\";\nimport type {\n ContractDefinition,\n MessageDefinition,\n QueueDefinition,\n ExchangeDefinition,\n} from \"@amqp-contract/contract\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nexport interface AsyncAPIGeneratorOptions {\n schemaConverters?: ConditionalSchemaConverter[];\n}\n\nexport type AsyncAPIGeneratorGenerateOptions = Pick<AsyncAPIObject, \"id\" | \"info\" | \"servers\">;\n\nexport class AsyncAPIGenerator {\n private readonly converters: ConditionalSchemaConverter[];\n\n constructor(options: AsyncAPIGeneratorOptions = {}) {\n this.converters = options.schemaConverters ?? [];\n }\n\n /**\n * Generate an AsyncAPI 3.0 document from a contract definition\n */\n async generate(\n contract: ContractDefinition,\n options: AsyncAPIGeneratorGenerateOptions,\n ): Promise<AsyncAPIObject> {\n const convertedChannels: ChannelsObject = {};\n const convertedOperations: OperationsObject = {};\n const convertedMessages: MessagesObject = {};\n\n // First, collect all messages from publishers and consumers\n const publisherMessages = new Map<string, { message: MessageDefinition; channelKey: string }>();\n const consumerMessages = new Map<string, { message: MessageDefinition; channelKey: string }>();\n\n // Collect messages from publishers\n if (contract.publishers) {\n for (const [publisherName, publisher] of Object.entries(contract.publishers)) {\n const channelKey = this.getExchangeName(publisher.exchange, contract);\n publisherMessages.set(publisherName, { message: publisher.message, channelKey });\n }\n }\n\n // Collect messages from consumers\n if (contract.consumers) {\n for (const [consumerName, consumer] of Object.entries(contract.consumers)) {\n const channelKey = this.getQueueName(consumer.queue, contract);\n consumerMessages.set(consumerName, { message: consumer.message, channelKey });\n }\n }\n\n // Generate channels from queues with their messages\n if (contract.queues) {\n for (const [queueName, queue] of Object.entries(contract.queues)) {\n const channelMessages: MessagesObject = {};\n\n // Add messages from consumers that reference this queue\n for (const [consumerName, { message, channelKey }] of consumerMessages) {\n if (channelKey === queueName) {\n const messageName = `${consumerName}Message`;\n channelMessages[messageName] = await this.convertMessage(message);\n convertedMessages[messageName] = await this.convertMessage(message);\n }\n }\n\n const channel: ChannelObject = {\n ...this.queueToChannel(queue),\n };\n\n if (Object.keys(channelMessages).length > 0) {\n channel.messages = channelMessages;\n }\n\n convertedChannels[queueName] = channel;\n }\n }\n\n // Generate channels from exchanges with their messages\n if (contract.exchanges) {\n for (const [exchangeName, exchange] of Object.entries(contract.exchanges)) {\n const channelMessages: MessagesObject = {};\n\n // Add messages from publishers that reference this exchange\n for (const [publisherName, { message, channelKey }] of publisherMessages) {\n if (channelKey === exchangeName) {\n const messageName = `${publisherName}Message`;\n channelMessages[messageName] = await this.convertMessage(message);\n convertedMessages[messageName] = await this.convertMessage(message);\n }\n }\n\n const channel: ChannelObject = {\n ...this.exchangeToChannel(exchange),\n };\n\n if (Object.keys(channelMessages).length > 0) {\n channel.messages = channelMessages;\n }\n\n convertedChannels[exchangeName] = channel;\n }\n }\n\n // Generate publish operations from publishers\n if (contract.publishers) {\n for (const [publisherName, publisher] of Object.entries(contract.publishers)) {\n const exchangeName = this.getExchangeName(publisher.exchange, contract);\n const messageName = `${publisherName}Message`;\n\n convertedOperations[publisherName] = {\n action: \"send\",\n channel: { $ref: `#/channels/${exchangeName}` },\n messages: [{ $ref: `#/channels/${exchangeName}/messages/${messageName}` }],\n summary: `Publish to ${publisher.exchange.name}`,\n ...(publisher.routingKey && {\n description: `Routing key: ${publisher.routingKey}`,\n }),\n };\n }\n }\n\n // Generate receive operations from consumers\n if (contract.consumers) {\n for (const [consumerName, consumer] of Object.entries(contract.consumers)) {\n const queueName = this.getQueueName(consumer.queue, contract);\n const messageName = `${consumerName}Message`;\n\n convertedOperations[consumerName] = {\n action: \"receive\",\n channel: { $ref: `#/channels/${queueName}` },\n messages: [{ $ref: `#/channels/${queueName}/messages/${messageName}` }],\n summary: `Consume from ${consumer.queue.name}`,\n ...(consumer.prefetch && {\n description: `Prefetch: ${consumer.prefetch}`,\n }),\n };\n }\n }\n\n return {\n ...options,\n asyncapi: \"3.0.0\",\n channels: convertedChannels,\n operations: convertedOperations,\n components: {\n messages: convertedMessages,\n },\n };\n }\n\n /**\n * Convert a message definition to AsyncAPI MessageObject\n */\n private async convertMessage(message: MessageDefinition): Promise<MessageObject> {\n const payload = message.payload;\n\n // Convert payload schema\n const payloadJsonSchema = await this.convertSchema(payload, \"input\");\n\n // Build result with required properties\n const result: Record<string, unknown> = {\n payload: payloadJsonSchema,\n contentType: \"application/json\",\n };\n\n // Add optional properties only if they exist\n if (message.headers) {\n const headersJsonSchema = await this.convertSchema(message.headers, \"input\");\n if (headersJsonSchema) {\n result[\"headers\"] = headersJsonSchema;\n }\n }\n\n if (message.summary) {\n result[\"summary\"] = message.summary;\n }\n\n if (message.description) {\n result[\"description\"] = message.description;\n }\n\n return result as MessageObject;\n }\n\n /**\n * Convert a queue definition to AsyncAPI ChannelObject\n */\n private queueToChannel(queue: QueueDefinition): ChannelObject {\n const result: Record<string, unknown> = {\n address: queue.name,\n title: queue.name,\n description: `AMQP Queue: ${queue.name}`,\n bindings: {\n amqp: {\n is: \"queue\",\n queue: {\n name: queue.name,\n durable: queue.durable ?? false,\n exclusive: queue.exclusive ?? false,\n autoDelete: queue.autoDelete ?? false,\n ...(queue.arguments && { vhost: \"/\" }),\n },\n },\n },\n };\n\n return result as ChannelObject;\n }\n\n /**\n * Convert an exchange definition to AsyncAPI ChannelObject\n */\n private exchangeToChannel(exchange: ExchangeDefinition): ChannelObject {\n const result: Record<string, unknown> = {\n address: exchange.name,\n title: exchange.name,\n description: `AMQP Exchange: ${exchange.name} (${exchange.type})`,\n bindings: {\n amqp: {\n is: \"routingKey\",\n exchange: {\n name: exchange.name,\n type: exchange.type,\n durable: exchange.durable ?? false,\n autoDelete: exchange.autoDelete ?? false,\n ...(exchange.arguments && { vhost: \"/\" }),\n },\n },\n },\n };\n\n return result as ChannelObject;\n }\n\n /**\n * Get the name/key of an exchange from the contract\n */\n private getExchangeName(exchange: ExchangeDefinition, contract: ContractDefinition): string {\n if (contract.exchanges) {\n for (const [name, ex] of Object.entries(contract.exchanges)) {\n if (ex === exchange || ex.name === exchange.name) {\n return name;\n }\n }\n }\n return exchange.name;\n }\n\n /**\n * Get the name/key of a queue from the contract\n */\n private getQueueName(queue: QueueDefinition, contract: ContractDefinition): string {\n if (contract.queues) {\n for (const [name, q] of Object.entries(contract.queues)) {\n if (q === queue || q.name === queue.name) {\n return name;\n }\n }\n }\n return queue.name;\n }\n\n /**\n * Convert a Standard Schema to JSON Schema using oRPC converters\n */\n private async convertSchema(\n schema: StandardSchemaV1,\n strategy: \"input\" | \"output\",\n ): Promise<JSONSchema> {\n // Try each converter until one matches\n for (const converter of this.converters) {\n const matches = await converter.condition(schema, { strategy });\n if (matches) {\n const [_required, jsonSchema] = await converter.convert(schema, { strategy });\n return jsonSchema;\n }\n }\n\n // If no converter matches, return a generic object schema\n // This allows the contract to still be generated even without schema converters\n return { type: \"object\" };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["convertedChannels: ChannelsObject","convertedOperations: OperationsObject","convertedMessages: MessagesObject","channelMessages: MessagesObject","channel: ChannelObject","result: Record<string, unknown>"],"sources":["../src/index.ts"],"sourcesContent":["import { ConditionalSchemaConverter, JSONSchema } from \"@orpc/openapi\";\nimport {\n AsyncAPIObject,\n ChannelsObject,\n OperationsObject,\n MessagesObject,\n MessageObject,\n ChannelObject,\n} from \"@asyncapi/parser/esm/spec-types/v3\";\nimport type {\n ContractDefinition,\n MessageDefinition,\n QueueDefinition,\n ExchangeDefinition,\n} from \"@amqp-contract/contract\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\n/**\n * Options for configuring the AsyncAPI generator.\n *\n * @example\n * ```typescript\n * import { AsyncAPIGenerator } from '@amqp-contract/asyncapi';\n * import { zodToJsonSchema } from '@orpc/zod';\n *\n * const generator = new AsyncAPIGenerator({\n * schemaConverters: [zodToJsonSchema]\n * });\n * ```\n */\nexport interface AsyncAPIGeneratorOptions {\n /**\n * Schema converters for transforming validation schemas to JSON Schema.\n * Supports Zod, Valibot, ArkType, and other Standard Schema v1 compatible libraries.\n */\n schemaConverters?: ConditionalSchemaConverter[];\n}\n\n/**\n * Options for generating an AsyncAPI document.\n * These correspond to the top-level AsyncAPI document fields.\n */\nexport type AsyncAPIGeneratorGenerateOptions = Pick<AsyncAPIObject, \"id\" | \"info\" | \"servers\">;\n\n/**\n * Generator for creating AsyncAPI 3.0 documentation from AMQP contracts.\n *\n * This class converts contract definitions into AsyncAPI 3.0 specification documents,\n * which can be used for API documentation, code generation, and tooling integration.\n *\n * @example\n * ```typescript\n * import { AsyncAPIGenerator } from '@amqp-contract/asyncapi';\n * import { zodToJsonSchema } from '@orpc/zod';\n * import { z } from 'zod';\n *\n * const contract = defineContract({\n * exchanges: {\n * orders: defineExchange('orders', 'topic', { durable: true })\n * },\n * publishers: {\n * orderCreated: definePublisher('orders', z.object({\n * orderId: z.string(),\n * amount: z.number()\n * }), {\n * routingKey: 'order.created'\n * })\n * }\n * });\n *\n * const generator = new AsyncAPIGenerator({\n * schemaConverters: [zodToJsonSchema]\n * });\n *\n * const asyncapi = await generator.generate(contract, {\n * id: 'urn:com:example:order-service',\n * info: {\n * title: 'Order Service API',\n * version: '1.0.0',\n * description: 'Async API for order processing'\n * },\n * servers: {\n * production: {\n * host: 'rabbitmq.example.com',\n * protocol: 'amqp',\n * protocolVersion: '0.9.1'\n * }\n * }\n * });\n * ```\n */\nexport class AsyncAPIGenerator {\n private readonly converters: ConditionalSchemaConverter[];\n\n /**\n * Create a new AsyncAPI generator instance.\n *\n * @param options - Configuration options including schema converters\n */\n constructor(options: AsyncAPIGeneratorOptions = {}) {\n this.converters = options.schemaConverters ?? [];\n }\n\n /**\n * Generate an AsyncAPI 3.0 document from a contract definition.\n *\n * Converts AMQP exchanges, queues, publishers, and consumers into\n * AsyncAPI channels, operations, and messages with proper JSON Schema\n * validation definitions.\n *\n * @param contract - The AMQP contract definition to convert\n * @param options - AsyncAPI document metadata (id, info, servers)\n * @returns Promise resolving to a complete AsyncAPI 3.0 document\n *\n * @example\n * ```typescript\n * const asyncapi = await generator.generate(contract, {\n * id: 'urn:com:example:api',\n * info: {\n * title: 'My API',\n * version: '1.0.0'\n * },\n * servers: {\n * dev: {\n * host: 'localhost:5672',\n * protocol: 'amqp'\n * }\n * }\n * });\n * ```\n */\n async generate(\n contract: ContractDefinition,\n options: AsyncAPIGeneratorGenerateOptions,\n ): Promise<AsyncAPIObject> {\n const convertedChannels: ChannelsObject = {};\n const convertedOperations: OperationsObject = {};\n const convertedMessages: MessagesObject = {};\n\n // First, collect all messages from publishers and consumers\n const publisherMessages = new Map<string, { message: MessageDefinition; channelKey: string }>();\n const consumerMessages = new Map<string, { message: MessageDefinition; channelKey: string }>();\n\n // Collect messages from publishers\n if (contract.publishers) {\n for (const [publisherName, publisher] of Object.entries(contract.publishers)) {\n const channelKey = this.getExchangeName(publisher.exchange, contract);\n publisherMessages.set(publisherName, { message: publisher.message, channelKey });\n }\n }\n\n // Collect messages from consumers\n if (contract.consumers) {\n for (const [consumerName, consumer] of Object.entries(contract.consumers)) {\n const channelKey = this.getQueueName(consumer.queue, contract);\n consumerMessages.set(consumerName, { message: consumer.message, channelKey });\n }\n }\n\n // Generate channels from queues with their messages\n if (contract.queues) {\n for (const [queueName, queue] of Object.entries(contract.queues)) {\n const channelMessages: MessagesObject = {};\n\n // Add messages from consumers that reference this queue\n for (const [consumerName, { message, channelKey }] of consumerMessages) {\n if (channelKey === queueName) {\n const messageName = `${consumerName}Message`;\n channelMessages[messageName] = await this.convertMessage(message);\n convertedMessages[messageName] = await this.convertMessage(message);\n }\n }\n\n const channel: ChannelObject = {\n ...this.queueToChannel(queue),\n };\n\n if (Object.keys(channelMessages).length > 0) {\n channel.messages = channelMessages;\n }\n\n convertedChannels[queueName] = channel;\n }\n }\n\n // Generate channels from exchanges with their messages\n if (contract.exchanges) {\n for (const [exchangeName, exchange] of Object.entries(contract.exchanges)) {\n const channelMessages: MessagesObject = {};\n\n // Add messages from publishers that reference this exchange\n for (const [publisherName, { message, channelKey }] of publisherMessages) {\n if (channelKey === exchangeName) {\n const messageName = `${publisherName}Message`;\n channelMessages[messageName] = await this.convertMessage(message);\n convertedMessages[messageName] = await this.convertMessage(message);\n }\n }\n\n const channel: ChannelObject = {\n ...this.exchangeToChannel(exchange),\n };\n\n if (Object.keys(channelMessages).length > 0) {\n channel.messages = channelMessages;\n }\n\n convertedChannels[exchangeName] = channel;\n }\n }\n\n // Generate publish operations from publishers\n if (contract.publishers) {\n for (const [publisherName, publisher] of Object.entries(contract.publishers)) {\n const exchangeName = this.getExchangeName(publisher.exchange, contract);\n const messageName = `${publisherName}Message`;\n\n convertedOperations[publisherName] = {\n action: \"send\",\n channel: { $ref: `#/channels/${exchangeName}` },\n messages: [{ $ref: `#/channels/${exchangeName}/messages/${messageName}` }],\n summary: `Publish to ${publisher.exchange.name}`,\n ...(publisher.routingKey && {\n description: `Routing key: ${publisher.routingKey}`,\n }),\n };\n }\n }\n\n // Generate receive operations from consumers\n if (contract.consumers) {\n for (const [consumerName, consumer] of Object.entries(contract.consumers)) {\n const queueName = this.getQueueName(consumer.queue, contract);\n const messageName = `${consumerName}Message`;\n\n convertedOperations[consumerName] = {\n action: \"receive\",\n channel: { $ref: `#/channels/${queueName}` },\n messages: [{ $ref: `#/channels/${queueName}/messages/${messageName}` }],\n summary: `Consume from ${consumer.queue.name}`,\n };\n }\n }\n\n return {\n ...options,\n asyncapi: \"3.0.0\",\n channels: convertedChannels,\n operations: convertedOperations,\n components: {\n messages: convertedMessages,\n },\n };\n }\n\n /**\n * Convert a message definition to AsyncAPI MessageObject\n */\n private async convertMessage(message: MessageDefinition): Promise<MessageObject> {\n const payload = message.payload;\n\n // Convert payload schema\n const payloadJsonSchema = await this.convertSchema(payload, \"input\");\n\n // Build result with required properties\n const result: Record<string, unknown> = {\n payload: payloadJsonSchema,\n contentType: \"application/json\",\n };\n\n // Add optional properties only if they exist\n if (message.headers) {\n const headersJsonSchema = await this.convertSchema(message.headers, \"input\");\n if (headersJsonSchema) {\n result[\"headers\"] = headersJsonSchema;\n }\n }\n\n if (message.summary) {\n result[\"summary\"] = message.summary;\n }\n\n if (message.description) {\n result[\"description\"] = message.description;\n }\n\n return result as MessageObject;\n }\n\n /**\n * Convert a queue definition to AsyncAPI ChannelObject\n */\n private queueToChannel(queue: QueueDefinition): ChannelObject {\n const result: Record<string, unknown> = {\n address: queue.name,\n title: queue.name,\n description: `AMQP Queue: ${queue.name}`,\n bindings: {\n amqp: {\n is: \"queue\",\n queue: {\n name: queue.name,\n durable: queue.durable ?? false,\n exclusive: queue.exclusive ?? false,\n autoDelete: queue.autoDelete ?? false,\n ...(queue.arguments && { vhost: \"/\" }),\n },\n },\n },\n };\n\n return result as ChannelObject;\n }\n\n /**\n * Convert an exchange definition to AsyncAPI ChannelObject\n */\n private exchangeToChannel(exchange: ExchangeDefinition): ChannelObject {\n const result: Record<string, unknown> = {\n address: exchange.name,\n title: exchange.name,\n description: `AMQP Exchange: ${exchange.name} (${exchange.type})`,\n bindings: {\n amqp: {\n is: \"routingKey\",\n exchange: {\n name: exchange.name,\n type: exchange.type,\n durable: exchange.durable ?? false,\n autoDelete: exchange.autoDelete ?? false,\n ...(exchange.arguments && { vhost: \"/\" }),\n },\n },\n },\n };\n\n return result as ChannelObject;\n }\n\n /**\n * Get the name/key of an exchange from the contract\n */\n private getExchangeName(exchange: ExchangeDefinition, contract: ContractDefinition): string {\n if (contract.exchanges) {\n for (const [name, ex] of Object.entries(contract.exchanges)) {\n if (ex === exchange || ex.name === exchange.name) {\n return name;\n }\n }\n }\n return exchange.name;\n }\n\n /**\n * Get the name/key of a queue from the contract\n */\n private getQueueName(queue: QueueDefinition, contract: ContractDefinition): string {\n if (contract.queues) {\n for (const [name, q] of Object.entries(contract.queues)) {\n if (q === queue || q.name === queue.name) {\n return name;\n }\n }\n }\n return queue.name;\n }\n\n /**\n * Convert a Standard Schema to JSON Schema using oRPC converters\n */\n private async convertSchema(\n schema: StandardSchemaV1,\n strategy: \"input\" | \"output\",\n ): Promise<JSONSchema> {\n // Try each converter until one matches\n for (const converter of this.converters) {\n const matches = await converter.condition(schema, { strategy });\n if (matches) {\n const [_required, jsonSchema] = await converter.convert(schema, { strategy });\n return jsonSchema;\n }\n }\n\n // If no converter matches, return a generic object schema\n // This allows the contract to still be generated even without schema converters\n return { type: \"object\" };\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2FA,IAAa,oBAAb,MAA+B;CAC7B,AAAiB;;;;;;CAOjB,YAAY,UAAoC,EAAE,EAAE;AAClD,OAAK,aAAa,QAAQ,oBAAoB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BlD,MAAM,SACJ,UACA,SACyB;EACzB,MAAMA,oBAAoC,EAAE;EAC5C,MAAMC,sBAAwC,EAAE;EAChD,MAAMC,oBAAoC,EAAE;EAG5C,MAAM,oCAAoB,IAAI,KAAiE;EAC/F,MAAM,mCAAmB,IAAI,KAAiE;AAG9F,MAAI,SAAS,WACX,MAAK,MAAM,CAAC,eAAe,cAAc,OAAO,QAAQ,SAAS,WAAW,EAAE;GAC5E,MAAM,aAAa,KAAK,gBAAgB,UAAU,UAAU,SAAS;AACrE,qBAAkB,IAAI,eAAe;IAAE,SAAS,UAAU;IAAS;IAAY,CAAC;;AAKpF,MAAI,SAAS,UACX,MAAK,MAAM,CAAC,cAAc,aAAa,OAAO,QAAQ,SAAS,UAAU,EAAE;GACzE,MAAM,aAAa,KAAK,aAAa,SAAS,OAAO,SAAS;AAC9D,oBAAiB,IAAI,cAAc;IAAE,SAAS,SAAS;IAAS;IAAY,CAAC;;AAKjF,MAAI,SAAS,OACX,MAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,SAAS,OAAO,EAAE;GAChE,MAAMC,kBAAkC,EAAE;AAG1C,QAAK,MAAM,CAAC,cAAc,EAAE,SAAS,iBAAiB,iBACpD,KAAI,eAAe,WAAW;IAC5B,MAAM,cAAc,GAAG,aAAa;AACpC,oBAAgB,eAAe,MAAM,KAAK,eAAe,QAAQ;AACjE,sBAAkB,eAAe,MAAM,KAAK,eAAe,QAAQ;;GAIvE,MAAMC,UAAyB,EAC7B,GAAG,KAAK,eAAe,MAAM,EAC9B;AAED,OAAI,OAAO,KAAK,gBAAgB,CAAC,SAAS,EACxC,SAAQ,WAAW;AAGrB,qBAAkB,aAAa;;AAKnC,MAAI,SAAS,UACX,MAAK,MAAM,CAAC,cAAc,aAAa,OAAO,QAAQ,SAAS,UAAU,EAAE;GACzE,MAAMD,kBAAkC,EAAE;AAG1C,QAAK,MAAM,CAAC,eAAe,EAAE,SAAS,iBAAiB,kBACrD,KAAI,eAAe,cAAc;IAC/B,MAAM,cAAc,GAAG,cAAc;AACrC,oBAAgB,eAAe,MAAM,KAAK,eAAe,QAAQ;AACjE,sBAAkB,eAAe,MAAM,KAAK,eAAe,QAAQ;;GAIvE,MAAMC,UAAyB,EAC7B,GAAG,KAAK,kBAAkB,SAAS,EACpC;AAED,OAAI,OAAO,KAAK,gBAAgB,CAAC,SAAS,EACxC,SAAQ,WAAW;AAGrB,qBAAkB,gBAAgB;;AAKtC,MAAI,SAAS,WACX,MAAK,MAAM,CAAC,eAAe,cAAc,OAAO,QAAQ,SAAS,WAAW,EAAE;GAC5E,MAAM,eAAe,KAAK,gBAAgB,UAAU,UAAU,SAAS;GACvE,MAAM,cAAc,GAAG,cAAc;AAErC,uBAAoB,iBAAiB;IACnC,QAAQ;IACR,SAAS,EAAE,MAAM,cAAc,gBAAgB;IAC/C,UAAU,CAAC,EAAE,MAAM,cAAc,aAAa,YAAY,eAAe,CAAC;IAC1E,SAAS,cAAc,UAAU,SAAS;IAC1C,GAAI,UAAU,cAAc,EAC1B,aAAa,gBAAgB,UAAU,cACxC;IACF;;AAKL,MAAI,SAAS,UACX,MAAK,MAAM,CAAC,cAAc,aAAa,OAAO,QAAQ,SAAS,UAAU,EAAE;GACzE,MAAM,YAAY,KAAK,aAAa,SAAS,OAAO,SAAS;GAC7D,MAAM,cAAc,GAAG,aAAa;AAEpC,uBAAoB,gBAAgB;IAClC,QAAQ;IACR,SAAS,EAAE,MAAM,cAAc,aAAa;IAC5C,UAAU,CAAC,EAAE,MAAM,cAAc,UAAU,YAAY,eAAe,CAAC;IACvE,SAAS,gBAAgB,SAAS,MAAM;IACzC;;AAIL,SAAO;GACL,GAAG;GACH,UAAU;GACV,UAAU;GACV,YAAY;GACZ,YAAY,EACV,UAAU,mBACX;GACF;;;;;CAMH,MAAc,eAAe,SAAoD;EAC/E,MAAM,UAAU,QAAQ;EAMxB,MAAMC,SAAkC;GACtC,SAJwB,MAAM,KAAK,cAAc,SAAS,QAAQ;GAKlE,aAAa;GACd;AAGD,MAAI,QAAQ,SAAS;GACnB,MAAM,oBAAoB,MAAM,KAAK,cAAc,QAAQ,SAAS,QAAQ;AAC5E,OAAI,kBACF,QAAO,aAAa;;AAIxB,MAAI,QAAQ,QACV,QAAO,aAAa,QAAQ;AAG9B,MAAI,QAAQ,YACV,QAAO,iBAAiB,QAAQ;AAGlC,SAAO;;;;;CAMT,AAAQ,eAAe,OAAuC;AAmB5D,SAlBwC;GACtC,SAAS,MAAM;GACf,OAAO,MAAM;GACb,aAAa,eAAe,MAAM;GAClC,UAAU,EACR,MAAM;IACJ,IAAI;IACJ,OAAO;KACL,MAAM,MAAM;KACZ,SAAS,MAAM,WAAW;KAC1B,WAAW,MAAM,aAAa;KAC9B,YAAY,MAAM,cAAc;KAChC,GAAI,MAAM,aAAa,EAAE,OAAO,KAAK;KACtC;IACF,EACF;GACF;;;;;CAQH,AAAQ,kBAAkB,UAA6C;AAmBrE,SAlBwC;GACtC,SAAS,SAAS;GAClB,OAAO,SAAS;GAChB,aAAa,kBAAkB,SAAS,KAAK,IAAI,SAAS,KAAK;GAC/D,UAAU,EACR,MAAM;IACJ,IAAI;IACJ,UAAU;KACR,MAAM,SAAS;KACf,MAAM,SAAS;KACf,SAAS,SAAS,WAAW;KAC7B,YAAY,SAAS,cAAc;KACnC,GAAI,SAAS,aAAa,EAAE,OAAO,KAAK;KACzC;IACF,EACF;GACF;;;;;CAQH,AAAQ,gBAAgB,UAA8B,UAAsC;AAC1F,MAAI,SAAS,WACX;QAAK,MAAM,CAAC,MAAM,OAAO,OAAO,QAAQ,SAAS,UAAU,CACzD,KAAI,OAAO,YAAY,GAAG,SAAS,SAAS,KAC1C,QAAO;;AAIb,SAAO,SAAS;;;;;CAMlB,AAAQ,aAAa,OAAwB,UAAsC;AACjF,MAAI,SAAS,QACX;QAAK,MAAM,CAAC,MAAM,MAAM,OAAO,QAAQ,SAAS,OAAO,CACrD,KAAI,MAAM,SAAS,EAAE,SAAS,MAAM,KAClC,QAAO;;AAIb,SAAO,MAAM;;;;;CAMf,MAAc,cACZ,QACA,UACqB;AAErB,OAAK,MAAM,aAAa,KAAK,WAE3B,KADgB,MAAM,UAAU,UAAU,QAAQ,EAAE,UAAU,CAAC,EAClD;GACX,MAAM,CAAC,WAAW,cAAc,MAAM,UAAU,QAAQ,QAAQ,EAAE,UAAU,CAAC;AAC7E,UAAO;;AAMX,SAAO,EAAE,MAAM,UAAU"}
package/docs/index.md ADDED
@@ -0,0 +1,165 @@
1
+ **@amqp-contract/asyncapi**
2
+
3
+ ***
4
+
5
+ # @amqp-contract/asyncapi
6
+
7
+ ## Classes
8
+
9
+ ### AsyncAPIGenerator
10
+
11
+ Defined in: [index.ts:92](https://github.com/btravers/amqp-contract/blob/f0945f098387fd3a6a40beac8cbe2ed7a4de210a/packages/asyncapi/src/index.ts#L92)
12
+
13
+ Generator for creating AsyncAPI 3.0 documentation from AMQP contracts.
14
+
15
+ This class converts contract definitions into AsyncAPI 3.0 specification documents,
16
+ which can be used for API documentation, code generation, and tooling integration.
17
+
18
+ #### Example
19
+
20
+ ```typescript
21
+ import { AsyncAPIGenerator } from '@amqp-contract/asyncapi';
22
+ import { zodToJsonSchema } from '@orpc/zod';
23
+ import { z } from 'zod';
24
+
25
+ const contract = defineContract({
26
+ exchanges: {
27
+ orders: defineExchange('orders', 'topic', { durable: true })
28
+ },
29
+ publishers: {
30
+ orderCreated: definePublisher('orders', z.object({
31
+ orderId: z.string(),
32
+ amount: z.number()
33
+ }), {
34
+ routingKey: 'order.created'
35
+ })
36
+ }
37
+ });
38
+
39
+ const generator = new AsyncAPIGenerator({
40
+ schemaConverters: [zodToJsonSchema]
41
+ });
42
+
43
+ const asyncapi = await generator.generate(contract, {
44
+ id: 'urn:com:example:order-service',
45
+ info: {
46
+ title: 'Order Service API',
47
+ version: '1.0.0',
48
+ description: 'Async API for order processing'
49
+ },
50
+ servers: {
51
+ production: {
52
+ host: 'rabbitmq.example.com',
53
+ protocol: 'amqp',
54
+ protocolVersion: '0.9.1'
55
+ }
56
+ }
57
+ });
58
+ ```
59
+
60
+ #### Constructors
61
+
62
+ ##### Constructor
63
+
64
+ ```ts
65
+ new AsyncAPIGenerator(options): AsyncAPIGenerator;
66
+ ```
67
+
68
+ Defined in: [index.ts:100](https://github.com/btravers/amqp-contract/blob/f0945f098387fd3a6a40beac8cbe2ed7a4de210a/packages/asyncapi/src/index.ts#L100)
69
+
70
+ Create a new AsyncAPI generator instance.
71
+
72
+ ###### Parameters
73
+
74
+ | Parameter | Type | Description |
75
+ | ------ | ------ | ------ |
76
+ | `options` | [`AsyncAPIGeneratorOptions`](#asyncapigeneratoroptions) | Configuration options including schema converters |
77
+
78
+ ###### Returns
79
+
80
+ [`AsyncAPIGenerator`](#asyncapigenerator)
81
+
82
+ #### Methods
83
+
84
+ ##### generate()
85
+
86
+ ```ts
87
+ generate(contract, options): Promise<AsyncAPIObject>;
88
+ ```
89
+
90
+ Defined in: [index.ts:132](https://github.com/btravers/amqp-contract/blob/f0945f098387fd3a6a40beac8cbe2ed7a4de210a/packages/asyncapi/src/index.ts#L132)
91
+
92
+ Generate an AsyncAPI 3.0 document from a contract definition.
93
+
94
+ Converts AMQP exchanges, queues, publishers, and consumers into
95
+ AsyncAPI channels, operations, and messages with proper JSON Schema
96
+ validation definitions.
97
+
98
+ ###### Parameters
99
+
100
+ | Parameter | Type | Description |
101
+ | ------ | ------ | ------ |
102
+ | `contract` | `ContractDefinition` | The AMQP contract definition to convert |
103
+ | `options` | [`AsyncAPIGeneratorGenerateOptions`](#asyncapigeneratorgenerateoptions) | AsyncAPI document metadata (id, info, servers) |
104
+
105
+ ###### Returns
106
+
107
+ `Promise`\<`AsyncAPIObject`\>
108
+
109
+ Promise resolving to a complete AsyncAPI 3.0 document
110
+
111
+ ###### Example
112
+
113
+ ```typescript
114
+ const asyncapi = await generator.generate(contract, {
115
+ id: 'urn:com:example:api',
116
+ info: {
117
+ title: 'My API',
118
+ version: '1.0.0'
119
+ },
120
+ servers: {
121
+ dev: {
122
+ host: 'localhost:5672',
123
+ protocol: 'amqp'
124
+ }
125
+ }
126
+ });
127
+ ```
128
+
129
+ ## Interfaces
130
+
131
+ ### AsyncAPIGeneratorOptions
132
+
133
+ Defined in: [index.ts:31](https://github.com/btravers/amqp-contract/blob/f0945f098387fd3a6a40beac8cbe2ed7a4de210a/packages/asyncapi/src/index.ts#L31)
134
+
135
+ Options for configuring the AsyncAPI generator.
136
+
137
+ #### Example
138
+
139
+ ```typescript
140
+ import { AsyncAPIGenerator } from '@amqp-contract/asyncapi';
141
+ import { zodToJsonSchema } from '@orpc/zod';
142
+
143
+ const generator = new AsyncAPIGenerator({
144
+ schemaConverters: [zodToJsonSchema]
145
+ });
146
+ ```
147
+
148
+ #### Properties
149
+
150
+ | Property | Type | Description | Defined in |
151
+ | ------ | ------ | ------ | ------ |
152
+ | <a id="schemaconverters"></a> `schemaConverters?` | `ConditionalSchemaConverter`[] | Schema converters for transforming validation schemas to JSON Schema. Supports Zod, Valibot, ArkType, and other Standard Schema v1 compatible libraries. | [index.ts:36](https://github.com/btravers/amqp-contract/blob/f0945f098387fd3a6a40beac8cbe2ed7a4de210a/packages/asyncapi/src/index.ts#L36) |
153
+
154
+ ## Type Aliases
155
+
156
+ ### AsyncAPIGeneratorGenerateOptions
157
+
158
+ ```ts
159
+ type AsyncAPIGeneratorGenerateOptions = Pick<AsyncAPIObject, "id" | "info" | "servers">;
160
+ ```
161
+
162
+ Defined in: [index.ts:43](https://github.com/btravers/amqp-contract/blob/f0945f098387fd3a6a40beac8cbe2ed7a4de210a/packages/asyncapi/src/index.ts#L43)
163
+
164
+ Options for generating an AsyncAPI document.
165
+ These correspond to the top-level AsyncAPI document fields.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amqp-contract/asyncapi",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "AsyncAPI specification generator for amqp-contract",
5
5
  "keywords": [
6
6
  "amqp",
@@ -38,12 +38,13 @@
38
38
  "module": "./dist/index.mjs",
39
39
  "types": "./dist/index.d.mts",
40
40
  "files": [
41
- "dist"
41
+ "dist",
42
+ "docs"
42
43
  ],
43
44
  "dependencies": {
44
45
  "@orpc/openapi": "1.13.0",
45
46
  "@standard-schema/spec": "1.1.0",
46
- "@amqp-contract/contract": "0.2.0"
47
+ "@amqp-contract/contract": "0.2.1"
47
48
  },
48
49
  "devDependencies": {
49
50
  "@asyncapi/parser": "3.4.0",
@@ -54,14 +55,18 @@
54
55
  "@vitest/coverage-v8": "4.0.16",
55
56
  "arktype": "2.1.29",
56
57
  "tsdown": "0.18.2",
58
+ "typedoc": "0.28.3",
59
+ "typedoc-plugin-markdown": "4.9.0",
57
60
  "typescript": "5.9.3",
58
61
  "valibot": "1.2.0",
59
62
  "vitest": "4.0.16",
60
63
  "zod": "4.2.1",
61
- "@amqp-contract/tsconfig": "0.0.0"
64
+ "@amqp-contract/tsconfig": "0.0.0",
65
+ "@amqp-contract/typedoc": "0.0.1"
62
66
  },
63
67
  "scripts": {
64
68
  "build": "tsdown src/index.ts --format cjs,esm --dts --clean",
69
+ "build:docs": "typedoc",
65
70
  "dev": "tsdown src/index.ts --format cjs,esm --dts --watch",
66
71
  "test": "vitest run",
67
72
  "test:watch": "vitest",