@amqp-contract/asyncapi 0.1.4 → 0.2.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
@@ -1,111 +1,171 @@
1
1
 
2
- //#region src/schema-converter.ts
3
- /**
4
- * Convert a Standard Schema to JSON Schema (AsyncAPI format)
5
- *
6
- * This is a basic converter that returns a generic object schema.
7
- * Users should provide their own schema-to-JSON-Schema converter function
8
- * specific to their schema library.
9
- *
10
- * For Zod users, import and use zodToJsonSchema from @amqp-contract/zod
11
- *
12
- * @example
13
- * ```ts
14
- * import { zodToJsonSchema } from '@amqp-contract/zod';
15
- * import { generateAsyncAPI } from '@amqp-contract/asyncapi';
16
- *
17
- * // Use zodToJsonSchema for converting Zod schemas
18
- * const jsonSchema = zodToJsonSchema(zodSchema);
19
- * ```
20
- */
21
- function standardSchemaToJsonSchema(_schema) {
22
- return { type: "object" };
23
- }
24
-
25
- //#endregion
26
- //#region src/generator.ts
27
- /**
28
- * Generate AsyncAPI 3.0.0 specification from AMQP contract
29
- */
30
- function generateAsyncAPI(contract, options) {
31
- const channels = {};
32
- const operations = {};
33
- const messages = {};
34
- if (contract.queues) for (const [queueName, queue] of Object.entries(contract.queues)) {
35
- const binding = { amqp: {
36
- is: "queue",
37
- queue: { name: queue.name }
38
- } };
39
- if (queue.durable !== void 0) binding.amqp.queue.durable = queue.durable;
40
- if (queue.exclusive !== void 0) binding.amqp.queue.exclusive = queue.exclusive;
41
- if (queue.autoDelete !== void 0) binding.amqp.queue.autoDelete = queue.autoDelete;
42
- channels[queueName] = {
43
- address: queue.name,
44
- description: `Queue: ${queue.name}`,
45
- bindings: binding
46
- };
2
+ //#region src/index.ts
3
+ var AsyncAPIGenerator = class {
4
+ converters;
5
+ constructor(options = {}) {
6
+ this.converters = options.schemaConverters ?? [];
47
7
  }
48
- if (contract.exchanges) for (const [exchangeName, exchange] of Object.entries(contract.exchanges)) {
49
- const binding = { amqp: {
50
- is: "routingKey",
51
- exchange: {
52
- name: exchange.name,
53
- type: exchange.type
8
+ /**
9
+ * Generate an AsyncAPI 3.0 document from a contract definition
10
+ */
11
+ async generate(contract, options) {
12
+ const convertedChannels = {};
13
+ const convertedOperations = {};
14
+ const convertedMessages = {};
15
+ const publisherMessages = /* @__PURE__ */ new Map();
16
+ const consumerMessages = /* @__PURE__ */ new Map();
17
+ if (contract.publishers) for (const [publisherName, publisher] of Object.entries(contract.publishers)) {
18
+ const channelKey = this.getExchangeName(publisher.exchange, contract);
19
+ publisherMessages.set(publisherName, {
20
+ message: publisher.message,
21
+ channelKey
22
+ });
23
+ }
24
+ if (contract.consumers) for (const [consumerName, consumer] of Object.entries(contract.consumers)) {
25
+ const channelKey = this.getQueueName(consumer.queue, contract);
26
+ consumerMessages.set(consumerName, {
27
+ message: consumer.message,
28
+ channelKey
29
+ });
30
+ }
31
+ if (contract.queues) for (const [queueName, queue] of Object.entries(contract.queues)) {
32
+ const channelMessages = {};
33
+ for (const [consumerName, { message, channelKey }] of consumerMessages) if (channelKey === queueName) {
34
+ const messageName = `${consumerName}Message`;
35
+ channelMessages[messageName] = await this.convertMessage(message);
36
+ convertedMessages[messageName] = await this.convertMessage(message);
54
37
  }
55
- } };
56
- if (exchange.durable !== void 0) binding.amqp.exchange.durable = exchange.durable;
57
- if (exchange.autoDelete !== void 0) binding.amqp.exchange.autoDelete = exchange.autoDelete;
58
- channels[exchangeName] = {
59
- address: exchange.name,
60
- description: `Exchange: ${exchange.name} (${exchange.type})`,
61
- bindings: binding
38
+ const channel = { ...this.queueToChannel(queue) };
39
+ if (Object.keys(channelMessages).length > 0) channel.messages = channelMessages;
40
+ convertedChannels[queueName] = channel;
41
+ }
42
+ if (contract.exchanges) for (const [exchangeName, exchange] of Object.entries(contract.exchanges)) {
43
+ const channelMessages = {};
44
+ for (const [publisherName, { message, channelKey }] of publisherMessages) if (channelKey === exchangeName) {
45
+ const messageName = `${publisherName}Message`;
46
+ channelMessages[messageName] = await this.convertMessage(message);
47
+ convertedMessages[messageName] = await this.convertMessage(message);
48
+ }
49
+ const channel = { ...this.exchangeToChannel(exchange) };
50
+ if (Object.keys(channelMessages).length > 0) channel.messages = channelMessages;
51
+ convertedChannels[exchangeName] = channel;
52
+ }
53
+ if (contract.publishers) for (const [publisherName, publisher] of Object.entries(contract.publishers)) {
54
+ const exchangeName = this.getExchangeName(publisher.exchange, contract);
55
+ const messageName = `${publisherName}Message`;
56
+ convertedOperations[publisherName] = {
57
+ action: "send",
58
+ channel: { $ref: `#/channels/${exchangeName}` },
59
+ messages: [{ $ref: `#/channels/${exchangeName}/messages/${messageName}` }],
60
+ summary: `Publish to ${publisher.exchange.name}`,
61
+ ...publisher.routingKey && { description: `Routing key: ${publisher.routingKey}` }
62
+ };
63
+ }
64
+ if (contract.consumers) for (const [consumerName, consumer] of Object.entries(contract.consumers)) {
65
+ const queueName = this.getQueueName(consumer.queue, contract);
66
+ const messageName = `${consumerName}Message`;
67
+ convertedOperations[consumerName] = {
68
+ action: "receive",
69
+ channel: { $ref: `#/channels/${queueName}` },
70
+ messages: [{ $ref: `#/channels/${queueName}/messages/${messageName}` }],
71
+ summary: `Consume from ${consumer.queue.name}`,
72
+ ...consumer.prefetch && { description: `Prefetch: ${consumer.prefetch}` }
73
+ };
74
+ }
75
+ return {
76
+ ...options,
77
+ asyncapi: "3.0.0",
78
+ channels: convertedChannels,
79
+ operations: convertedOperations,
80
+ components: { messages: convertedMessages }
62
81
  };
63
82
  }
64
- if (contract.publishers) for (const [publisherName, publisher] of Object.entries(contract.publishers)) {
65
- const messageName = `${publisherName}Message`;
66
- messages[messageName] = {
67
- name: messageName,
68
- title: `${publisherName} message`,
69
- contentType: "application/json",
70
- payload: standardSchemaToJsonSchema(publisher.message)
71
- };
72
- operations[publisherName] = {
73
- action: "send",
74
- channel: { $ref: `#/channels/${publisher.exchange}` },
75
- messages: [{ $ref: `#/components/messages/${messageName}` }],
76
- description: `Publish message to ${publisher.exchange}`
83
+ /**
84
+ * Convert a message definition to AsyncAPI MessageObject
85
+ */
86
+ async convertMessage(message) {
87
+ const payload = message.payload;
88
+ const result = {
89
+ payload: await this.convertSchema(payload, "input"),
90
+ contentType: "application/json"
77
91
  };
92
+ if (message.headers) {
93
+ const headersJsonSchema = await this.convertSchema(message.headers, "input");
94
+ if (headersJsonSchema) result["headers"] = headersJsonSchema;
95
+ }
96
+ if (message.summary) result["summary"] = message.summary;
97
+ if (message.description) result["description"] = message.description;
98
+ return result;
78
99
  }
79
- if (contract.consumers) for (const [consumerName, consumer] of Object.entries(contract.consumers)) {
80
- const messageName = `${consumerName}Message`;
81
- messages[messageName] = {
82
- name: messageName,
83
- title: `${consumerName} message`,
84
- contentType: "application/json",
85
- payload: standardSchemaToJsonSchema(consumer.message)
100
+ /**
101
+ * Convert a queue definition to AsyncAPI ChannelObject
102
+ */
103
+ queueToChannel(queue) {
104
+ return {
105
+ address: queue.name,
106
+ title: queue.name,
107
+ description: `AMQP Queue: ${queue.name}`,
108
+ bindings: { amqp: {
109
+ is: "queue",
110
+ queue: {
111
+ name: queue.name,
112
+ durable: queue.durable ?? false,
113
+ exclusive: queue.exclusive ?? false,
114
+ autoDelete: queue.autoDelete ?? false,
115
+ ...queue.arguments && { vhost: "/" }
116
+ }
117
+ } }
86
118
  };
87
- operations[consumerName] = {
88
- action: "receive",
89
- channel: { $ref: `#/channels/${consumer.queue}` },
90
- messages: [{ $ref: `#/components/messages/${messageName}` }],
91
- description: `Consume message from ${consumer.queue}`
119
+ }
120
+ /**
121
+ * Convert an exchange definition to AsyncAPI ChannelObject
122
+ */
123
+ exchangeToChannel(exchange) {
124
+ return {
125
+ address: exchange.name,
126
+ title: exchange.name,
127
+ description: `AMQP Exchange: ${exchange.name} (${exchange.type})`,
128
+ bindings: { amqp: {
129
+ is: "routingKey",
130
+ exchange: {
131
+ name: exchange.name,
132
+ type: exchange.type,
133
+ durable: exchange.durable ?? false,
134
+ autoDelete: exchange.autoDelete ?? false,
135
+ ...exchange.arguments && { vhost: "/" }
136
+ }
137
+ } }
92
138
  };
93
139
  }
94
- const result = {
95
- asyncapi: "3.0.0",
96
- info: {
97
- title: options.info.title ?? "AMQP Contract API",
98
- version: options.info.version ?? "1.0.0",
99
- ...options.info
100
- },
101
- channels,
102
- operations,
103
- components: { messages }
104
- };
105
- if (options.servers) result.servers = options.servers;
106
- return result;
107
- }
140
+ /**
141
+ * Get the name/key of an exchange from the contract
142
+ */
143
+ getExchangeName(exchange, contract) {
144
+ if (contract.exchanges) {
145
+ for (const [name, ex] of Object.entries(contract.exchanges)) if (ex === exchange || ex.name === exchange.name) return name;
146
+ }
147
+ return exchange.name;
148
+ }
149
+ /**
150
+ * Get the name/key of a queue from the contract
151
+ */
152
+ getQueueName(queue, contract) {
153
+ if (contract.queues) {
154
+ for (const [name, q] of Object.entries(contract.queues)) if (q === queue || q.name === queue.name) return name;
155
+ }
156
+ return queue.name;
157
+ }
158
+ /**
159
+ * Convert a Standard Schema to JSON Schema using oRPC converters
160
+ */
161
+ async convertSchema(schema, strategy) {
162
+ for (const converter of this.converters) if (await converter.condition(schema, { strategy })) {
163
+ const [_required, jsonSchema] = await converter.convert(schema, { strategy });
164
+ return jsonSchema;
165
+ }
166
+ return { type: "object" };
167
+ }
168
+ };
108
169
 
109
170
  //#endregion
110
- exports.generateAsyncAPI = generateAsyncAPI;
111
- exports.standardSchemaToJsonSchema = standardSchemaToJsonSchema;
171
+ exports.AsyncAPIGenerator = AsyncAPIGenerator;
package/dist/index.d.cts CHANGED
@@ -1,136 +1,44 @@
1
+ import { ConditionalSchemaConverter } from "@orpc/openapi";
2
+ import { AsyncAPIObject } from "@asyncapi/parser/esm/spec-types/v3";
1
3
  import { ContractDefinition } from "@amqp-contract/contract";
2
- import { StandardSchemaV1 } from "@standard-schema/spec";
3
4
 
4
- //#region src/generator.d.ts
5
- /**
6
- * AsyncAPI 3.0.0 Specification
7
- */
8
- interface AsyncAPIDocument {
9
- asyncapi: "3.0.0";
10
- info: AsyncAPIInfo;
11
- servers?: Record<string, AsyncAPIServer>;
12
- channels?: Record<string, AsyncAPIChannel>;
13
- operations?: Record<string, AsyncAPIOperation>;
14
- components?: AsyncAPIComponents;
5
+ //#region src/index.d.ts
6
+ interface AsyncAPIGeneratorOptions {
7
+ schemaConverters?: ConditionalSchemaConverter[];
8
+ }
9
+ type AsyncAPIGeneratorGenerateOptions = Pick<AsyncAPIObject, "id" | "info" | "servers">;
10
+ declare class AsyncAPIGenerator {
11
+ private readonly converters;
12
+ constructor(options?: AsyncAPIGeneratorOptions);
13
+ /**
14
+ * Generate an AsyncAPI 3.0 document from a contract definition
15
+ */
16
+ generate(contract: ContractDefinition, options: AsyncAPIGeneratorGenerateOptions): Promise<AsyncAPIObject>;
17
+ /**
18
+ * Convert a message definition to AsyncAPI MessageObject
19
+ */
20
+ private convertMessage;
21
+ /**
22
+ * Convert a queue definition to AsyncAPI ChannelObject
23
+ */
24
+ private queueToChannel;
25
+ /**
26
+ * Convert an exchange definition to AsyncAPI ChannelObject
27
+ */
28
+ private exchangeToChannel;
29
+ /**
30
+ * Get the name/key of an exchange from the contract
31
+ */
32
+ private getExchangeName;
33
+ /**
34
+ * Get the name/key of a queue from the contract
35
+ */
36
+ private getQueueName;
37
+ /**
38
+ * Convert a Standard Schema to JSON Schema using oRPC converters
39
+ */
40
+ private convertSchema;
15
41
  }
16
- interface AsyncAPIInfo {
17
- title: string;
18
- version: string;
19
- description?: string;
20
- termsOfService?: string;
21
- contact?: {
22
- name?: string;
23
- url?: string;
24
- email?: string;
25
- };
26
- license?: {
27
- name: string;
28
- url?: string;
29
- };
30
- }
31
- interface AsyncAPIServer {
32
- host: string;
33
- protocol: string;
34
- description?: string;
35
- variables?: Record<string, {
36
- default: string;
37
- description?: string;
38
- }>;
39
- }
40
- interface AsyncAPIChannel {
41
- address: string;
42
- messages?: Record<string, AsyncAPIMessageRef>;
43
- description?: string;
44
- bindings?: {
45
- amqp?: {
46
- is: "queue" | "routingKey";
47
- queue?: {
48
- name: string;
49
- durable?: boolean;
50
- exclusive?: boolean;
51
- autoDelete?: boolean;
52
- };
53
- exchange?: {
54
- name: string;
55
- type: "topic" | "direct" | "fanout" | "headers";
56
- durable?: boolean;
57
- autoDelete?: boolean;
58
- };
59
- };
60
- };
61
- }
62
- interface AsyncAPIOperation {
63
- action: "send" | "receive";
64
- channel: AsyncAPIRef;
65
- messages?: AsyncAPIMessageRef[];
66
- description?: string;
67
- }
68
- interface AsyncAPIMessageRef {
69
- $ref?: string;
70
- payload?: AsyncAPISchema;
71
- contentType?: string;
72
- name?: string;
73
- title?: string;
74
- summary?: string;
75
- description?: string;
76
- }
77
- interface AsyncAPISchema {
78
- type?: string;
79
- properties?: Record<string, AsyncAPISchema>;
80
- required?: string[];
81
- items?: AsyncAPISchema;
82
- $ref?: string;
83
- description?: string;
84
- format?: string;
85
- minimum?: number;
86
- maximum?: number;
87
- minLength?: number;
88
- maxLength?: number;
89
- pattern?: string;
90
- enum?: unknown[];
91
- }
92
- interface AsyncAPIRef {
93
- $ref: string;
94
- }
95
- interface AsyncAPIComponents {
96
- messages?: Record<string, AsyncAPIMessageRef>;
97
- schemas?: Record<string, AsyncAPISchema>;
98
- }
99
- /**
100
- * Options for generating AsyncAPI specification
101
- */
102
- interface GenerateAsyncAPIOptions {
103
- info: Omit<AsyncAPIInfo, "title" | "version"> & {
104
- title?: string;
105
- version?: string;
106
- };
107
- servers?: Record<string, AsyncAPIServer>;
108
- }
109
- /**
110
- * Generate AsyncAPI 3.0.0 specification from AMQP contract
111
- */
112
- declare function generateAsyncAPI(contract: ContractDefinition, options: GenerateAsyncAPIOptions): AsyncAPIDocument;
113
- //#endregion
114
- //#region src/schema-converter.d.ts
115
- /**
116
- * Convert a Standard Schema to JSON Schema (AsyncAPI format)
117
- *
118
- * This is a basic converter that returns a generic object schema.
119
- * Users should provide their own schema-to-JSON-Schema converter function
120
- * specific to their schema library.
121
- *
122
- * For Zod users, import and use zodToJsonSchema from @amqp-contract/zod
123
- *
124
- * @example
125
- * ```ts
126
- * import { zodToJsonSchema } from '@amqp-contract/zod';
127
- * import { generateAsyncAPI } from '@amqp-contract/asyncapi';
128
- *
129
- * // Use zodToJsonSchema for converting Zod schemas
130
- * const jsonSchema = zodToJsonSchema(zodSchema);
131
- * ```
132
- */
133
- declare function standardSchemaToJsonSchema(_schema: StandardSchemaV1): AsyncAPISchema;
134
42
  //#endregion
135
- export { type AsyncAPIChannel, type AsyncAPIComponents, type AsyncAPIDocument, type AsyncAPIInfo, type AsyncAPIMessageRef, type AsyncAPIOperation, type AsyncAPISchema, type AsyncAPIServer, type GenerateAsyncAPIOptions, generateAsyncAPI, standardSchemaToJsonSchema };
43
+ export { AsyncAPIGenerator, AsyncAPIGeneratorGenerateOptions, AsyncAPIGeneratorOptions };
136
44
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/generator.ts","../src/schema-converter.ts"],"sourcesContent":[],"mappings":";;;;;;;AAMiB,UAAA,gBAAA,CAAgB;EAEzB,QAAA,EAAA,OAAA;EACmB,IAAA,EADnB,YACmB;EAAf,OAAA,CAAA,EAAA,MAAA,CAAA,MAAA,EAAe,cAAf,CAAA;EACgB,QAAA,CAAA,EAAf,MAAe,CAAA,MAAA,EAAA,eAAA,CAAA;EAAf,UAAA,CAAA,EACE,MADF,CAAA,MAAA,EACiB,iBADjB,CAAA;EACiB,UAAA,CAAA,EACf,kBADe;;AACf,UAGE,YAAA,CAHF;EAAkB,KAAA,EAAA,MAAA;EAGhB,OAAA,EAAA,MAAY;EAgBZ,WAAA,CAAA,EAAA,MAAc;EAOd,cAAA,CAAA,EAAA,MAAe;EAuBf,OAAA,CAAA,EAAA;IAOA,IAAA,CAAA,EAAA,MAAA;IAUA,GAAA,CAAA,EAAA,MAAA;IAEa,KAAA,CAAA,EAAA,MAAA;EAAf,CAAA;EAEL,OAAA,CAAA,EAAA;IAAc,IAAA,EAAA,MAAA;IAYd,GAAA,CAAA,EAAA,MAAW;EAIJ,CAAA;;AACJ,UApEI,cAAA,CAoEJ;EACc,IAAA,EAAA,MAAA;EAAf,QAAA,EAAA,MAAA;EAAM,WAAA,CAAA,EAAA,MAAA;EAMD,SAAA,CAAA,EAvEH,MAuEG,CAAA,MAAA,EAAuB;IAC3B,OAAA,EAAA,MAAA;IAAL,WAAA,CAAA,EAAA,MAAA;EAImB,CAAA,CAAA;;AAAT,UAzED,eAAA,CAyEC;EAMF,OAAA,EAAA,MAAA;EACJ,QAAA,CAAA,EA9EC,MA8ED,CAAA,MAAA,EA9EgB,kBA8EhB,CAAA;EACD,WAAA,CAAA,EAAA,MAAA;EACR,QAAA,CAAA,EAAA;IAAgB,IAAA,CAAA,EAAA;;;;QCnGH,OAAA,CAAA,EAAA,OAA0B;;;;;;;;;;;;;UDwCzB,iBAAA;;WAEN;aACE;;;UAII,kBAAA;;YAEL;;;;;;;UAQK,cAAA;;eAEF,eAAe;;UAEpB;;;;;;;;;;;UAYA,WAAA;;;UAIO,kBAAA;aACJ,eAAe;YAChB,eAAe;;;;;UAMV,uBAAA;QACT,KAAK;;;;YAID,eAAe;;;;;iBAMX,gBAAA,WACJ,6BACD,0BACR;;;;;AAlHH;;;;;;;;;;AASA;AAgBA;AAOA;AAuBA;AAOA;AAUA;AAE8B,iBC3Dd,0BAAA,CD2Dc,OAAA,EC3DsB,gBD2DtB,CAAA,EC3DyC,cD2DzC"}
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"}
package/dist/index.d.mts CHANGED
@@ -1,136 +1,44 @@
1
+ import { ConditionalSchemaConverter } from "@orpc/openapi";
2
+ import { AsyncAPIObject } from "@asyncapi/parser/esm/spec-types/v3";
1
3
  import { ContractDefinition } from "@amqp-contract/contract";
2
- import { StandardSchemaV1 } from "@standard-schema/spec";
3
4
 
4
- //#region src/generator.d.ts
5
- /**
6
- * AsyncAPI 3.0.0 Specification
7
- */
8
- interface AsyncAPIDocument {
9
- asyncapi: "3.0.0";
10
- info: AsyncAPIInfo;
11
- servers?: Record<string, AsyncAPIServer>;
12
- channels?: Record<string, AsyncAPIChannel>;
13
- operations?: Record<string, AsyncAPIOperation>;
14
- components?: AsyncAPIComponents;
5
+ //#region src/index.d.ts
6
+ interface AsyncAPIGeneratorOptions {
7
+ schemaConverters?: ConditionalSchemaConverter[];
8
+ }
9
+ type AsyncAPIGeneratorGenerateOptions = Pick<AsyncAPIObject, "id" | "info" | "servers">;
10
+ declare class AsyncAPIGenerator {
11
+ private readonly converters;
12
+ constructor(options?: AsyncAPIGeneratorOptions);
13
+ /**
14
+ * Generate an AsyncAPI 3.0 document from a contract definition
15
+ */
16
+ generate(contract: ContractDefinition, options: AsyncAPIGeneratorGenerateOptions): Promise<AsyncAPIObject>;
17
+ /**
18
+ * Convert a message definition to AsyncAPI MessageObject
19
+ */
20
+ private convertMessage;
21
+ /**
22
+ * Convert a queue definition to AsyncAPI ChannelObject
23
+ */
24
+ private queueToChannel;
25
+ /**
26
+ * Convert an exchange definition to AsyncAPI ChannelObject
27
+ */
28
+ private exchangeToChannel;
29
+ /**
30
+ * Get the name/key of an exchange from the contract
31
+ */
32
+ private getExchangeName;
33
+ /**
34
+ * Get the name/key of a queue from the contract
35
+ */
36
+ private getQueueName;
37
+ /**
38
+ * Convert a Standard Schema to JSON Schema using oRPC converters
39
+ */
40
+ private convertSchema;
15
41
  }
16
- interface AsyncAPIInfo {
17
- title: string;
18
- version: string;
19
- description?: string;
20
- termsOfService?: string;
21
- contact?: {
22
- name?: string;
23
- url?: string;
24
- email?: string;
25
- };
26
- license?: {
27
- name: string;
28
- url?: string;
29
- };
30
- }
31
- interface AsyncAPIServer {
32
- host: string;
33
- protocol: string;
34
- description?: string;
35
- variables?: Record<string, {
36
- default: string;
37
- description?: string;
38
- }>;
39
- }
40
- interface AsyncAPIChannel {
41
- address: string;
42
- messages?: Record<string, AsyncAPIMessageRef>;
43
- description?: string;
44
- bindings?: {
45
- amqp?: {
46
- is: "queue" | "routingKey";
47
- queue?: {
48
- name: string;
49
- durable?: boolean;
50
- exclusive?: boolean;
51
- autoDelete?: boolean;
52
- };
53
- exchange?: {
54
- name: string;
55
- type: "topic" | "direct" | "fanout" | "headers";
56
- durable?: boolean;
57
- autoDelete?: boolean;
58
- };
59
- };
60
- };
61
- }
62
- interface AsyncAPIOperation {
63
- action: "send" | "receive";
64
- channel: AsyncAPIRef;
65
- messages?: AsyncAPIMessageRef[];
66
- description?: string;
67
- }
68
- interface AsyncAPIMessageRef {
69
- $ref?: string;
70
- payload?: AsyncAPISchema;
71
- contentType?: string;
72
- name?: string;
73
- title?: string;
74
- summary?: string;
75
- description?: string;
76
- }
77
- interface AsyncAPISchema {
78
- type?: string;
79
- properties?: Record<string, AsyncAPISchema>;
80
- required?: string[];
81
- items?: AsyncAPISchema;
82
- $ref?: string;
83
- description?: string;
84
- format?: string;
85
- minimum?: number;
86
- maximum?: number;
87
- minLength?: number;
88
- maxLength?: number;
89
- pattern?: string;
90
- enum?: unknown[];
91
- }
92
- interface AsyncAPIRef {
93
- $ref: string;
94
- }
95
- interface AsyncAPIComponents {
96
- messages?: Record<string, AsyncAPIMessageRef>;
97
- schemas?: Record<string, AsyncAPISchema>;
98
- }
99
- /**
100
- * Options for generating AsyncAPI specification
101
- */
102
- interface GenerateAsyncAPIOptions {
103
- info: Omit<AsyncAPIInfo, "title" | "version"> & {
104
- title?: string;
105
- version?: string;
106
- };
107
- servers?: Record<string, AsyncAPIServer>;
108
- }
109
- /**
110
- * Generate AsyncAPI 3.0.0 specification from AMQP contract
111
- */
112
- declare function generateAsyncAPI(contract: ContractDefinition, options: GenerateAsyncAPIOptions): AsyncAPIDocument;
113
- //#endregion
114
- //#region src/schema-converter.d.ts
115
- /**
116
- * Convert a Standard Schema to JSON Schema (AsyncAPI format)
117
- *
118
- * This is a basic converter that returns a generic object schema.
119
- * Users should provide their own schema-to-JSON-Schema converter function
120
- * specific to their schema library.
121
- *
122
- * For Zod users, import and use zodToJsonSchema from @amqp-contract/zod
123
- *
124
- * @example
125
- * ```ts
126
- * import { zodToJsonSchema } from '@amqp-contract/zod';
127
- * import { generateAsyncAPI } from '@amqp-contract/asyncapi';
128
- *
129
- * // Use zodToJsonSchema for converting Zod schemas
130
- * const jsonSchema = zodToJsonSchema(zodSchema);
131
- * ```
132
- */
133
- declare function standardSchemaToJsonSchema(_schema: StandardSchemaV1): AsyncAPISchema;
134
42
  //#endregion
135
- export { type AsyncAPIChannel, type AsyncAPIComponents, type AsyncAPIDocument, type AsyncAPIInfo, type AsyncAPIMessageRef, type AsyncAPIOperation, type AsyncAPISchema, type AsyncAPIServer, type GenerateAsyncAPIOptions, generateAsyncAPI, standardSchemaToJsonSchema };
43
+ export { AsyncAPIGenerator, AsyncAPIGeneratorGenerateOptions, AsyncAPIGeneratorOptions };
136
44
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/generator.ts","../src/schema-converter.ts"],"sourcesContent":[],"mappings":";;;;;;;AAMiB,UAAA,gBAAA,CAAgB;EAEzB,QAAA,EAAA,OAAA;EACmB,IAAA,EADnB,YACmB;EAAf,OAAA,CAAA,EAAA,MAAA,CAAA,MAAA,EAAe,cAAf,CAAA;EACgB,QAAA,CAAA,EAAf,MAAe,CAAA,MAAA,EAAA,eAAA,CAAA;EAAf,UAAA,CAAA,EACE,MADF,CAAA,MAAA,EACiB,iBADjB,CAAA;EACiB,UAAA,CAAA,EACf,kBADe;;AACf,UAGE,YAAA,CAHF;EAAkB,KAAA,EAAA,MAAA;EAGhB,OAAA,EAAA,MAAY;EAgBZ,WAAA,CAAA,EAAA,MAAc;EAOd,cAAA,CAAA,EAAA,MAAe;EAuBf,OAAA,CAAA,EAAA;IAOA,IAAA,CAAA,EAAA,MAAA;IAUA,GAAA,CAAA,EAAA,MAAA;IAEa,KAAA,CAAA,EAAA,MAAA;EAAf,CAAA;EAEL,OAAA,CAAA,EAAA;IAAc,IAAA,EAAA,MAAA;IAYd,GAAA,CAAA,EAAA,MAAW;EAIJ,CAAA;;AACJ,UApEI,cAAA,CAoEJ;EACc,IAAA,EAAA,MAAA;EAAf,QAAA,EAAA,MAAA;EAAM,WAAA,CAAA,EAAA,MAAA;EAMD,SAAA,CAAA,EAvEH,MAuEG,CAAA,MAAA,EAAuB;IAC3B,OAAA,EAAA,MAAA;IAAL,WAAA,CAAA,EAAA,MAAA;EAImB,CAAA,CAAA;;AAAT,UAzED,eAAA,CAyEC;EAMF,OAAA,EAAA,MAAA;EACJ,QAAA,CAAA,EA9EC,MA8ED,CAAA,MAAA,EA9EgB,kBA8EhB,CAAA;EACD,WAAA,CAAA,EAAA,MAAA;EACR,QAAA,CAAA,EAAA;IAAgB,IAAA,CAAA,EAAA;;;;QCnGH,OAAA,CAAA,EAAA,OAA0B;;;;;;;;;;;;;UDwCzB,iBAAA;;WAEN;aACE;;;UAII,kBAAA;;YAEL;;;;;;;UAQK,cAAA;;eAEF,eAAe;;UAEpB;;;;;;;;;;;UAYA,WAAA;;;UAIO,kBAAA;aACJ,eAAe;YAChB,eAAe;;;;;UAMV,uBAAA;QACT,KAAK;;;;YAID,eAAe;;;;;iBAMX,gBAAA,WACJ,6BACD,0BACR;;;;;AAlHH;;;;;;;;;;AASA;AAgBA;AAOA;AAuBA;AAOA;AAUA;AAE8B,iBC3Dd,0BAAA,CD2Dc,OAAA,EC3DsB,gBD2DtB,CAAA,EC3DyC,cD2DzC"}
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"}
package/dist/index.mjs CHANGED
@@ -1,110 +1,171 @@
1
- //#region src/schema-converter.ts
2
- /**
3
- * Convert a Standard Schema to JSON Schema (AsyncAPI format)
4
- *
5
- * This is a basic converter that returns a generic object schema.
6
- * Users should provide their own schema-to-JSON-Schema converter function
7
- * specific to their schema library.
8
- *
9
- * For Zod users, import and use zodToJsonSchema from @amqp-contract/zod
10
- *
11
- * @example
12
- * ```ts
13
- * import { zodToJsonSchema } from '@amqp-contract/zod';
14
- * import { generateAsyncAPI } from '@amqp-contract/asyncapi';
15
- *
16
- * // Use zodToJsonSchema for converting Zod schemas
17
- * const jsonSchema = zodToJsonSchema(zodSchema);
18
- * ```
19
- */
20
- function standardSchemaToJsonSchema(_schema) {
21
- return { type: "object" };
22
- }
23
-
24
- //#endregion
25
- //#region src/generator.ts
26
- /**
27
- * Generate AsyncAPI 3.0.0 specification from AMQP contract
28
- */
29
- function generateAsyncAPI(contract, options) {
30
- const channels = {};
31
- const operations = {};
32
- const messages = {};
33
- if (contract.queues) for (const [queueName, queue] of Object.entries(contract.queues)) {
34
- const binding = { amqp: {
35
- is: "queue",
36
- queue: { name: queue.name }
37
- } };
38
- if (queue.durable !== void 0) binding.amqp.queue.durable = queue.durable;
39
- if (queue.exclusive !== void 0) binding.amqp.queue.exclusive = queue.exclusive;
40
- if (queue.autoDelete !== void 0) binding.amqp.queue.autoDelete = queue.autoDelete;
41
- channels[queueName] = {
42
- address: queue.name,
43
- description: `Queue: ${queue.name}`,
44
- bindings: binding
45
- };
1
+ //#region src/index.ts
2
+ var AsyncAPIGenerator = class {
3
+ converters;
4
+ constructor(options = {}) {
5
+ this.converters = options.schemaConverters ?? [];
46
6
  }
47
- if (contract.exchanges) for (const [exchangeName, exchange] of Object.entries(contract.exchanges)) {
48
- const binding = { amqp: {
49
- is: "routingKey",
50
- exchange: {
51
- name: exchange.name,
52
- type: exchange.type
7
+ /**
8
+ * Generate an AsyncAPI 3.0 document from a contract definition
9
+ */
10
+ async generate(contract, options) {
11
+ const convertedChannels = {};
12
+ const convertedOperations = {};
13
+ const convertedMessages = {};
14
+ const publisherMessages = /* @__PURE__ */ new Map();
15
+ const consumerMessages = /* @__PURE__ */ new Map();
16
+ if (contract.publishers) for (const [publisherName, publisher] of Object.entries(contract.publishers)) {
17
+ const channelKey = this.getExchangeName(publisher.exchange, contract);
18
+ publisherMessages.set(publisherName, {
19
+ message: publisher.message,
20
+ channelKey
21
+ });
22
+ }
23
+ if (contract.consumers) for (const [consumerName, consumer] of Object.entries(contract.consumers)) {
24
+ const channelKey = this.getQueueName(consumer.queue, contract);
25
+ consumerMessages.set(consumerName, {
26
+ message: consumer.message,
27
+ channelKey
28
+ });
29
+ }
30
+ if (contract.queues) for (const [queueName, queue] of Object.entries(contract.queues)) {
31
+ const channelMessages = {};
32
+ for (const [consumerName, { message, channelKey }] of consumerMessages) if (channelKey === queueName) {
33
+ const messageName = `${consumerName}Message`;
34
+ channelMessages[messageName] = await this.convertMessage(message);
35
+ convertedMessages[messageName] = await this.convertMessage(message);
53
36
  }
54
- } };
55
- if (exchange.durable !== void 0) binding.amqp.exchange.durable = exchange.durable;
56
- if (exchange.autoDelete !== void 0) binding.amqp.exchange.autoDelete = exchange.autoDelete;
57
- channels[exchangeName] = {
58
- address: exchange.name,
59
- description: `Exchange: ${exchange.name} (${exchange.type})`,
60
- bindings: binding
37
+ const channel = { ...this.queueToChannel(queue) };
38
+ if (Object.keys(channelMessages).length > 0) channel.messages = channelMessages;
39
+ convertedChannels[queueName] = channel;
40
+ }
41
+ if (contract.exchanges) for (const [exchangeName, exchange] of Object.entries(contract.exchanges)) {
42
+ const channelMessages = {};
43
+ for (const [publisherName, { message, channelKey }] of publisherMessages) if (channelKey === exchangeName) {
44
+ const messageName = `${publisherName}Message`;
45
+ channelMessages[messageName] = await this.convertMessage(message);
46
+ convertedMessages[messageName] = await this.convertMessage(message);
47
+ }
48
+ const channel = { ...this.exchangeToChannel(exchange) };
49
+ if (Object.keys(channelMessages).length > 0) channel.messages = channelMessages;
50
+ convertedChannels[exchangeName] = channel;
51
+ }
52
+ if (contract.publishers) for (const [publisherName, publisher] of Object.entries(contract.publishers)) {
53
+ const exchangeName = this.getExchangeName(publisher.exchange, contract);
54
+ const messageName = `${publisherName}Message`;
55
+ convertedOperations[publisherName] = {
56
+ action: "send",
57
+ channel: { $ref: `#/channels/${exchangeName}` },
58
+ messages: [{ $ref: `#/channels/${exchangeName}/messages/${messageName}` }],
59
+ summary: `Publish to ${publisher.exchange.name}`,
60
+ ...publisher.routingKey && { description: `Routing key: ${publisher.routingKey}` }
61
+ };
62
+ }
63
+ if (contract.consumers) for (const [consumerName, consumer] of Object.entries(contract.consumers)) {
64
+ const queueName = this.getQueueName(consumer.queue, contract);
65
+ const messageName = `${consumerName}Message`;
66
+ convertedOperations[consumerName] = {
67
+ action: "receive",
68
+ channel: { $ref: `#/channels/${queueName}` },
69
+ messages: [{ $ref: `#/channels/${queueName}/messages/${messageName}` }],
70
+ summary: `Consume from ${consumer.queue.name}`,
71
+ ...consumer.prefetch && { description: `Prefetch: ${consumer.prefetch}` }
72
+ };
73
+ }
74
+ return {
75
+ ...options,
76
+ asyncapi: "3.0.0",
77
+ channels: convertedChannels,
78
+ operations: convertedOperations,
79
+ components: { messages: convertedMessages }
61
80
  };
62
81
  }
63
- if (contract.publishers) for (const [publisherName, publisher] of Object.entries(contract.publishers)) {
64
- const messageName = `${publisherName}Message`;
65
- messages[messageName] = {
66
- name: messageName,
67
- title: `${publisherName} message`,
68
- contentType: "application/json",
69
- payload: standardSchemaToJsonSchema(publisher.message)
70
- };
71
- operations[publisherName] = {
72
- action: "send",
73
- channel: { $ref: `#/channels/${publisher.exchange}` },
74
- messages: [{ $ref: `#/components/messages/${messageName}` }],
75
- description: `Publish message to ${publisher.exchange}`
82
+ /**
83
+ * Convert a message definition to AsyncAPI MessageObject
84
+ */
85
+ async convertMessage(message) {
86
+ const payload = message.payload;
87
+ const result = {
88
+ payload: await this.convertSchema(payload, "input"),
89
+ contentType: "application/json"
76
90
  };
91
+ if (message.headers) {
92
+ const headersJsonSchema = await this.convertSchema(message.headers, "input");
93
+ if (headersJsonSchema) result["headers"] = headersJsonSchema;
94
+ }
95
+ if (message.summary) result["summary"] = message.summary;
96
+ if (message.description) result["description"] = message.description;
97
+ return result;
77
98
  }
78
- if (contract.consumers) for (const [consumerName, consumer] of Object.entries(contract.consumers)) {
79
- const messageName = `${consumerName}Message`;
80
- messages[messageName] = {
81
- name: messageName,
82
- title: `${consumerName} message`,
83
- contentType: "application/json",
84
- payload: standardSchemaToJsonSchema(consumer.message)
99
+ /**
100
+ * Convert a queue definition to AsyncAPI ChannelObject
101
+ */
102
+ queueToChannel(queue) {
103
+ return {
104
+ address: queue.name,
105
+ title: queue.name,
106
+ description: `AMQP Queue: ${queue.name}`,
107
+ bindings: { amqp: {
108
+ is: "queue",
109
+ queue: {
110
+ name: queue.name,
111
+ durable: queue.durable ?? false,
112
+ exclusive: queue.exclusive ?? false,
113
+ autoDelete: queue.autoDelete ?? false,
114
+ ...queue.arguments && { vhost: "/" }
115
+ }
116
+ } }
85
117
  };
86
- operations[consumerName] = {
87
- action: "receive",
88
- channel: { $ref: `#/channels/${consumer.queue}` },
89
- messages: [{ $ref: `#/components/messages/${messageName}` }],
90
- description: `Consume message from ${consumer.queue}`
118
+ }
119
+ /**
120
+ * Convert an exchange definition to AsyncAPI ChannelObject
121
+ */
122
+ exchangeToChannel(exchange) {
123
+ return {
124
+ address: exchange.name,
125
+ title: exchange.name,
126
+ description: `AMQP Exchange: ${exchange.name} (${exchange.type})`,
127
+ bindings: { amqp: {
128
+ is: "routingKey",
129
+ exchange: {
130
+ name: exchange.name,
131
+ type: exchange.type,
132
+ durable: exchange.durable ?? false,
133
+ autoDelete: exchange.autoDelete ?? false,
134
+ ...exchange.arguments && { vhost: "/" }
135
+ }
136
+ } }
91
137
  };
92
138
  }
93
- const result = {
94
- asyncapi: "3.0.0",
95
- info: {
96
- title: options.info.title ?? "AMQP Contract API",
97
- version: options.info.version ?? "1.0.0",
98
- ...options.info
99
- },
100
- channels,
101
- operations,
102
- components: { messages }
103
- };
104
- if (options.servers) result.servers = options.servers;
105
- return result;
106
- }
139
+ /**
140
+ * Get the name/key of an exchange from the contract
141
+ */
142
+ getExchangeName(exchange, contract) {
143
+ if (contract.exchanges) {
144
+ for (const [name, ex] of Object.entries(contract.exchanges)) if (ex === exchange || ex.name === exchange.name) return name;
145
+ }
146
+ return exchange.name;
147
+ }
148
+ /**
149
+ * Get the name/key of a queue from the contract
150
+ */
151
+ getQueueName(queue, contract) {
152
+ if (contract.queues) {
153
+ for (const [name, q] of Object.entries(contract.queues)) if (q === queue || q.name === queue.name) return name;
154
+ }
155
+ return queue.name;
156
+ }
157
+ /**
158
+ * Convert a Standard Schema to JSON Schema using oRPC converters
159
+ */
160
+ async convertSchema(schema, strategy) {
161
+ for (const converter of this.converters) if (await converter.condition(schema, { strategy })) {
162
+ const [_required, jsonSchema] = await converter.convert(schema, { strategy });
163
+ return jsonSchema;
164
+ }
165
+ return { type: "object" };
166
+ }
167
+ };
107
168
 
108
169
  //#endregion
109
- export { generateAsyncAPI, standardSchemaToJsonSchema };
170
+ export { AsyncAPIGenerator };
110
171
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["channels: Record<string, AsyncAPIChannel>","operations: Record<string, AsyncAPIOperation>","messages: Record<string, AsyncAPIMessageRef>","binding: {\n amqp?: {\n is: \"queue\";\n queue?: {\n name: string;\n durable?: boolean;\n exclusive?: boolean;\n autoDelete?: boolean;\n };\n };\n }","binding: {\n amqp?: {\n is: \"routingKey\";\n exchange?: {\n name: string;\n type: \"topic\" | \"direct\" | \"fanout\" | \"headers\";\n durable?: boolean;\n autoDelete?: boolean;\n };\n };\n }","result: AsyncAPIDocument"],"sources":["../src/schema-converter.ts","../src/generator.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type { AsyncAPISchema } from \"./generator.js\";\n\n/**\n * Convert a Standard Schema to JSON Schema (AsyncAPI format)\n *\n * This is a basic converter that returns a generic object schema.\n * Users should provide their own schema-to-JSON-Schema converter function\n * specific to their schema library.\n *\n * For Zod users, import and use zodToJsonSchema from @amqp-contract/zod\n *\n * @example\n * ```ts\n * import { zodToJsonSchema } from '@amqp-contract/zod';\n * import { generateAsyncAPI } from '@amqp-contract/asyncapi';\n *\n * // Use zodToJsonSchema for converting Zod schemas\n * const jsonSchema = zodToJsonSchema(zodSchema);\n * ```\n */\nexport function standardSchemaToJsonSchema(_schema: StandardSchemaV1): AsyncAPISchema {\n // Basic fallback - returns a generic object schema\n // Users should provide their own converter for better results\n return { type: \"object\" };\n}\n","import type { ContractDefinition } from \"@amqp-contract/contract\";\nimport { standardSchemaToJsonSchema } from \"./schema-converter.js\";\n\n/**\n * AsyncAPI 3.0.0 Specification\n */\nexport interface AsyncAPIDocument {\n asyncapi: \"3.0.0\";\n info: AsyncAPIInfo;\n servers?: Record<string, AsyncAPIServer>;\n channels?: Record<string, AsyncAPIChannel>;\n operations?: Record<string, AsyncAPIOperation>;\n components?: AsyncAPIComponents;\n}\n\nexport interface AsyncAPIInfo {\n title: string;\n version: string;\n description?: string;\n termsOfService?: string;\n contact?: {\n name?: string;\n url?: string;\n email?: string;\n };\n license?: {\n name: string;\n url?: string;\n };\n}\n\nexport interface AsyncAPIServer {\n host: string;\n protocol: string;\n description?: string;\n variables?: Record<string, { default: string; description?: string }>;\n}\n\nexport interface AsyncAPIChannel {\n address: string;\n messages?: Record<string, AsyncAPIMessageRef>;\n description?: string;\n bindings?: {\n amqp?: {\n is: \"queue\" | \"routingKey\";\n queue?: {\n name: string;\n durable?: boolean;\n exclusive?: boolean;\n autoDelete?: boolean;\n };\n exchange?: {\n name: string;\n type: \"topic\" | \"direct\" | \"fanout\" | \"headers\";\n durable?: boolean;\n autoDelete?: boolean;\n };\n };\n };\n}\n\nexport interface AsyncAPIOperation {\n action: \"send\" | \"receive\";\n channel: AsyncAPIRef;\n messages?: AsyncAPIMessageRef[];\n description?: string;\n}\n\nexport interface AsyncAPIMessageRef {\n $ref?: string;\n payload?: AsyncAPISchema;\n contentType?: string;\n name?: string;\n title?: string;\n summary?: string;\n description?: string;\n}\n\nexport interface AsyncAPISchema {\n type?: string;\n properties?: Record<string, AsyncAPISchema>;\n required?: string[];\n items?: AsyncAPISchema;\n $ref?: string;\n description?: string;\n format?: string;\n minimum?: number;\n maximum?: number;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n enum?: unknown[];\n}\n\ninterface AsyncAPIRef {\n $ref: string;\n}\n\nexport interface AsyncAPIComponents {\n messages?: Record<string, AsyncAPIMessageRef>;\n schemas?: Record<string, AsyncAPISchema>;\n}\n\n/**\n * Options for generating AsyncAPI specification\n */\nexport interface GenerateAsyncAPIOptions {\n info: Omit<AsyncAPIInfo, \"title\" | \"version\"> & {\n title?: string;\n version?: string;\n };\n servers?: Record<string, AsyncAPIServer>;\n}\n\n/**\n * Generate AsyncAPI 3.0.0 specification from AMQP contract\n */\nexport function generateAsyncAPI(\n contract: ContractDefinition,\n options: GenerateAsyncAPIOptions,\n): AsyncAPIDocument {\n const channels: Record<string, AsyncAPIChannel> = {};\n const operations: Record<string, AsyncAPIOperation> = {};\n const messages: Record<string, AsyncAPIMessageRef> = {};\n\n // Generate channels from queues\n if (contract.queues) {\n for (const [queueName, queue] of Object.entries(contract.queues)) {\n const binding: {\n amqp?: {\n is: \"queue\";\n queue?: {\n name: string;\n durable?: boolean;\n exclusive?: boolean;\n autoDelete?: boolean;\n };\n };\n } = {\n amqp: {\n is: \"queue\",\n queue: {\n name: queue.name,\n },\n },\n };\n\n if (queue.durable !== undefined) {\n binding.amqp!.queue!.durable = queue.durable;\n }\n if (queue.exclusive !== undefined) {\n binding.amqp!.queue!.exclusive = queue.exclusive;\n }\n if (queue.autoDelete !== undefined) {\n binding.amqp!.queue!.autoDelete = queue.autoDelete;\n }\n\n channels[queueName] = {\n address: queue.name,\n description: `Queue: ${queue.name}`,\n bindings: binding,\n };\n }\n }\n\n // Generate channels from exchanges\n if (contract.exchanges) {\n for (const [exchangeName, exchange] of Object.entries(contract.exchanges)) {\n const binding: {\n amqp?: {\n is: \"routingKey\";\n exchange?: {\n name: string;\n type: \"topic\" | \"direct\" | \"fanout\" | \"headers\";\n durable?: boolean;\n autoDelete?: boolean;\n };\n };\n } = {\n amqp: {\n is: \"routingKey\",\n exchange: {\n name: exchange.name,\n type: exchange.type,\n },\n },\n };\n\n if (exchange.durable !== undefined) {\n binding.amqp!.exchange!.durable = exchange.durable;\n }\n if (exchange.autoDelete !== undefined) {\n binding.amqp!.exchange!.autoDelete = exchange.autoDelete;\n }\n\n channels[exchangeName] = {\n address: exchange.name,\n description: `Exchange: ${exchange.name} (${exchange.type})`,\n bindings: binding,\n };\n }\n }\n\n // Generate operations from publishers\n if (contract.publishers) {\n for (const [publisherName, publisher] of Object.entries(contract.publishers)) {\n const messageName = `${publisherName}Message`;\n\n messages[messageName] = {\n name: messageName,\n title: `${publisherName} message`,\n contentType: \"application/json\",\n payload: standardSchemaToJsonSchema(publisher.message),\n };\n\n operations[publisherName] = {\n action: \"send\",\n channel: { $ref: `#/channels/${publisher.exchange}` },\n messages: [{ $ref: `#/components/messages/${messageName}` }],\n description: `Publish message to ${publisher.exchange}`,\n };\n }\n }\n\n // Generate operations from consumers\n if (contract.consumers) {\n for (const [consumerName, consumer] of Object.entries(contract.consumers)) {\n const messageName = `${consumerName}Message`;\n\n messages[messageName] = {\n name: messageName,\n title: `${consumerName} message`,\n contentType: \"application/json\",\n payload: standardSchemaToJsonSchema(consumer.message),\n };\n\n operations[consumerName] = {\n action: \"receive\",\n channel: { $ref: `#/channels/${consumer.queue}` },\n messages: [{ $ref: `#/components/messages/${messageName}` }],\n description: `Consume message from ${consumer.queue}`,\n };\n }\n }\n\n const result: AsyncAPIDocument = {\n asyncapi: \"3.0.0\",\n info: {\n title: options.info.title ?? \"AMQP Contract API\",\n version: options.info.version ?? \"1.0.0\",\n ...options.info,\n },\n channels,\n operations,\n components: {\n messages,\n },\n };\n\n if (options.servers) {\n result.servers = options.servers;\n }\n\n return result;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,2BAA2B,SAA2C;AAGpF,QAAO,EAAE,MAAM,UAAU;;;;;;;;AC6F3B,SAAgB,iBACd,UACA,SACkB;CAClB,MAAMA,WAA4C,EAAE;CACpD,MAAMC,aAAgD,EAAE;CACxD,MAAMC,WAA+C,EAAE;AAGvD,KAAI,SAAS,OACX,MAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,SAAS,OAAO,EAAE;EAChE,MAAMC,UAUF,EACF,MAAM;GACJ,IAAI;GACJ,OAAO,EACL,MAAM,MAAM,MACb;GACF,EACF;AAED,MAAI,MAAM,YAAY,OACpB,SAAQ,KAAM,MAAO,UAAU,MAAM;AAEvC,MAAI,MAAM,cAAc,OACtB,SAAQ,KAAM,MAAO,YAAY,MAAM;AAEzC,MAAI,MAAM,eAAe,OACvB,SAAQ,KAAM,MAAO,aAAa,MAAM;AAG1C,WAAS,aAAa;GACpB,SAAS,MAAM;GACf,aAAa,UAAU,MAAM;GAC7B,UAAU;GACX;;AAKL,KAAI,SAAS,UACX,MAAK,MAAM,CAAC,cAAc,aAAa,OAAO,QAAQ,SAAS,UAAU,EAAE;EACzE,MAAMC,UAUF,EACF,MAAM;GACJ,IAAI;GACJ,UAAU;IACR,MAAM,SAAS;IACf,MAAM,SAAS;IAChB;GACF,EACF;AAED,MAAI,SAAS,YAAY,OACvB,SAAQ,KAAM,SAAU,UAAU,SAAS;AAE7C,MAAI,SAAS,eAAe,OAC1B,SAAQ,KAAM,SAAU,aAAa,SAAS;AAGhD,WAAS,gBAAgB;GACvB,SAAS,SAAS;GAClB,aAAa,aAAa,SAAS,KAAK,IAAI,SAAS,KAAK;GAC1D,UAAU;GACX;;AAKL,KAAI,SAAS,WACX,MAAK,MAAM,CAAC,eAAe,cAAc,OAAO,QAAQ,SAAS,WAAW,EAAE;EAC5E,MAAM,cAAc,GAAG,cAAc;AAErC,WAAS,eAAe;GACtB,MAAM;GACN,OAAO,GAAG,cAAc;GACxB,aAAa;GACb,SAAS,2BAA2B,UAAU,QAAQ;GACvD;AAED,aAAW,iBAAiB;GAC1B,QAAQ;GACR,SAAS,EAAE,MAAM,cAAc,UAAU,YAAY;GACrD,UAAU,CAAC,EAAE,MAAM,yBAAyB,eAAe,CAAC;GAC5D,aAAa,sBAAsB,UAAU;GAC9C;;AAKL,KAAI,SAAS,UACX,MAAK,MAAM,CAAC,cAAc,aAAa,OAAO,QAAQ,SAAS,UAAU,EAAE;EACzE,MAAM,cAAc,GAAG,aAAa;AAEpC,WAAS,eAAe;GACtB,MAAM;GACN,OAAO,GAAG,aAAa;GACvB,aAAa;GACb,SAAS,2BAA2B,SAAS,QAAQ;GACtD;AAED,aAAW,gBAAgB;GACzB,QAAQ;GACR,SAAS,EAAE,MAAM,cAAc,SAAS,SAAS;GACjD,UAAU,CAAC,EAAE,MAAM,yBAAyB,eAAe,CAAC;GAC5D,aAAa,wBAAwB,SAAS;GAC/C;;CAIL,MAAMC,SAA2B;EAC/B,UAAU;EACV,MAAM;GACJ,OAAO,QAAQ,KAAK,SAAS;GAC7B,SAAS,QAAQ,KAAK,WAAW;GACjC,GAAG,QAAQ;GACZ;EACD;EACA;EACA,YAAY,EACV,UACD;EACF;AAED,KAAI,QAAQ,QACV,QAAO,UAAU,QAAQ;AAG3B,QAAO"}
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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amqp-contract/asyncapi",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "description": "AsyncAPI specification generator for amqp-contract",
5
5
  "keywords": [
6
6
  "amqp",
@@ -41,14 +41,21 @@
41
41
  "dist"
42
42
  ],
43
43
  "dependencies": {
44
+ "@orpc/openapi": "1.13.0",
44
45
  "@standard-schema/spec": "1.1.0",
45
- "@amqp-contract/contract": "0.1.4"
46
+ "@amqp-contract/contract": "0.2.0"
46
47
  },
47
48
  "devDependencies": {
49
+ "@asyncapi/parser": "3.4.0",
50
+ "@orpc/arktype": "1.13.0",
51
+ "@orpc/valibot": "1.13.0",
52
+ "@orpc/zod": "1.13.0",
48
53
  "@types/node": "25.0.3",
49
54
  "@vitest/coverage-v8": "4.0.16",
55
+ "arktype": "2.1.29",
50
56
  "tsdown": "0.18.2",
51
57
  "typescript": "5.9.3",
58
+ "valibot": "1.2.0",
52
59
  "vitest": "4.0.16",
53
60
  "zod": "4.2.1",
54
61
  "@amqp-contract/tsconfig": "0.0.0"