Skip to content
This repository was archived by the owner on Feb 5, 2025. It is now read-only.

Commit 1aee346

Browse files
committed
feat([openapi]): feat([openapi]): if service version is lower than latest add a service version in versioned folder
1 parent df9490b commit 1aee346

File tree

4 files changed

+104
-32
lines changed

4 files changed

+104
-32
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"@types/fs-extra": "^11.0.4",
2121
"@types/lodash": "^4.17.7",
2222
"@types/node": "^20.16.1",
23+
"@types/semver": "^7.5.8",
2324
"prettier": "^3.3.3",
2425
"tsup": "^8.1.0",
2526
"typescript": "^5.5.3",
@@ -38,6 +39,7 @@
3839
"@eventcatalog/sdk": "^0.1.4",
3940
"chalk": "^4",
4041
"openapi-types": "^12.1.3",
42+
"semver": "^7.6.3",
4143
"slugify": "^1.6.6"
4244
}
4345
}

pnpm-lock.yaml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/index.ts

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { Domain, Service } from './types';
1111
import { getMessageTypeUtils } from './utils/catalog-shorthand';
1212
import { OpenAPI } from 'openapi-types';
1313
import checkLicense from './utils/checkLicense';
14+
import * as semver from 'semver';
1415

1516
type Props = {
1617
services: Service[];
@@ -53,9 +54,11 @@ export default async (_: any, options: Props) => {
5354
const version = document.info.version;
5455

5556
const service = buildService(serviceSpec, document);
56-
let serviceMarkdown = service.markdown;
57-
let serviceSpecificationsFiles = [];
58-
let serviceSpecifications = service.specifications;
57+
let serviceCatalogPath = service.id;
58+
let markdown = service.markdown;
59+
let specFiles = [];
60+
let specifications = service.specifications;
61+
let { sends, receives } = await processMessagesForOpenAPISpec(serviceSpec.path, document);
5962

6063
// Manage domain
6164
if (options.domain) {
@@ -91,64 +94,66 @@ export default async (_: any, options: Props) => {
9194
await addServiceToDomain(domainId, { id: service.id, version: service.version }, domainVersion);
9295
}
9396

94-
// Process all messages for the OpenAPI spec
95-
let { sends, receives } = await processMessagesForOpenAPISpec(serviceSpec.path, document);
96-
9797
// Check if service is already defined... if the versions do not match then create service.
9898
const latestServiceInCatalog = await getService(service.id, 'latest');
99+
const existingVersionInCatalog = await getService(service.id, version);
100+
99101
console.log(chalk.blue(`Processing service: ${document.info.title} (v${version})`));
100102

103+
// Found a service, and versions do not match, we need to version the one already there
101104
if (latestServiceInCatalog) {
102-
serviceMarkdown = latestServiceInCatalog.markdown;
103-
serviceSpecificationsFiles = await getSpecificationFilesForService(service.id, 'latest');
104-
sends = latestServiceInCatalog.sends || ([] as any);
105-
106-
// persist any specifications that are already in the catalog
107-
serviceSpecifications = {
108-
...serviceSpecifications,
109-
...latestServiceInCatalog.specifications,
110-
};
111-
112-
// Found a service, and versions do not match, we need to version the one already there
113-
if (latestServiceInCatalog.version !== version) {
105+
if (isHigherVersion(version, latestServiceInCatalog.version)) {
114106
await versionService(service.id);
115107
console.log(chalk.cyan(` - Versioned previous service (v${latestServiceInCatalog.version})`));
108+
} else {
109+
serviceCatalogPath = serviceCatalogPath.concat(`/versioned/${version}`);
110+
console.log(chalk.yellow(` - Service (v${latestServiceInCatalog.version}) already exists, skipped creation...`));
116111
}
112+
}
113+
114+
if (existingVersionInCatalog) {
115+
markdown = existingVersionInCatalog.markdown;
116+
specFiles = await getSpecificationFilesForService(service.id, version);
117+
sends = existingVersionInCatalog.sends || ([] as any);
118+
receives = [...(existingVersionInCatalog.receives ?? []), ...receives];
119+
120+
// persist any specifications that are already in the catalog
121+
specifications = {
122+
...specifications,
123+
...existingVersionInCatalog.specifications,
124+
};
117125

118126
// Match found, override it
119-
if (latestServiceInCatalog.version === version) {
120-
receives = latestServiceInCatalog.receives ? [...latestServiceInCatalog.receives, ...receives] : receives;
121-
await rmServiceById(service.id);
122-
}
127+
await rmServiceById(service.id, version);
123128
}
124129

125130
await writeService(
126131
{
127132
...service,
128-
markdown: serviceMarkdown,
129-
specifications: serviceSpecifications,
133+
markdown: markdown,
134+
specifications: specifications,
130135
sends,
131136
receives,
132137
},
133-
{ path: service.id }
138+
{ path: serviceCatalogPath }
134139
);
135140

136141
// What files need added to the service (speficiation files)
137-
const specFiles = [
142+
const existingSpecFiles = [
138143
// add any previous spec files to the list
139-
...serviceSpecificationsFiles,
144+
...specFiles,
140145
{
141146
content: openAPIFile,
142147
fileName: service.schemaPath,
143148
},
144149
];
145150

146-
for (const specFile of specFiles) {
151+
for (const spec of existingSpecFiles) {
147152
await addFileToService(
148153
service.id,
149154
{
150-
fileName: specFile.fileName,
151-
content: specFile.content,
155+
fileName: spec.fileName,
156+
content: spec.content,
152157
},
153158
version
154159
);
@@ -235,3 +240,6 @@ const processMessagesForOpenAPISpec = async (pathToSpec: string, document: OpenA
235240
}
236241
return { receives, sends: [] };
237242
};
243+
function isHigherVersion(sourceVersion: string, targetVersion: string) {
244+
return semver.gt(sourceVersion, targetVersion);
245+
}

src/test/plugin.test.ts

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,13 +286,69 @@ describe('OpenAPI EventCatalog Plugin', () => {
286286
expect(service.specifications?.openapiPath).toEqual('petstore.yml');
287287
});
288288

289+
it('if the service already has higher version the new one with lowert version will be created as versioned', async () => {
290+
const { getService, writeService } = utils(catalogDir);
291+
292+
await writeService(
293+
{
294+
id: 'swagger-petstore',
295+
version: '2.0.0',
296+
name: 'swagger-petstore',
297+
markdown: 'My content',
298+
},
299+
{ path: 'swagger-petstore' }
300+
);
301+
302+
await plugin(config, { services: [{ path: join(openAPIExamples, 'petstore.yml'), id: 'swagger-petstore' }] });
303+
304+
const service = await getService('swagger-petstore', '1.0.0');
305+
const latestservice = await getService('swagger-petstore', '2.0.0');
306+
expect(service).toBeDefined();
307+
expect(latestservice).toBeDefined();
308+
});
309+
310+
it('if the service already has higher version the new one with lowert version will be created as versioned', async () => {
311+
const { getService, writeService } = utils(catalogDir);
312+
313+
await writeService(
314+
{
315+
id: 'swagger-petstore',
316+
version: '2.0.0',
317+
name: 'swagger-petstore',
318+
markdown: 'My content',
319+
},
320+
{ path: 'swagger-petstore' }
321+
);
322+
323+
await writeService(
324+
{
325+
id: 'swagger-petstore',
326+
version: '1.0.0',
327+
name: 'swagger-petstore',
328+
markdown: 'My content',
329+
},
330+
{ path: 'swagger-petstore/versioned/1.0.0' }
331+
);
332+
333+
await plugin(config, { services: [{ path: join(openAPIExamples, 'petstore.yml'), id: 'swagger-petstore' }] });
334+
335+
const service = await getService('swagger-petstore', '1.0.0');
336+
const latestservice = await getService('swagger-petstore', '2.0.0');
337+
338+
expect(latestservice).toBeDefined();
339+
expect(service).toBeDefined();
340+
341+
expect(service.receives?.length).toBe(4);
342+
expect(service.markdown).toBe('My content');
343+
});
344+
289345
it('if the service already has specifications they are persisted and the openapi one is added on', async () => {
290346
const { getService, writeService, addFileToService } = utils(catalogDir);
291347

292348
await writeService(
293349
{
294350
id: 'swagger-petstore',
295-
version: '0.0.1',
351+
version: '1.0.0',
296352
name: 'Swagger Petstore',
297353
specifications: {
298354
asyncapiPath: 'asyncapi.yml',
@@ -308,7 +364,7 @@ describe('OpenAPI EventCatalog Plugin', () => {
308364
fileName: 'asyncapi.yml',
309365
content: 'Some content',
310366
},
311-
'0.0.1'
367+
'1.0.0'
312368
);
313369

314370
await plugin(config, { services: [{ path: join(openAPIExamples, 'petstore.yml'), id: 'swagger-petstore' }] });

0 commit comments

Comments
 (0)