@eventcatalog/generator-asyncapi 0.0.2
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/LICENSE.md +661 -0
- package/README.md +132 -0
- package/dist/index.d.mts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +292 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +261 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<h1>⚡️ AsyncAPI generator for EventCatalog</h1>
|
|
4
|
+
|
|
5
|
+
[![PRs Welcome][prs-badge]][prs]
|
|
6
|
+
<img src="https://img.shields.io/github/actions/workflow/status/event-catalog/generator-asyncapi/verify-build.yml"/>
|
|
7
|
+
[](https://discord.gg/3rjaZMmrAm) [<img src="https://img.shields.io/badge/LinkedIn-0077B5?style=for-the-badge&logo=linkedin&logoColor=white" height="20px" />](https://www.linkedin.com/in/david-boyne/) [](https://eda-visuals.boyney.io/?utm_source=event-catalog-gihub)
|
|
8
|
+
|
|
9
|
+
<img alt="header" src="./images/asyncapi.jpeg" />
|
|
10
|
+
|
|
11
|
+
<h4>Features: Generate EventCatalogs with your AsyncAPI files, Auto versioning, schema downloads, map to domains, custom AsyncAPI extensions and more... </h4>
|
|
12
|
+
|
|
13
|
+
[Read the Docs](https://eventcatalog.dev/) | [Edit the Docs](https://github.com/event-catalog/docs) | [View Demo](https://demo.eventcatalog.dev/docs)
|
|
14
|
+
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<hr/>
|
|
18
|
+
|
|
19
|
+
# Core Features
|
|
20
|
+
|
|
21
|
+
- 📃 Document domains, services and messages from your AsyncAPI file ([example](https://github.com/event-catalog/eventcatalog-asyncapi-example))
|
|
22
|
+
- 📊 Visualise your architecture ([demo](https://demo.eventcatalog.dev/visualiser))
|
|
23
|
+
- ⭐ Download your AsyncAPI files and message schemas form EventCatalog (e.g Avro, JSON) ([demo](https://demo.eventcatalog.dev/docs/events/InventoryAdjusted/0.0.4))
|
|
24
|
+
- 💅 Custom MDX components ([read more](https://eventcatalog.dev/docs/development/components/using-components))
|
|
25
|
+
- 🗄️ Auto versioning of your domains, services and messages
|
|
26
|
+
- ⭐ Discoverability feature (search, filter and more) ([demo](https://demo.eventcatalog.dev/discover/events))
|
|
27
|
+
- ⭐ And much more...
|
|
28
|
+
|
|
29
|
+
# How it works
|
|
30
|
+
|
|
31
|
+
[EventCatalog](https://www.eventcatalog.dev/) is technology agnostic, meaning it can integrate with any schemas, specs or brokers.
|
|
32
|
+
|
|
33
|
+
EventCatalog supports [generators](https://www.eventcatalog.dev/docs/development/plugins/generators).
|
|
34
|
+
Generators are scripts are run to pre build to generate content in your catalog. Generators can use the [EventCatalog SDK](https://www.eventcatalog.dev/docs/sdk).
|
|
35
|
+
|
|
36
|
+
With this AsyncAPI plugin you can connect your AsyncAPI files to your catalog. This is done by defining your generators in your `eventcatlaog.config.js` file.
|
|
37
|
+
|
|
38
|
+
```js
|
|
39
|
+
...
|
|
40
|
+
generators: [
|
|
41
|
+
[
|
|
42
|
+
'@eventcatalogtest/generator-asyncapi',
|
|
43
|
+
{
|
|
44
|
+
path: [path.join(__dirname, 'asyncapi-files', 'orders-service.yml'),
|
|
45
|
+
domain: { id: 'orders', name: 'Orders', version: '0.0.1' },
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
],
|
|
49
|
+
...
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
In this example the generator will read the `orders-service.yml` file and populate services and messages inside your catalog. It will add the service to the domain `Orders`.
|
|
53
|
+
|
|
54
|
+
You can see an example in the [eventcatalog-asyncapi-example](https://github.com/event-catalog/eventcatalog-asyncapi-example/blob/main/eventcatalog.config.js) repo
|
|
55
|
+
|
|
56
|
+
# Getting started
|
|
57
|
+
|
|
58
|
+
## Installation and configuration
|
|
59
|
+
|
|
60
|
+
_Make sure you are on the latest version of EventCatalog_.
|
|
61
|
+
|
|
62
|
+
1. Install the package
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
@eventcatalog/generator-asyncapi
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
2. Configure your `eventcatalog.config.js` file [(see example)](https://github.com/event-catalog/eventcatalog-asyncapi-example/blob/main/eventcatalog.config.js)
|
|
69
|
+
|
|
70
|
+
3. Run the generate command
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
npm run generate
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
4. See your new domains, services and messages, run
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
npm run dev
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Found a problem?
|
|
83
|
+
|
|
84
|
+
Raise a GitHub issue on this project, or contact us on [our Discord server](https://discord.gg/3rjaZMmrAm).
|
|
85
|
+
|
|
86
|
+
# Sponsors
|
|
87
|
+
|
|
88
|
+
Thank you to our EventCatalog project sponsors.
|
|
89
|
+
|
|
90
|
+
<hr />
|
|
91
|
+
|
|
92
|
+
<div align="center">
|
|
93
|
+
<img alt="hookdeck" src="./images/sponsors/hookdeck.svg" />
|
|
94
|
+
<p style="margin: 0; padding: 0;">Serverless infrastructure for event-driven architecture. </p>
|
|
95
|
+
<a href="https://hookdeck.com/?ref=eventcatalog-sponsor" target="_blank" >Learn more</a>
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
<hr />
|
|
99
|
+
|
|
100
|
+
_Sponsors help make EventCatalog sustainable, want to help the project? Get in touch! Or [visit our sponsor page](https://www.eventcatalog.dev/support)._
|
|
101
|
+
|
|
102
|
+
# Enterprise support
|
|
103
|
+
|
|
104
|
+
Interested in collaborating with us? Our offerings include dedicated support, priority assistance, feature development, custom integrations, and more.
|
|
105
|
+
|
|
106
|
+
Find more details on our [services page](https://eventcatalog.dev/services).
|
|
107
|
+
|
|
108
|
+
# Contributing
|
|
109
|
+
|
|
110
|
+
If you have any questions, features or issues please raise any issue or pull requests you like. We will try my best to get back to you.
|
|
111
|
+
|
|
112
|
+
You can find the [contributing guidelines here](https://eventcatalog.dev/docs/contributing/overview).
|
|
113
|
+
|
|
114
|
+
## Running the project locally
|
|
115
|
+
|
|
116
|
+
1. Clone the repo
|
|
117
|
+
1. Install required dependencies `pnpm i`
|
|
118
|
+
1. Run the examples `npx tsx examples/streelights-mqtt/index.ts
|
|
119
|
+
1. Run tests `pnpm run tests`
|
|
120
|
+
|
|
121
|
+
[license-badge]: https://img.shields.io/github/license/event-catalog/eventcatalog.svg?color=yellow
|
|
122
|
+
[license]: https://github.com/event-catalog/eventcatalog/blob/main/LICENSE
|
|
123
|
+
[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
|
|
124
|
+
[prs]: http://makeapullrequest.com
|
|
125
|
+
[github-watch-badge]: https://img.shields.io/github/watchers/event-catalog/eventcatalog.svg?style=social
|
|
126
|
+
[github-watch]: https://github.com/event-catalog/eventcatalog/watchers
|
|
127
|
+
[github-star-badge]: https://img.shields.io/github/stars/event-catalog/eventcatalog.svg?style=social
|
|
128
|
+
[github-star]: https://github.com/event-catalog/eventcatalog/stargazers
|
|
129
|
+
|
|
130
|
+
# Commercial Use
|
|
131
|
+
|
|
132
|
+
This project is governed by the [AGPL-3.0](/LICENSE.md) copyleft license. To ensure the sustainability of the project, you can freely make use of this software as long the outcome is distributed under the same license. Otherwise, you must obtain a [commercial license](./LICENSE-COMMERCIAL.md) that removes such restrictions.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type Domain = {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
version: string;
|
|
5
|
+
};
|
|
6
|
+
type Props = {
|
|
7
|
+
path: string | string[];
|
|
8
|
+
domain?: Domain;
|
|
9
|
+
debug?: boolean;
|
|
10
|
+
};
|
|
11
|
+
declare const _default: (config: any, options: Props) => Promise<void>;
|
|
12
|
+
|
|
13
|
+
export { _default as default };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type Domain = {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
version: string;
|
|
5
|
+
};
|
|
6
|
+
type Props = {
|
|
7
|
+
path: string | string[];
|
|
8
|
+
domain?: Domain;
|
|
9
|
+
debug?: boolean;
|
|
10
|
+
};
|
|
11
|
+
declare const _default: (config: any, options: Props) => Promise<void>;
|
|
12
|
+
|
|
13
|
+
export { _default as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
default: () => src_default
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(src_exports);
|
|
36
|
+
var import_parser = require("@asyncapi/parser");
|
|
37
|
+
var import_promises = require("fs/promises");
|
|
38
|
+
var import_sdk = __toESM(require("@eventcatalog/sdk"));
|
|
39
|
+
var import_slugify = __toESM(require("slugify"));
|
|
40
|
+
|
|
41
|
+
// src/utils/schemas.ts
|
|
42
|
+
var getFileExtentionFromSchemaFormat = (format = "") => {
|
|
43
|
+
if (format.includes("avro")) return "avsc";
|
|
44
|
+
if (format.includes("yml")) return "yml";
|
|
45
|
+
if (format.includes("json")) return "json";
|
|
46
|
+
if (format.includes("openapi")) return "openapi";
|
|
47
|
+
if (format.includes("protobuf")) return "protobuf";
|
|
48
|
+
if (format.includes("yaml")) return "yaml";
|
|
49
|
+
return "json";
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// src/utils/messages.ts
|
|
53
|
+
var defaultMarkdown = (document, message) => {
|
|
54
|
+
return `
|
|
55
|
+
## Architecture
|
|
56
|
+
<NodeGraph />
|
|
57
|
+
|
|
58
|
+
${messageHasSchema(message) ? `
|
|
59
|
+
## Schema
|
|
60
|
+
<SchemaViewer file="${getSchemaFileName(message)}" title="Message Schema" maxHeight="500" />
|
|
61
|
+
` : ""}
|
|
62
|
+
|
|
63
|
+
${message.externalDocs() ? `
|
|
64
|
+
## External documentation
|
|
65
|
+
- [${message.externalDocs()?.description()}](${message.externalDocs()?.url()})
|
|
66
|
+
` : ""}
|
|
67
|
+
|
|
68
|
+
`;
|
|
69
|
+
};
|
|
70
|
+
var getSummary = (message) => {
|
|
71
|
+
const messageSummary = message.hasSummary() ? message.summary() : "";
|
|
72
|
+
const messageDescription = message.hasDescription() ? message.description() : "";
|
|
73
|
+
let eventCatalogMessageSummary = messageSummary;
|
|
74
|
+
if (!eventCatalogMessageSummary) {
|
|
75
|
+
eventCatalogMessageSummary = messageDescription && messageDescription.length < 150 ? messageDescription : "";
|
|
76
|
+
}
|
|
77
|
+
return eventCatalogMessageSummary;
|
|
78
|
+
};
|
|
79
|
+
var messageHasSchema = (message) => {
|
|
80
|
+
return message.hasPayload() && message.schemaFormat();
|
|
81
|
+
};
|
|
82
|
+
var getSchemaFileName = (message) => {
|
|
83
|
+
const extension = getFileExtentionFromSchemaFormat(message.schemaFormat());
|
|
84
|
+
return `schema.${extension}`;
|
|
85
|
+
};
|
|
86
|
+
var getMessageName = (message) => {
|
|
87
|
+
return message.hasTitle() && message.title() ? message.title() : message.id();
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// src/utils/services.ts
|
|
91
|
+
var defaultMarkdown2 = (document) => {
|
|
92
|
+
return `
|
|
93
|
+
|
|
94
|
+
${document.info().hasDescription() ? `${document.info().description()}` : ""}
|
|
95
|
+
|
|
96
|
+
## Architecture diagram
|
|
97
|
+
<NodeGraph />
|
|
98
|
+
|
|
99
|
+
${document.info().externalDocs() ? `
|
|
100
|
+
## External documentation
|
|
101
|
+
- [${document.info().externalDocs()?.description()}](${document.info().externalDocs()?.url()})
|
|
102
|
+
` : ""}
|
|
103
|
+
`;
|
|
104
|
+
};
|
|
105
|
+
var getSummary2 = (document) => {
|
|
106
|
+
const summary = document.info().hasDescription() ? document.info().description() : "";
|
|
107
|
+
return summary && summary.length < 150 ? summary : "";
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// src/utils/domains.ts
|
|
111
|
+
var defaultMarkdown3 = (document) => {
|
|
112
|
+
return `
|
|
113
|
+
|
|
114
|
+
## Architecture diagram
|
|
115
|
+
<NodeGraph />
|
|
116
|
+
|
|
117
|
+
`;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// src/index.ts
|
|
121
|
+
var import_chalk = __toESM(require("chalk"));
|
|
122
|
+
var parser = new import_parser.Parser();
|
|
123
|
+
var src_default = async (config, options) => {
|
|
124
|
+
if (!process.env.PROJECT_DIR) {
|
|
125
|
+
throw new Error("Please provide catalog url (env variable PROJECT_DIR)");
|
|
126
|
+
}
|
|
127
|
+
const {
|
|
128
|
+
writeService,
|
|
129
|
+
writeEvent,
|
|
130
|
+
writeCommand,
|
|
131
|
+
getService,
|
|
132
|
+
versionService,
|
|
133
|
+
rmService,
|
|
134
|
+
getDomain,
|
|
135
|
+
writeDomain,
|
|
136
|
+
addServiceToDomain,
|
|
137
|
+
getCommand,
|
|
138
|
+
getEvent,
|
|
139
|
+
rmEventById,
|
|
140
|
+
rmCommandById,
|
|
141
|
+
versionCommand,
|
|
142
|
+
versionEvent,
|
|
143
|
+
addSchemaToCommand,
|
|
144
|
+
addSchemaToEvent,
|
|
145
|
+
addFileToService,
|
|
146
|
+
versionDomain
|
|
147
|
+
} = (0, import_sdk.default)(process.env.PROJECT_DIR);
|
|
148
|
+
const asyncAPIFiles = Array.isArray(options.path) ? options.path : [options.path];
|
|
149
|
+
console.log(import_chalk.default.green(`Processing ${asyncAPIFiles.length} AsyncAPI files...`));
|
|
150
|
+
for (const path of asyncAPIFiles) {
|
|
151
|
+
console.log(import_chalk.default.gray(`Processing ${path}`));
|
|
152
|
+
const asyncAPIFile = await (0, import_promises.readFile)(path, "utf-8");
|
|
153
|
+
const { document } = await parser.parse(asyncAPIFile);
|
|
154
|
+
if (!document) {
|
|
155
|
+
console.log(import_chalk.default.red("Failed to parse AsyncAPI file"));
|
|
156
|
+
if (options.debug) {
|
|
157
|
+
const diagnostics = await parser.validate(asyncAPIFile);
|
|
158
|
+
console.log(diagnostics);
|
|
159
|
+
} else {
|
|
160
|
+
console.log(import_chalk.default.red("Run with debug option in the generator to see diagnostics"));
|
|
161
|
+
}
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const operations = document.allOperations();
|
|
165
|
+
const documentTags = document.info().tags().all() || [];
|
|
166
|
+
const serviceId = (0, import_slugify.default)(document.info().title(), { lower: true, strict: true });
|
|
167
|
+
const version = document.info().version();
|
|
168
|
+
const sends = [];
|
|
169
|
+
const receives = [];
|
|
170
|
+
let serviceMarkdown = defaultMarkdown2(document);
|
|
171
|
+
if (options.domain) {
|
|
172
|
+
const { id: domainId, name: domainName, version: domainVersion } = options.domain;
|
|
173
|
+
const domain = await getDomain(options.domain.id, domainVersion || "latest");
|
|
174
|
+
const currentDomain = await getDomain(options.domain.id, "latest");
|
|
175
|
+
console.log(import_chalk.default.blue(`
|
|
176
|
+
Processing domain: ${domainName} (v${domainVersion})`));
|
|
177
|
+
if (currentDomain && currentDomain.version !== domainVersion) {
|
|
178
|
+
await versionDomain(domainId);
|
|
179
|
+
console.log(import_chalk.default.cyan(` - Versioned previous domain (v${currentDomain.version})`));
|
|
180
|
+
}
|
|
181
|
+
if (!domain || domain && domain.version !== domainVersion) {
|
|
182
|
+
await writeDomain({
|
|
183
|
+
id: domainId,
|
|
184
|
+
name: domainName,
|
|
185
|
+
version: domainVersion,
|
|
186
|
+
markdown: defaultMarkdown3(document)
|
|
187
|
+
// services: [{ id: serviceId, version: version }],
|
|
188
|
+
});
|
|
189
|
+
console.log(import_chalk.default.cyan(` - Domain (v${domainVersion}) created`));
|
|
190
|
+
}
|
|
191
|
+
if (currentDomain && currentDomain.version === domainVersion) {
|
|
192
|
+
console.log(import_chalk.default.yellow(` - Domain (v${domainVersion}) already exists, skipped creation...`));
|
|
193
|
+
}
|
|
194
|
+
await addServiceToDomain(domainId, { id: serviceId, version }, domainVersion);
|
|
195
|
+
}
|
|
196
|
+
for (const operation of operations) {
|
|
197
|
+
for (const message of operation.messages()) {
|
|
198
|
+
const eventType = message.extensions().get("x-eventcatalog-message-type")?.value() || "event";
|
|
199
|
+
const messageId = message.id().toLowerCase();
|
|
200
|
+
let messageMarkdown = defaultMarkdown(document, message);
|
|
201
|
+
const writeMessage = eventType === "event" ? writeEvent : writeCommand;
|
|
202
|
+
const versionMessage = eventType === "event" ? versionEvent : versionCommand;
|
|
203
|
+
const getMessage = eventType === "event" ? getEvent : getCommand;
|
|
204
|
+
const rmMessageById = eventType === "event" ? rmEventById : rmCommandById;
|
|
205
|
+
const addSchemaToMessage = eventType === "event" ? addSchemaToEvent : addSchemaToCommand;
|
|
206
|
+
const badges = message.tags().all() || [];
|
|
207
|
+
const catalogedMessage = await getMessage(message.id().toLowerCase(), "latest");
|
|
208
|
+
console.log(import_chalk.default.blue(`Processing message: ${getMessageName(message)} (v${version})`));
|
|
209
|
+
if (catalogedMessage) {
|
|
210
|
+
messageMarkdown = catalogedMessage.markdown;
|
|
211
|
+
if (catalogedMessage.version === version) {
|
|
212
|
+
await rmMessageById(messageId, version);
|
|
213
|
+
} else {
|
|
214
|
+
await versionMessage(messageId);
|
|
215
|
+
console.log(import_chalk.default.cyan(` - Versioned previous message: (v${catalogedMessage.version})`));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
await writeMessage(
|
|
219
|
+
{
|
|
220
|
+
id: messageId,
|
|
221
|
+
version,
|
|
222
|
+
name: getMessageName(message),
|
|
223
|
+
summary: getSummary(message),
|
|
224
|
+
markdown: messageMarkdown,
|
|
225
|
+
badges: badges.map((badge) => ({ content: badge.name(), textColor: "blue", backgroundColor: "blue" })),
|
|
226
|
+
schemaPath: messageHasSchema(message) ? getSchemaFileName(message) : void 0
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
path: message.id()
|
|
230
|
+
}
|
|
231
|
+
);
|
|
232
|
+
console.log(import_chalk.default.cyan(` - Message (v${version}) created`));
|
|
233
|
+
if (messageHasSchema(message)) {
|
|
234
|
+
addSchemaToMessage(
|
|
235
|
+
messageId,
|
|
236
|
+
{
|
|
237
|
+
fileName: getSchemaFileName(message),
|
|
238
|
+
schema: JSON.stringify(message.payload()?.json(), null, 4)
|
|
239
|
+
},
|
|
240
|
+
version
|
|
241
|
+
);
|
|
242
|
+
console.log(import_chalk.default.cyan(` - Schema added to message (v${version})`));
|
|
243
|
+
}
|
|
244
|
+
if (operation.action() === "send" || operation.action() === "publish") {
|
|
245
|
+
sends.push({ id: messageId, version });
|
|
246
|
+
}
|
|
247
|
+
if (operation.action() === "receive" || operation.action() === "subscribe") {
|
|
248
|
+
receives.push({ id: messageId, version });
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
const latestServiceInCatalog = await getService(serviceId, "latest");
|
|
253
|
+
console.log(import_chalk.default.blue(`Processing service: ${document.info().title()} (v${version})`));
|
|
254
|
+
if (latestServiceInCatalog) {
|
|
255
|
+
serviceMarkdown = latestServiceInCatalog.markdown;
|
|
256
|
+
if (latestServiceInCatalog.version !== version) {
|
|
257
|
+
await versionService(serviceId);
|
|
258
|
+
console.log(import_chalk.default.cyan(` - Versioned previous service (v${latestServiceInCatalog.version})`));
|
|
259
|
+
}
|
|
260
|
+
if (latestServiceInCatalog.version === version) {
|
|
261
|
+
serviceMarkdown = latestServiceInCatalog.markdown;
|
|
262
|
+
await rmService(document.info().title());
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
await writeService(
|
|
266
|
+
{
|
|
267
|
+
id: serviceId,
|
|
268
|
+
name: document.info().title(),
|
|
269
|
+
version,
|
|
270
|
+
summary: getSummary2(document),
|
|
271
|
+
badges: documentTags.map((tag) => ({ content: tag.name(), textColor: "blue", backgroundColor: "blue" })),
|
|
272
|
+
markdown: serviceMarkdown,
|
|
273
|
+
sends,
|
|
274
|
+
schemaPath: path.split("/").pop() || "asyncapi.yml",
|
|
275
|
+
receives
|
|
276
|
+
},
|
|
277
|
+
{ path: document.info().title() }
|
|
278
|
+
);
|
|
279
|
+
await addFileToService(
|
|
280
|
+
serviceId,
|
|
281
|
+
{
|
|
282
|
+
fileName: path.split("/").pop() || "asyncapi.yml",
|
|
283
|
+
content: asyncAPIFile
|
|
284
|
+
},
|
|
285
|
+
version
|
|
286
|
+
);
|
|
287
|
+
console.log(import_chalk.default.cyan(` - Service (v${version}) created`));
|
|
288
|
+
console.log(import_chalk.default.green(`
|
|
289
|
+
Finished generating event catalog for AsyncAPI ${document.info().title()} (v${version})`));
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/utils/schemas.ts","../src/utils/messages.ts","../src/utils/services.ts","../src/utils/domains.ts"],"sourcesContent":["// import utils from '@eventcatalog/sdk';\nimport { Parser } from '@asyncapi/parser';\nconst parser = new Parser();\nimport { readFile } from 'node:fs/promises';\nimport utils from '@eventcatalog/sdk';\nimport slugify from 'slugify';\nimport {\n defaultMarkdown as generateMarkdownForMessage,\n getMessageName,\n getSummary as getMessageSummary,\n getSchemaFileName,\n messageHasSchema,\n} from './utils/messages';\nimport { defaultMarkdown as generateMarkdownForService, getSummary as getServiceSummary } from './utils/services';\nimport { defaultMarkdown as generateMarkdownForDomain } from './utils/domains';\nimport chalk from 'chalk';\n\nlet metrics = { eventsCreated: 0, commandsCreated: 0, servicesCreated: 0, domainsCreated: 0 };\n\ntype Domain = {\n id: string;\n name: string;\n version: string;\n};\n\ntype Props = {\n path: string | string[];\n domain?: Domain;\n debug?: boolean;\n};\n\nexport default async (config: any, options: Props) => {\n if (!process.env.PROJECT_DIR) {\n throw new Error('Please provide catalog url (env variable PROJECT_DIR)');\n }\n\n const {\n writeService,\n writeEvent,\n writeCommand,\n getService,\n versionService,\n rmService,\n getDomain,\n writeDomain,\n addServiceToDomain,\n getCommand,\n getEvent,\n rmEventById,\n rmCommandById,\n versionCommand,\n versionEvent,\n addSchemaToCommand,\n addSchemaToEvent,\n addFileToService,\n versionDomain,\n } = utils(process.env.PROJECT_DIR);\n\n const asyncAPIFiles = Array.isArray(options.path) ? options.path : [options.path];\n\n console.log(chalk.green(`Processing ${asyncAPIFiles.length} AsyncAPI files...`));\n\n for (const path of asyncAPIFiles) {\n console.log(chalk.gray(`Processing ${path}`));\n\n const asyncAPIFile = await readFile(path, 'utf-8');\n const { document } = await parser.parse(asyncAPIFile);\n\n if (!document) {\n console.log(chalk.red('Failed to parse AsyncAPI file'));\n if (options.debug) {\n const diagnostics = await parser.validate(asyncAPIFile);\n console.log(diagnostics);\n } else {\n console.log(chalk.red('Run with debug option in the generator to see diagnostics'));\n }\n continue;\n }\n\n const operations = document.allOperations();\n const documentTags = document.info().tags().all() || [];\n\n const serviceId = slugify(document.info().title(), { lower: true, strict: true });\n const version = document.info().version();\n\n // What messages does this service send and receive\n const sends = [];\n const receives = [];\n\n let serviceMarkdown = generateMarkdownForService(document);\n\n // Manage domain\n if (options.domain) {\n // Try and get the domain\n const { id: domainId, name: domainName, version: domainVersion } = options.domain;\n const domain = await getDomain(options.domain.id, domainVersion || 'latest');\n const currentDomain = await getDomain(options.domain.id, 'latest');\n\n console.log(chalk.blue(`\\nProcessing domain: ${domainName} (v${domainVersion})`));\n\n // Found a domain, but the versions do not match\n if (currentDomain && currentDomain.version !== domainVersion) {\n await versionDomain(domainId);\n console.log(chalk.cyan(` - Versioned previous domain (v${currentDomain.version})`));\n }\n\n // Do we need to create a new domain?\n if (!domain || (domain && domain.version !== domainVersion)) {\n await writeDomain({\n id: domainId,\n name: domainName,\n version: domainVersion,\n markdown: generateMarkdownForDomain(document),\n // services: [{ id: serviceId, version: version }],\n });\n console.log(chalk.cyan(` - Domain (v${domainVersion}) created`));\n }\n\n if (currentDomain && currentDomain.version === domainVersion) {\n console.log(chalk.yellow(` - Domain (v${domainVersion}) already exists, skipped creation...`));\n }\n\n // Add the service to the domain\n await addServiceToDomain(domainId, { id: serviceId, version: version }, domainVersion);\n }\n\n // Find events/commands\n for (const operation of operations) {\n for (const message of operation.messages()) {\n const eventType = message.extensions().get('x-eventcatalog-message-type')?.value() || 'event';\n\n const messageId = message.id().toLowerCase();\n\n let messageMarkdown = generateMarkdownForMessage(document, message);\n const writeMessage = eventType === 'event' ? writeEvent : writeCommand;\n const versionMessage = eventType === 'event' ? versionEvent : versionCommand;\n const getMessage = eventType === 'event' ? getEvent : getCommand;\n const rmMessageById = eventType === 'event' ? rmEventById : rmCommandById;\n const addSchemaToMessage = eventType === 'event' ? addSchemaToEvent : addSchemaToCommand;\n const badges = message.tags().all() || [];\n\n // Check if the message already exists in the catalog\n const catalogedMessage = await getMessage(message.id().toLowerCase(), 'latest');\n\n console.log(chalk.blue(`Processing message: ${getMessageName(message)} (v${version})`));\n\n if (catalogedMessage) {\n messageMarkdown = catalogedMessage.markdown;\n // if the version matches, we can override the message but keep markdown as it was\n if (catalogedMessage.version === version) {\n await rmMessageById(messageId, version);\n } else {\n // if the version does not match, we need to version the message\n await versionMessage(messageId);\n console.log(chalk.cyan(` - Versioned previous message: (v${catalogedMessage.version})`));\n }\n }\n\n // Write the message to the catalog\n await writeMessage(\n {\n id: messageId,\n version: version,\n name: getMessageName(message),\n summary: getMessageSummary(message),\n markdown: messageMarkdown,\n badges: badges.map((badge) => ({ content: badge.name(), textColor: 'blue', backgroundColor: 'blue' })),\n schemaPath: messageHasSchema(message) ? getSchemaFileName(message) : undefined,\n },\n {\n path: message.id(),\n }\n );\n\n console.log(chalk.cyan(` - Message (v${version}) created`));\n\n // Check if the message has a payload, if it does then document in EventCatalog\n if (messageHasSchema(message)) {\n addSchemaToMessage(\n messageId,\n {\n fileName: getSchemaFileName(message),\n schema: JSON.stringify(message.payload()?.json(), null, 4),\n },\n version\n );\n console.log(chalk.cyan(` - Schema added to message (v${version})`));\n }\n\n // Add the message to the correct array\n if (operation.action() === 'send' || operation.action() === 'publish') {\n sends.push({ id: messageId, version: version });\n }\n if (operation.action() === 'receive' || operation.action() === 'subscribe') {\n receives.push({ id: messageId, version: version });\n }\n }\n }\n\n // Check if service is already defined... if the versions do not match then create service.\n const latestServiceInCatalog = await getService(serviceId, 'latest');\n\n console.log(chalk.blue(`Processing service: ${document.info().title()} (v${version})`));\n\n if (latestServiceInCatalog) {\n serviceMarkdown = latestServiceInCatalog.markdown;\n // Found a service, and versions do not match, we need to version the one already there\n if (latestServiceInCatalog.version !== version) {\n await versionService(serviceId);\n console.log(chalk.cyan(` - Versioned previous service (v${latestServiceInCatalog.version})`));\n }\n\n // Match found, override it\n if (latestServiceInCatalog.version === version) {\n serviceMarkdown = latestServiceInCatalog.markdown;\n await rmService(document.info().title());\n }\n }\n\n await writeService(\n {\n id: serviceId,\n name: document.info().title(),\n version: version,\n summary: getServiceSummary(document),\n badges: documentTags.map((tag) => ({ content: tag.name(), textColor: 'blue', backgroundColor: 'blue' })),\n markdown: serviceMarkdown,\n sends,\n schemaPath: path.split('/').pop() || 'asyncapi.yml',\n receives,\n },\n { path: document.info().title() }\n );\n\n await addFileToService(\n serviceId,\n {\n fileName: path.split('/').pop() || 'asyncapi.yml',\n content: asyncAPIFile,\n },\n version\n );\n\n console.log(chalk.cyan(` - Service (v${version}) created`));\n\n console.log(chalk.green(`\\nFinished generating event catalog for AsyncAPI ${document.info().title()} (v${version})`));\n }\n};\n","export const getFileExtentionFromSchemaFormat = (format: string | undefined = '') => {\n if (format.includes('avro')) return 'avsc';\n if (format.includes('yml')) return 'yml';\n if (format.includes('json')) return 'json';\n if (format.includes('openapi')) return 'openapi';\n if (format.includes('protobuf')) return 'protobuf';\n if (format.includes('yaml')) return 'yaml';\n\n return 'json';\n};\n","import { MessageInterface, AsyncAPIDocumentInterface } from '@asyncapi/parser';\nimport { getFileExtentionFromSchemaFormat } from './schemas';\n\nexport const defaultMarkdown = (document: AsyncAPIDocumentInterface, message: MessageInterface) => {\n return `\n## Architecture\n<NodeGraph />\n\n${\n messageHasSchema(message)\n ? `\n## Schema\n<SchemaViewer file=\"${getSchemaFileName(message)}\" title=\"Message Schema\" maxHeight=\"500\" />\n`\n : ''\n}\n\n${\n message.externalDocs()\n ? `\n## External documentation\n- [${message.externalDocs()?.description()}](${message.externalDocs()?.url()})\n`\n : ''\n}\n\n`;\n};\n\nexport const getSummary = (message: MessageInterface) => {\n const messageSummary = message.hasSummary() ? message.summary() : '';\n const messageDescription = message.hasDescription() ? message.description() : '';\n\n let eventCatalogMessageSummary = messageSummary;\n\n if (!eventCatalogMessageSummary) {\n eventCatalogMessageSummary = messageDescription && messageDescription.length < 150 ? messageDescription : '';\n }\n\n return eventCatalogMessageSummary;\n};\n\nexport const messageHasSchema = (message: MessageInterface) => {\n return message.hasPayload() && message.schemaFormat();\n};\n\nexport const getSchemaFileName = (message: MessageInterface) => {\n const extension = getFileExtentionFromSchemaFormat(message.schemaFormat());\n return `schema.${extension}`;\n};\n\nexport const getMessageName = (message: MessageInterface) => {\n return message.hasTitle() && message.title() ? (message.title() as string) : message.id();\n};\n","import { AsyncAPIDocumentInterface } from '@asyncapi/parser';\n\nexport const defaultMarkdown = (document: AsyncAPIDocumentInterface) => {\n return `\n\n${document.info().hasDescription() ? `${document.info().description()}` : ''} \n\n## Architecture diagram\n<NodeGraph />\n\n${\n document.info().externalDocs()\n ? `\n## External documentation\n- [${document.info().externalDocs()?.description()}](${document.info().externalDocs()?.url()})\n`\n : ''\n}\n`;\n};\n\nexport const getSummary = (document: AsyncAPIDocumentInterface) => {\n const summary = document.info().hasDescription() ? document.info().description() : '';\n return summary && summary.length < 150 ? summary : '';\n};\n","import { AsyncAPIDocumentInterface } from '@asyncapi/parser';\n\nexport const defaultMarkdown = (document: AsyncAPIDocumentInterface) => {\n return `\n\n## Architecture diagram\n<NodeGraph />\n\n`;\n};\n"],"mappings":"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","names":["defaultMarkdown","getSummary","defaultMarkdown","utils","chalk","slugify","defaultMarkdown","getSummary"]}
|