Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/helpers/src/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { getMessageExamples, getOperationMessages } = require('./operations');
const { getServerUrl, getServer } = require('./servers');
const { getClientName, listFiles, getInfo, toSnakeCase } = require('./utils');
const { getClientName, listFiles, getInfo, toSnakeCase, getTitle} = require('./utils');
const { getQueryParams } = require('./bindings');

module.exports = {
Expand All @@ -11,6 +11,7 @@ module.exports = {
getQueryParams,
getOperationMessages,
getMessageExamples,
getTitle,
getInfo,
toSnakeCase
};
70 changes: 46 additions & 24 deletions packages/helpers/src/utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,48 @@
const { readdir } = require('fs/promises');

/**
* Validate and retrieve the AsyncAPI info object from an AsyncAPI document.
*
* Throws an error if the provided AsyncAPI document has no `info` section.
*
* @param {object} asyncapi - The AsyncAPI document object.
* @returns {object} The validated info object from the AsyncAPI document.
*/
const getInfo = (asyncapi) => {
if (!asyncapi) {
throw new Error('Make sure you pass AsyncAPI document as an argument.');
}
if (!asyncapi.info) {
throw new Error('Provided AsyncAPI document doesn\'t contain Info object.');
}
const info = asyncapi.info();
if (!info) {
throw new Error('AsyncAPI document info object cannot be empty.');
}
return info;
};

/**
* Validate and retrieve the AsyncAPI title parameter in the info object.
*
* Throws an error if the provided AsyncAPI info object lacks a `title` parameter.
*
* @param {object} asyncapi - The AsyncAPI document object.
* @throws {Error} When `title` is `null` or `undefined` or `empty string` .
* @returns {string} The retrieved `title` parameter.
*/
const getTitle = asyncapi => {
const info = getInfo(asyncapi);
if (!info.title) {
throw new Error('Provided AsyncAPI document info field doesn\'t contain title.');
}
const title = info.title();
if (title === '') {
throw new Error('AsyncAPI document title cannot be an empty string.');
}

return title;
};
/**
* Get client name from AsyncAPI info.title or uses a custom name if provided.
*
Expand All @@ -9,11 +52,11 @@ const { readdir } = require('fs/promises');
*
* @returns {string} The formatted client name, either the custom name or a generated name based on the title
*/
const getClientName = (info, appendClientSuffix, customClientName) => {
const getClientName = (asyncapi, appendClientSuffix, customClientName) => {
if (customClientName) {
return customClientName;
}
const title = info.title();
const title = getTitle(asyncapi);
const baseName = `${title.replace(/\s+/g, '') // Remove all spaces
.replace(/^./, char => char.toUpperCase())}`; // Make the first letter uppercase
return appendClientSuffix ? `${baseName}Client` : baseName;
Expand All @@ -35,28 +78,6 @@ const listFiles = async (dir) => {
.map(dirE => dirE.name);
};

/**
* Validate and retrieve the AsyncAPI info object from an AsyncAPI document.
*
* Throws an error if the provided AsyncAPI document has no `info` section.
*
* @param {object} asyncapi - The AsyncAPI document object.
* @returns {object} The validated info object from the AsyncAPI document.
*/
const getInfo = (asyncapi) => {
if (!asyncapi) {
throw new Error('Make sure you pass AsyncAPI document as an argument.');
}
if (!asyncapi.info) {
throw new Error('Provided AsyncAPI document doesn\'t contain Info object.');
}
const info = asyncapi.info();
if (!info) {
throw new Error('AsyncAPI document info object cannot be empty.');
}
return info;
};

/**
* Convert a camelCase or PascalCase string to snake_case.
* If the string is already in snake_case, it will be returned unchanged.
Expand All @@ -75,6 +96,7 @@ const toSnakeCase = (inputStr) => {
module.exports = {
getClientName,
listFiles,
getTitle,
getInfo,
toSnakeCase
};
50 changes: 43 additions & 7 deletions packages/helpers/test/utils.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const path = require('path');
const { Parser, fromFile } = require('@asyncapi/parser');
const { getClientName, getInfo, toSnakeCase } = require('@asyncapi/generator-helpers');
const { getClientName, getInfo, getTitle, toSnakeCase } = require('@asyncapi/generator-helpers');

const parser = new Parser();
const asyncapi_v3_path = path.resolve(__dirname, './__fixtures__/asyncapi-websocket-query.yml');
Expand All @@ -14,33 +14,30 @@ describe('getClientName integration test with AsyncAPI', () => {
});

it('should generate correct client name for the provided AsyncAPI info object without appendClientSuffix', () => {
const info = parsedAsyncAPIDocument.info();
const appendClientSuffix = false;
const customClientName = '';

const clientName = getClientName(info, appendClientSuffix, customClientName);
const clientName = getClientName(parsedAsyncAPIDocument, appendClientSuffix, customClientName);

// Example assertion: Check if the name is formatted correctly
expect(clientName).toBe('GeminiMarketDataWebsocketAPI');
});

it('should generate correct client name for the provided AsyncAPI info object with appendClientSuffix', () => {
const info = parsedAsyncAPIDocument.info();
const appendClientSuffix = true;
const customClientName = '';

const clientName = getClientName(info, appendClientSuffix, customClientName);
const clientName = getClientName(parsedAsyncAPIDocument, appendClientSuffix, customClientName);

// Example assertion: Check if the name is formatted correctly
expect(clientName).toBe('GeminiMarketDataWebsocketAPIClient');
});

it('should return customClientName', () => {
const info = parsedAsyncAPIDocument.info();
const appendClientSuffix = false;
const customClientName = 'GeminiClient';

const clientName = getClientName(info, appendClientSuffix, customClientName);
const clientName = getClientName(parsedAsyncAPIDocument, appendClientSuffix, customClientName);

// Example assertion: Check if the name is formatted correctly
expect(clientName).toBe(customClientName);
Expand Down Expand Up @@ -82,6 +79,45 @@ describe('getInfo integration test with AsyncAPI', () => {
});
});

describe('getTitle integration test with AsyncAPI', () => {
let parsedAsyncAPIDocument;

beforeAll(async () => {
const parseResult = await fromFile(parser, asyncapi_v3_path).parse();
parsedAsyncAPIDocument = parseResult.document;
});

it('should return the exact title parameter when exists', () => {
const info = parsedAsyncAPIDocument.info();
const expectedTitle = info.title();
const actualTitle = getTitle(parsedAsyncAPIDocument);
expect(actualTitle).toStrictEqual(expectedTitle);
});

it('should throw error when title function does not exist', () => {
const asyncAPIDocWithoutTitle = {
info: () => ({
// info object without title method
})
};
expect(() => {
getTitle(asyncAPIDocWithoutTitle);
}).toThrow('Provided AsyncAPI document info field doesn\'t contain title.');
});

it('should throw error when title is an empty string', () => {
const asyncAPIDocWithEmptyTitle = {
info: () => ({
title: () => ''
})
};

expect(() => {
getTitle(asyncAPIDocWithEmptyTitle);
}).toThrow('AsyncAPI document title cannot be an empty string.');
});
});

describe('toSnakeCase integration test with AsyncAPI', () => {
let parsedAsyncAPIDocument, operations;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { File } from '@asyncapi/generator-react-sdk';
import { getClientName, getServerUrl, getServer, getInfo } from '@asyncapi/generator-helpers';
import { getClientName, getServerUrl, getServer, getInfo, getTitle } from '@asyncapi/generator-helpers';
import { FileHeaderInfo } from '../components/FileHeaderInfo';
import { Requires } from '../components/Requires';
import { ClientClass } from '../components/ClientClass';

export default function ({ asyncapi, params }) {
const server = getServer(asyncapi.servers(), params.server);
const info = getInfo(asyncapi);
const title = info.title();
const clientName = getClientName(info, params.appendClientSuffix, params.customClientName);
const title = getTitle(asyncapi);
const clientName = getClientName(asyncapi, params.appendClientSuffix, params.customClientName);
const serverUrl = getServerUrl(server);
return (
// The clientFileName default values can be found and modified under the package.json
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { AvailableOperations } from '../components/AvailableOperations';
export default function({ asyncapi, params }) {
const server = getServer(asyncapi.servers(), params.server);
const info = asyncapi.info();
const clientName = getClientName(info);
const clientName = getClientName(asyncapi, params.appendClientSuffix, params.customClientName);

const operations = asyncapi.operations().all();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { File } from '@asyncapi/generator-react-sdk';
import { getClientName, getServerUrl, getServer, getInfo } from '@asyncapi/generator-helpers';
import { getClientName, getServerUrl, getServer, getInfo, getTitle } from '@asyncapi/generator-helpers';
import { FileHeaderInfo } from '../components/FileHeaderInfo';
import { Requires } from '../components/Requires';
import { ClientClass } from '../components/ClientClass';

export default function ({ asyncapi, params }) {
const server = getServer(asyncapi.servers(), params.server);
const info = getInfo(asyncapi);
const title = info.title();
const clientName = getClientName(info, params.appendClientSuffix, params.customClientName);
const title = getTitle(asyncapi);
const clientName = getClientName(asyncapi, params.appendClientSuffix, params.customClientName);
const serverUrl = getServerUrl(server);
const sendOperations = asyncapi.operations().filterBySend();
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { File } from '@asyncapi/generator-react-sdk';
import { getClientName, getServerUrl, getServer, getQueryParams, getInfo } from '@asyncapi/generator-helpers';
import { getClientName, getServerUrl, getServer, getQueryParams, getInfo, getTitle } from '@asyncapi/generator-helpers';
import { FileHeaderInfo } from '../components/FileHeaderInfo';
import { Requires } from '../components/Requires';
import { ClientClass } from '../components/ClientClass';

export default function ({ asyncapi, params }) {
const server = getServer(asyncapi.servers(), params.server);
const info = getInfo(asyncapi);
const title = info.title();
const title = getTitle(asyncapi);
const queryParams = getQueryParams(asyncapi.channels());
const clientName = getClientName(info, params.appendClientSuffix, params.customClientName);
const clientName = getClientName(asyncapi, params.appendClientSuffix, params.customClientName);
const serverUrl = getServerUrl(server);
const operations = asyncapi.operations();
return (
Expand Down