@eventcatalog/generator-amazon-apigateway 1.0.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/README.md ADDED
@@ -0,0 +1,135 @@
1
+ <div align="center">
2
+
3
+ <h1>⚡️ Amazon API Gateway 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://dcbadge.limes.pink/api/server/https://discord.gg/3rjaZMmrAm?style=flat)](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/) [![blog](https://img.shields.io/badge/blog-EDA--Visuals-brightgreen)](https://eda-visuals.boyney.io/?utm_source=event-catalog-gihub) [![blog](https://img.shields.io/badge/license-Dual--License-brightgreen)](https://github.com/event-catalog/generator-asyncapi/blob/main/LICENSE.md)
8
+
9
+ <img alt="header" src="https://github.com/event-catalog/generators/blob/main/images/amazon-apigateway.png?raw=true" />
10
+
11
+ <h4>Features: Generate EventCatalogs with your Amazon API Gateway OpenAPI files, Map routes to commands, queries and events, Auto versioning of your domains, services and messages, Add Semantic meanings to your APIS</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 APIs
22
+ - 📊 Visualise your architecture ([demo](https://demo.eventcatalog.dev/visualiser))
23
+ - View your OpenAPI files in EventCatalog and download schemas
24
+ - 💅 Custom MDX components ([read more](https://eventcatalog.dev/docs/development/components/using-components))
25
+ - 🗄️ Auto versioning of your domains, services and messages
26
+ - ⭐ Map routes to commands, queries and events in EventCatalog
27
+ - ⭐ Discoverability feature (search, filter and more) ([demo](https://demo.eventcatalog.dev/discover/events))
28
+ - ⭐ And much more...
29
+
30
+ # How it works
31
+
32
+ [EventCatalog](https://www.eventcatalog.dev/) is technology agnostic, meaning it can integrate with any schemas, specs or brokers.
33
+
34
+ The generator requires the [OpenAPI Generator](https://github.com/event-catalog/generators/tree/main/packages/generator-openapi).
35
+
36
+ 1. Install the Amazon API Gateway Generator
37
+ 2. Configure your generator in your `eventcatalog.config.js` file.
38
+ 3. This will turn your API Gateway OpenAPI speciifcation files into EventCatalog ready files.
39
+ 4. Install the OpenAPI Generator
40
+ 5. Configure the OpenAPI generator to read and process files from your output of Amazon API Gateway Generator.
41
+ 6. View your APIs, messages, services and domains in EventCatalog.
42
+
43
+ ### Example
44
+
45
+ This example:
46
+
47
+ 1. Downloads the `Store API` from Amazon API Gateway
48
+ 1. Hydrates the OpenAPI file with EventCatalog extensions
49
+ 1. Outputs the generated OpenAPI files to `amazon-apigateway-specs`
50
+
51
+ 1. Runs the OpenAPI generator
52
+ 1. Processes the generated OpenAPI files into EventCatalog
53
+
54
+ ```js
55
+ ...
56
+ generators: [
57
+ [
58
+ '@eventcatalogtest/generator-amazon-apigateway',
59
+ {
60
+ output: 'amazon-apigateway-specs',
61
+ apis: [
62
+ {
63
+ name: 'Store API',
64
+ region: 'us-east-1',
65
+ stageName: 'prod',
66
+ routes: {
67
+ 'post /users': {
68
+ type: 'command',
69
+ }
70
+ }
71
+ }
72
+ ]
73
+ },
74
+ ],
75
+ [
76
+ '@eventcatalogtest/generator-openapi',
77
+ {
78
+ services: [
79
+ { path: [path.join(__dirname, 'amazon-apigateway-specs', 'Store API.json'), id: 'store' },
80
+ ],
81
+ domain: { id: 'Shopping Cart', name: 'Shopping Cart', version: '0.0.1' },
82
+ },
83
+ ],
84
+ ],
85
+ ...
86
+ ```
87
+
88
+ # Getting started
89
+
90
+ ## Installation and configuration
91
+
92
+ _Make sure you are on the latest version of EventCatalog_.
93
+
94
+ 1. Install the packages
95
+
96
+ ```sh
97
+ @eventcatalog/generator-amazon-apigateway
98
+ @eventcatalog/generator-openapi
99
+ ```
100
+
101
+ 2. Configure your `eventcatalog.config.js` file
102
+
103
+ - First configure the API Gateway Geneartor
104
+ - Then configure the OpenAPI generator
105
+
106
+ 3. Run the generate command
107
+
108
+ ```sh
109
+ npm run generate
110
+ ```
111
+
112
+ 4. See your new domains, services and messages, run
113
+
114
+ ```sh
115
+ npm run dev
116
+ ```
117
+
118
+ ## Found a problem?
119
+
120
+ Raise a GitHub issue on this project, or contact us on [our Discord server](https://discord.gg/3rjaZMmrAm).
121
+
122
+ [license-badge]: https://img.shields.io/github/license/event-catalog/eventcatalog.svg?color=yellow
123
+ [license]: https://github.com/event-catalog/eventcatalog/blob/main/LICENSE
124
+ [prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
125
+ [prs]: http://makeapullrequest.com
126
+ [github-watch-badge]: https://img.shields.io/github/watchers/event-catalog/eventcatalog.svg?style=social
127
+ [github-watch]: https://github.com/event-catalog/eventcatalog/watchers
128
+ [github-star-badge]: https://img.shields.io/github/stars/event-catalog/eventcatalog.svg?style=social
129
+ [github-star]: https://github.com/event-catalog/eventcatalog/stargazers
130
+
131
+ # Commercial Use
132
+
133
+ This project is governed by a [dual-license](./LICENSE.md). To ensure the sustainability of the project, you can freely make use of this software if your projects are Open Source. Otherwise for proprietary systems you must obtain a [commercial license](./LICENSE-COMMERCIAL.md).
134
+
135
+ You can purchase a license or get a free trial at https://eventcatalog.cloud or email us at `hello@eventcatalog.dev`.
@@ -0,0 +1,25 @@
1
+ import { AwsCredentialIdentity, AwsCredentialIdentityProvider } from '@smithy/types';
2
+
3
+ type Route = {
4
+ type: 'command' | 'query' | 'event';
5
+ id?: string;
6
+ name?: string;
7
+ description?: string;
8
+ };
9
+ type API = {
10
+ name: string;
11
+ region: string;
12
+ stageName: string;
13
+ version?: number;
14
+ routes: Record<string, Route>;
15
+ };
16
+ type Props = {
17
+ debug?: boolean;
18
+ licenseKey?: string;
19
+ apis: API[];
20
+ output?: string;
21
+ credentials?: AwsCredentialIdentity | AwsCredentialIdentityProvider;
22
+ };
23
+ declare const _default: (_: any, options: Props) => Promise<void>;
24
+
25
+ export { type API, type Route, _default as default };
@@ -0,0 +1,25 @@
1
+ import { AwsCredentialIdentity, AwsCredentialIdentityProvider } from '@smithy/types';
2
+
3
+ type Route = {
4
+ type: 'command' | 'query' | 'event';
5
+ id?: string;
6
+ name?: string;
7
+ description?: string;
8
+ };
9
+ type API = {
10
+ name: string;
11
+ region: string;
12
+ stageName: string;
13
+ version?: number;
14
+ routes: Record<string, Route>;
15
+ };
16
+ type Props = {
17
+ debug?: boolean;
18
+ licenseKey?: string;
19
+ apis: API[];
20
+ output?: string;
21
+ credentials?: AwsCredentialIdentity | AwsCredentialIdentityProvider;
22
+ };
23
+ declare const _default: (_: any, options: Props) => Promise<void>;
24
+
25
+ export { type API, type Route, _default as default };
package/dist/index.js ADDED
@@ -0,0 +1,156 @@
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 index_exports = {};
32
+ __export(index_exports, {
33
+ default: () => index_default
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+ var import_client_api_gateway2 = require("@aws-sdk/client-api-gateway");
37
+
38
+ // src/utils/apigateway.ts
39
+ var import_client_api_gateway = require("@aws-sdk/client-api-gateway");
40
+ async function getOpenApiSpec(client, restApiId, stageName) {
41
+ try {
42
+ const command = new import_client_api_gateway.GetExportCommand({
43
+ restApiId,
44
+ stageName,
45
+ exportType: "oas30",
46
+ // Use 'swagger' for Swagger/OpenAPI 2.0
47
+ accepts: "application/json"
48
+ });
49
+ const response = await client.send(command);
50
+ let openAPISpec;
51
+ try {
52
+ openAPISpec = new TextDecoder().decode(response.body);
53
+ return JSON.parse(openAPISpec);
54
+ } catch (error) {
55
+ return response.body;
56
+ }
57
+ } catch (error) {
58
+ console.error("Error fetching OpenAPI specification:", error);
59
+ throw error;
60
+ }
61
+ }
62
+ async function getRestApiIdByName(client, apiName) {
63
+ try {
64
+ let position;
65
+ do {
66
+ const command = new import_client_api_gateway.GetRestApisCommand({
67
+ position
68
+ // Include the position token for pagination
69
+ });
70
+ const response = await client.send(command);
71
+ const api = response.items?.find((api2) => api2.name === apiName);
72
+ if (api) {
73
+ return api.id;
74
+ }
75
+ position = response.position;
76
+ } while (position);
77
+ throw new Error(`API with name '${apiName}' not found`);
78
+ } catch (error) {
79
+ console.error("Error fetching REST API ID:", error);
80
+ throw error;
81
+ }
82
+ }
83
+
84
+ // src/utils/hydrate-openapi-file.ts
85
+ async function hydrate(openApiSpec, routeConfig, version) {
86
+ const modifiedSpec = JSON.parse(JSON.stringify(openApiSpec));
87
+ const defaultMessageType = "query";
88
+ const specVersion = version || routeConfig.version || 1;
89
+ modifiedSpec.info.version = `${specVersion}`;
90
+ for (const [path, pathItem] of Object.entries(modifiedSpec.paths)) {
91
+ for (const [method, operation] of Object.entries(pathItem)) {
92
+ if (operation && typeof operation === "object" && !Array.isArray(operation)) {
93
+ const operationObj = operation;
94
+ const configKey = `${method.toLowerCase()} ${path}`;
95
+ const config = routeConfig[configKey] || {};
96
+ const messageType = typeof config === "string" ? config : config.type || defaultMessageType;
97
+ operationObj["x-eventcatalog-message-type"] = messageType;
98
+ if (typeof config === "object" && config.id) {
99
+ operationObj.operationId = config.id;
100
+ } else if (!operationObj.operationId) {
101
+ const normalizedPath = path.replace(/^\//, "").replace(/\//g, "_").replace(/[{}]/g, "");
102
+ operationObj.operationId = `${method.toLowerCase()}_${normalizedPath}`;
103
+ }
104
+ if (typeof config === "object" && config.description) {
105
+ operationObj.description = config.description;
106
+ }
107
+ if (typeof config === "object") {
108
+ if (config.id) {
109
+ operationObj["x-eventcatalog-message-id"] = config.id;
110
+ }
111
+ if (config.name) {
112
+ operationObj["x-eventcatalog-message-name"] = config.name;
113
+ }
114
+ }
115
+ }
116
+ }
117
+ }
118
+ return modifiedSpec;
119
+ }
120
+
121
+ // src/index.ts
122
+ var import_promises = require("fs/promises");
123
+ var import_node_path = require("path");
124
+ var import_chalk = __toESM(require("chalk"));
125
+ var import_promises2 = __toESM(require("fs/promises"));
126
+ var index_default = async (_, options) => {
127
+ if (!process.env.PROJECT_DIR) {
128
+ process.env.PROJECT_DIR = process.cwd();
129
+ }
130
+ if (!process.env.PROJECT_DIR) {
131
+ throw new Error("Please provide catalog url (env variable PROJECT_DIR)");
132
+ }
133
+ const outputDir = options.output ? (0, import_node_path.join)(process.env.PROJECT_DIR, options.output) : (0, import_node_path.join)(process.env.PROJECT_DIR, "amazon-apigateway-specs");
134
+ console.log(import_chalk.default.green(`Processing ${options.apis.length} apis with API Gateway`));
135
+ for (const api of options.apis) {
136
+ console.log(import_chalk.default.gray(`Processing ${api.name} in ${api.region} with Amazon API Gateway...`));
137
+ const client = new import_client_api_gateway2.APIGatewayClient({ region: api.region, credentials: options.credentials });
138
+ const apiName = await getRestApiIdByName(client, api.name);
139
+ if (!apiName) {
140
+ console.log(import_chalk.default.yellow(` - API with name '${api.name}' not found, skipping import...`));
141
+ continue;
142
+ }
143
+ const openApiSpec = await getOpenApiSpec(client, apiName, api.stageName);
144
+ console.log(import_chalk.default.cyan(` - Found OpenAPI file, hydrating with EventCatalog extensions...`));
145
+ const hydratedSpec = await hydrate(openApiSpec, api.routes, api.version);
146
+ const output = (0, import_node_path.join)(process.env.PROJECT_DIR, "amazon-apigateway-specs", `${api.name}.json`);
147
+ await import_promises2.default.mkdir(outputDir, { recursive: true });
148
+ console.log(import_chalk.default.cyan(` - Writing OpenAPI file to ${output}...`));
149
+ await (0, import_promises.writeFile)(output, JSON.stringify(hydratedSpec, null, 2));
150
+ }
151
+ console.log(import_chalk.default.green(`
152
+ Finished generating event catalog with Amazon API Gateway Apis.`));
153
+ console.log(import_chalk.default.green(`
154
+ Specifications have been written to ${outputDir}`));
155
+ };
156
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/utils/apigateway.ts","../src/utils/hydrate-openapi-file.ts"],"sourcesContent":["import { APIGatewayClient } from '@aws-sdk/client-api-gateway';\nimport { AwsCredentialIdentity, AwsCredentialIdentityProvider } from '@smithy/types';\nimport { getOpenApiSpec, getRestApiIdByName } from './utils/apigateway';\nimport { hydrate } from './utils/hydrate-openapi-file';\nimport { writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport chalk from 'chalk';\nimport fs from 'fs/promises';\n\nexport type Route = {\n type: 'command' | 'query' | 'event';\n id?: string;\n name?: string;\n description?: string;\n};\n\nexport type API = {\n name: string;\n region: string;\n stageName: string;\n version?: number;\n routes: Record<string, Route>;\n};\n\ntype Props = {\n debug?: boolean;\n licenseKey?: string;\n apis: API[];\n output?: string;\n credentials?: AwsCredentialIdentity | AwsCredentialIdentityProvider;\n};\n\nexport default async (_: any, options: Props) => {\n if (!process.env.PROJECT_DIR) {\n process.env.PROJECT_DIR = process.cwd();\n }\n\n if (!process.env.PROJECT_DIR) {\n throw new Error('Please provide catalog url (env variable PROJECT_DIR)');\n }\n\n const outputDir = options.output\n ? join(process.env.PROJECT_DIR, options.output)\n : join(process.env.PROJECT_DIR, 'amazon-apigateway-specs');\n\n console.log(chalk.green(`Processing ${options.apis.length} apis with API Gateway`));\n\n // Loop through all the APIS and hydrate the openapi spec\n for (const api of options.apis) {\n console.log(chalk.gray(`Processing ${api.name} in ${api.region} with Amazon API Gateway...`));\n\n const client = new APIGatewayClient({ region: api.region, credentials: options.credentials });\n\n const apiName = await getRestApiIdByName(client, api.name);\n\n if (!apiName) {\n console.log(chalk.yellow(` - API with name '${api.name}' not found, skipping import...`));\n continue;\n }\n\n const openApiSpec = await getOpenApiSpec(client, apiName, api.stageName);\n\n console.log(chalk.cyan(` - Found OpenAPI file, hydrating with EventCatalog extensions...`));\n const hydratedSpec = await hydrate(openApiSpec, api.routes, api.version);\n\n const output = join(process.env.PROJECT_DIR, 'amazon-apigateway-specs', `${api.name}.json`);\n\n // ensure the directory exists\n await fs.mkdir(outputDir, { recursive: true });\n\n console.log(chalk.cyan(` - Writing OpenAPI file to ${output}...`));\n await writeFile(output, JSON.stringify(hydratedSpec, null, 2));\n }\n\n console.log(chalk.green(`\\nFinished generating event catalog with Amazon API Gateway Apis.`));\n console.log(chalk.green(`\\nSpecifications have been written to ${outputDir}`));\n};\n","import { APIGatewayClient, GetExportCommand, GetRestApisCommand } from '@aws-sdk/client-api-gateway';\n\nexport async function getOpenApiSpec(client: APIGatewayClient, restApiId: string, stageName: string) {\n try {\n const command = new GetExportCommand({\n restApiId: restApiId,\n stageName: stageName,\n exportType: 'oas30', // Use 'swagger' for Swagger/OpenAPI 2.0\n accepts: 'application/json',\n });\n\n const response = await client.send(command);\n\n let openAPISpec;\n\n try {\n openAPISpec = new TextDecoder().decode(response.body);\n return JSON.parse(openAPISpec);\n } catch (error) {\n return response.body;\n }\n } catch (error) {\n console.error('Error fetching OpenAPI specification:', error);\n throw error;\n }\n}\n\nexport async function getRestApiIdByName(client: APIGatewayClient, apiName: string) {\n try {\n let position: string | undefined;\n do {\n const command = new GetRestApisCommand({\n position: position, // Include the position token for pagination\n });\n const response = await client.send(command);\n\n const api = response.items?.find((api) => api.name === apiName);\n if (api) {\n return api.id; // Found the API, return its ID\n }\n\n position = response.position; // Get the next position token\n } while (position); // Continue while there are more APIs to fetch\n\n throw new Error(`API with name '${apiName}' not found`);\n } catch (error) {\n console.error('Error fetching REST API ID:', error);\n throw error;\n }\n}\n","export async function hydrate(openApiSpec: any, routeConfig: any, version?: number) {\n // Clone the spec to avoid modifying the original\n const modifiedSpec = JSON.parse(JSON.stringify(openApiSpec));\n\n // Default configuration - all routes are queries unless specified\n const defaultMessageType = 'query';\n\n // Set version from config or default to 1\n const specVersion = version || routeConfig.version || 1;\n modifiedSpec.info.version = `${specVersion}`;\n\n // Iterate through all paths and their methods\n for (const [path, pathItem] of Object.entries(modifiedSpec.paths)) {\n for (const [method, operation] of Object.entries(pathItem as Record<string, unknown>)) {\n if (operation && typeof operation === 'object' && !Array.isArray(operation)) {\n const operationObj = operation as {\n operationId?: string;\n description?: string;\n [key: string]: any;\n };\n\n const configKey = `${method.toLowerCase()} ${path}`;\n const config = routeConfig[configKey] || {};\n\n // Add message type extension\n const messageType = typeof config === 'string' ? config : config.type || defaultMessageType;\n operationObj['x-eventcatalog-message-type'] = messageType;\n\n // Set operationId\n if (typeof config === 'object' && config.id) {\n operationObj.operationId = config.id;\n } else if (!operationObj.operationId) {\n const normalizedPath = path.replace(/^\\//, '').replace(/\\//g, '_').replace(/[{}]/g, '');\n\n operationObj.operationId = `${method.toLowerCase()}_${normalizedPath}`;\n }\n\n // Add description if provided in config\n if (typeof config === 'object' && config.description) {\n operationObj.description = config.description;\n }\n\n // Add optional message ID and name if provided\n if (typeof config === 'object') {\n if (config.id) {\n operationObj['x-eventcatalog-message-id'] = config.id;\n }\n if (config.name) {\n operationObj['x-eventcatalog-message-name'] = config.name;\n }\n }\n }\n }\n }\n\n return modifiedSpec;\n}\n"],"mappings":"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","names":["import_client_api_gateway","api","import_promises","chalk","fs"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,125 @@
1
+ // src/index.ts
2
+ import { APIGatewayClient as APIGatewayClient2 } from "@aws-sdk/client-api-gateway";
3
+
4
+ // src/utils/apigateway.ts
5
+ import { GetExportCommand, GetRestApisCommand } from "@aws-sdk/client-api-gateway";
6
+ async function getOpenApiSpec(client, restApiId, stageName) {
7
+ try {
8
+ const command = new GetExportCommand({
9
+ restApiId,
10
+ stageName,
11
+ exportType: "oas30",
12
+ // Use 'swagger' for Swagger/OpenAPI 2.0
13
+ accepts: "application/json"
14
+ });
15
+ const response = await client.send(command);
16
+ let openAPISpec;
17
+ try {
18
+ openAPISpec = new TextDecoder().decode(response.body);
19
+ return JSON.parse(openAPISpec);
20
+ } catch (error) {
21
+ return response.body;
22
+ }
23
+ } catch (error) {
24
+ console.error("Error fetching OpenAPI specification:", error);
25
+ throw error;
26
+ }
27
+ }
28
+ async function getRestApiIdByName(client, apiName) {
29
+ try {
30
+ let position;
31
+ do {
32
+ const command = new GetRestApisCommand({
33
+ position
34
+ // Include the position token for pagination
35
+ });
36
+ const response = await client.send(command);
37
+ const api = response.items?.find((api2) => api2.name === apiName);
38
+ if (api) {
39
+ return api.id;
40
+ }
41
+ position = response.position;
42
+ } while (position);
43
+ throw new Error(`API with name '${apiName}' not found`);
44
+ } catch (error) {
45
+ console.error("Error fetching REST API ID:", error);
46
+ throw error;
47
+ }
48
+ }
49
+
50
+ // src/utils/hydrate-openapi-file.ts
51
+ async function hydrate(openApiSpec, routeConfig, version) {
52
+ const modifiedSpec = JSON.parse(JSON.stringify(openApiSpec));
53
+ const defaultMessageType = "query";
54
+ const specVersion = version || routeConfig.version || 1;
55
+ modifiedSpec.info.version = `${specVersion}`;
56
+ for (const [path, pathItem] of Object.entries(modifiedSpec.paths)) {
57
+ for (const [method, operation] of Object.entries(pathItem)) {
58
+ if (operation && typeof operation === "object" && !Array.isArray(operation)) {
59
+ const operationObj = operation;
60
+ const configKey = `${method.toLowerCase()} ${path}`;
61
+ const config = routeConfig[configKey] || {};
62
+ const messageType = typeof config === "string" ? config : config.type || defaultMessageType;
63
+ operationObj["x-eventcatalog-message-type"] = messageType;
64
+ if (typeof config === "object" && config.id) {
65
+ operationObj.operationId = config.id;
66
+ } else if (!operationObj.operationId) {
67
+ const normalizedPath = path.replace(/^\//, "").replace(/\//g, "_").replace(/[{}]/g, "");
68
+ operationObj.operationId = `${method.toLowerCase()}_${normalizedPath}`;
69
+ }
70
+ if (typeof config === "object" && config.description) {
71
+ operationObj.description = config.description;
72
+ }
73
+ if (typeof config === "object") {
74
+ if (config.id) {
75
+ operationObj["x-eventcatalog-message-id"] = config.id;
76
+ }
77
+ if (config.name) {
78
+ operationObj["x-eventcatalog-message-name"] = config.name;
79
+ }
80
+ }
81
+ }
82
+ }
83
+ }
84
+ return modifiedSpec;
85
+ }
86
+
87
+ // src/index.ts
88
+ import { writeFile } from "node:fs/promises";
89
+ import { join } from "node:path";
90
+ import chalk from "chalk";
91
+ import fs from "fs/promises";
92
+ var index_default = async (_, options) => {
93
+ if (!process.env.PROJECT_DIR) {
94
+ process.env.PROJECT_DIR = process.cwd();
95
+ }
96
+ if (!process.env.PROJECT_DIR) {
97
+ throw new Error("Please provide catalog url (env variable PROJECT_DIR)");
98
+ }
99
+ const outputDir = options.output ? join(process.env.PROJECT_DIR, options.output) : join(process.env.PROJECT_DIR, "amazon-apigateway-specs");
100
+ console.log(chalk.green(`Processing ${options.apis.length} apis with API Gateway`));
101
+ for (const api of options.apis) {
102
+ console.log(chalk.gray(`Processing ${api.name} in ${api.region} with Amazon API Gateway...`));
103
+ const client = new APIGatewayClient2({ region: api.region, credentials: options.credentials });
104
+ const apiName = await getRestApiIdByName(client, api.name);
105
+ if (!apiName) {
106
+ console.log(chalk.yellow(` - API with name '${api.name}' not found, skipping import...`));
107
+ continue;
108
+ }
109
+ const openApiSpec = await getOpenApiSpec(client, apiName, api.stageName);
110
+ console.log(chalk.cyan(` - Found OpenAPI file, hydrating with EventCatalog extensions...`));
111
+ const hydratedSpec = await hydrate(openApiSpec, api.routes, api.version);
112
+ const output = join(process.env.PROJECT_DIR, "amazon-apigateway-specs", `${api.name}.json`);
113
+ await fs.mkdir(outputDir, { recursive: true });
114
+ console.log(chalk.cyan(` - Writing OpenAPI file to ${output}...`));
115
+ await writeFile(output, JSON.stringify(hydratedSpec, null, 2));
116
+ }
117
+ console.log(chalk.green(`
118
+ Finished generating event catalog with Amazon API Gateway Apis.`));
119
+ console.log(chalk.green(`
120
+ Specifications have been written to ${outputDir}`));
121
+ };
122
+ export {
123
+ index_default as default
124
+ };
125
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/utils/apigateway.ts","../src/utils/hydrate-openapi-file.ts"],"sourcesContent":["import { APIGatewayClient } from '@aws-sdk/client-api-gateway';\nimport { AwsCredentialIdentity, AwsCredentialIdentityProvider } from '@smithy/types';\nimport { getOpenApiSpec, getRestApiIdByName } from './utils/apigateway';\nimport { hydrate } from './utils/hydrate-openapi-file';\nimport { writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport chalk from 'chalk';\nimport fs from 'fs/promises';\n\nexport type Route = {\n type: 'command' | 'query' | 'event';\n id?: string;\n name?: string;\n description?: string;\n};\n\nexport type API = {\n name: string;\n region: string;\n stageName: string;\n version?: number;\n routes: Record<string, Route>;\n};\n\ntype Props = {\n debug?: boolean;\n licenseKey?: string;\n apis: API[];\n output?: string;\n credentials?: AwsCredentialIdentity | AwsCredentialIdentityProvider;\n};\n\nexport default async (_: any, options: Props) => {\n if (!process.env.PROJECT_DIR) {\n process.env.PROJECT_DIR = process.cwd();\n }\n\n if (!process.env.PROJECT_DIR) {\n throw new Error('Please provide catalog url (env variable PROJECT_DIR)');\n }\n\n const outputDir = options.output\n ? join(process.env.PROJECT_DIR, options.output)\n : join(process.env.PROJECT_DIR, 'amazon-apigateway-specs');\n\n console.log(chalk.green(`Processing ${options.apis.length} apis with API Gateway`));\n\n // Loop through all the APIS and hydrate the openapi spec\n for (const api of options.apis) {\n console.log(chalk.gray(`Processing ${api.name} in ${api.region} with Amazon API Gateway...`));\n\n const client = new APIGatewayClient({ region: api.region, credentials: options.credentials });\n\n const apiName = await getRestApiIdByName(client, api.name);\n\n if (!apiName) {\n console.log(chalk.yellow(` - API with name '${api.name}' not found, skipping import...`));\n continue;\n }\n\n const openApiSpec = await getOpenApiSpec(client, apiName, api.stageName);\n\n console.log(chalk.cyan(` - Found OpenAPI file, hydrating with EventCatalog extensions...`));\n const hydratedSpec = await hydrate(openApiSpec, api.routes, api.version);\n\n const output = join(process.env.PROJECT_DIR, 'amazon-apigateway-specs', `${api.name}.json`);\n\n // ensure the directory exists\n await fs.mkdir(outputDir, { recursive: true });\n\n console.log(chalk.cyan(` - Writing OpenAPI file to ${output}...`));\n await writeFile(output, JSON.stringify(hydratedSpec, null, 2));\n }\n\n console.log(chalk.green(`\\nFinished generating event catalog with Amazon API Gateway Apis.`));\n console.log(chalk.green(`\\nSpecifications have been written to ${outputDir}`));\n};\n","import { APIGatewayClient, GetExportCommand, GetRestApisCommand } from '@aws-sdk/client-api-gateway';\n\nexport async function getOpenApiSpec(client: APIGatewayClient, restApiId: string, stageName: string) {\n try {\n const command = new GetExportCommand({\n restApiId: restApiId,\n stageName: stageName,\n exportType: 'oas30', // Use 'swagger' for Swagger/OpenAPI 2.0\n accepts: 'application/json',\n });\n\n const response = await client.send(command);\n\n let openAPISpec;\n\n try {\n openAPISpec = new TextDecoder().decode(response.body);\n return JSON.parse(openAPISpec);\n } catch (error) {\n return response.body;\n }\n } catch (error) {\n console.error('Error fetching OpenAPI specification:', error);\n throw error;\n }\n}\n\nexport async function getRestApiIdByName(client: APIGatewayClient, apiName: string) {\n try {\n let position: string | undefined;\n do {\n const command = new GetRestApisCommand({\n position: position, // Include the position token for pagination\n });\n const response = await client.send(command);\n\n const api = response.items?.find((api) => api.name === apiName);\n if (api) {\n return api.id; // Found the API, return its ID\n }\n\n position = response.position; // Get the next position token\n } while (position); // Continue while there are more APIs to fetch\n\n throw new Error(`API with name '${apiName}' not found`);\n } catch (error) {\n console.error('Error fetching REST API ID:', error);\n throw error;\n }\n}\n","export async function hydrate(openApiSpec: any, routeConfig: any, version?: number) {\n // Clone the spec to avoid modifying the original\n const modifiedSpec = JSON.parse(JSON.stringify(openApiSpec));\n\n // Default configuration - all routes are queries unless specified\n const defaultMessageType = 'query';\n\n // Set version from config or default to 1\n const specVersion = version || routeConfig.version || 1;\n modifiedSpec.info.version = `${specVersion}`;\n\n // Iterate through all paths and their methods\n for (const [path, pathItem] of Object.entries(modifiedSpec.paths)) {\n for (const [method, operation] of Object.entries(pathItem as Record<string, unknown>)) {\n if (operation && typeof operation === 'object' && !Array.isArray(operation)) {\n const operationObj = operation as {\n operationId?: string;\n description?: string;\n [key: string]: any;\n };\n\n const configKey = `${method.toLowerCase()} ${path}`;\n const config = routeConfig[configKey] || {};\n\n // Add message type extension\n const messageType = typeof config === 'string' ? config : config.type || defaultMessageType;\n operationObj['x-eventcatalog-message-type'] = messageType;\n\n // Set operationId\n if (typeof config === 'object' && config.id) {\n operationObj.operationId = config.id;\n } else if (!operationObj.operationId) {\n const normalizedPath = path.replace(/^\\//, '').replace(/\\//g, '_').replace(/[{}]/g, '');\n\n operationObj.operationId = `${method.toLowerCase()}_${normalizedPath}`;\n }\n\n // Add description if provided in config\n if (typeof config === 'object' && config.description) {\n operationObj.description = config.description;\n }\n\n // Add optional message ID and name if provided\n if (typeof config === 'object') {\n if (config.id) {\n operationObj['x-eventcatalog-message-id'] = config.id;\n }\n if (config.name) {\n operationObj['x-eventcatalog-message-name'] = config.name;\n }\n }\n }\n }\n }\n\n return modifiedSpec;\n}\n"],"mappings":"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","names":["APIGatewayClient","api","APIGatewayClient"]}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@eventcatalog/generator-amazon-apigateway",
3
+ "version": "1.0.0",
4
+ "description": "Generator for Amazon API Gateway",
5
+ "scripts": {
6
+ "build": "tsup",
7
+ "test": "vitest",
8
+ "format": "prettier --write .",
9
+ "format:diff": "prettier --list-different .",
10
+ "changeset": "changeset",
11
+ "release": "changeset publish"
12
+ },
13
+ "publishConfig": {
14
+ "access": "public"
15
+ },
16
+ "keywords": [],
17
+ "author": "",
18
+ "license": "ISC",
19
+ "devDependencies": {
20
+ "@smithy/types": "^3.5.0",
21
+ "@types/node": "^20.16.1",
22
+ "prettier": "^3.3.3",
23
+ "tsup": "^8.1.0",
24
+ "typescript": "^5.5.3",
25
+ "vitest": "^2.0.2"
26
+ },
27
+ "files": [
28
+ "dist",
29
+ "package.json"
30
+ ],
31
+ "main": "./dist/index.js",
32
+ "module": "./dist/index.mjs",
33
+ "types": "./dist/index.d.ts",
34
+ "dependencies": {
35
+ "@aws-sdk/client-api-gateway": "^3.743.0",
36
+ "@aws-sdk/credential-provider-node": "^3.743.0",
37
+ "@changesets/cli": "^2.27.7",
38
+ "chalk": "^4"
39
+ }
40
+ }