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
53 changes: 12 additions & 41 deletions packages/components/src/components/CloseConnection.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,10 @@
import { Text } from '@asyncapi/generator-react-sdk';
import { MethodGenerator } from './MethodGenerator';

/**
* @typedef {'python' | 'javascript' | 'dart'} Language
* Supported programming languages.
*/

/**
* Configuration for method syntax based on programming language.
* @type {Record<Language, { returnType?: string, openingTag?: string, closingTag?: string, indentSize?: number }>}
*/
const methodConfig = {
python: { returnType: 'def', openingTag: ':', indentSize: 2 },
javascript: { openingTag: '{', closingTag: '}', indentSize: 2 },
dart: { returnType: 'void', openingTag: '{', closingTag: '}', indentSize: 2 }
};

/**
* Configuration for WebSocket close method logic per language.
* @type {Record<Language, { methodDocs?: string, methodLogic: string }>}
Expand Down Expand Up @@ -53,40 +43,21 @@ print('WebSocket connection closed.');`
* @returns {JSX.Element} Rendered method block with appropriate formatting.
*/
export function CloseConnection({ language, methodName = 'close', methodParams = [], preExecutionCode = '', postExecutionCode = '' }) {
const {
returnType = '',
openingTag = '',
closingTag = '' ,
indentSize = 2
} = methodConfig[language];
const {
methodDocs = '',
methodLogic = ''
} = websocketCloseConfig[language];
const params = methodParams.join(', ');

let completeCode = methodLogic;

if (preExecutionCode) {
completeCode = `${preExecutionCode}\n${completeCode}`;
}
if (postExecutionCode) {
completeCode = `${completeCode}\n${postExecutionCode}`;
}

const innerIndent = (' ').repeat(indentSize);
const indentedLogic = completeCode.split('\n')
.map(line => line ? `${innerIndent}${line}` : '')
.join('\n');

const methodCode = `${methodDocs}
${returnType} ${methodName}(${params}) ${openingTag}
${indentedLogic}
${closingTag}`;


return (
<Text indent={2}>
{methodCode}
</Text>
<MethodGenerator
language={language}
methodName={methodName}
methodParams = {methodParams}
methodDocs = {methodDocs}
methodLogic = {methodLogic}
preExecutionCode = {preExecutionCode}
postExecutionCode = {postExecutionCode}
indent = {2}
/>
);
}
79 changes: 79 additions & 0 deletions packages/components/src/components/MethodGenerator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { Text } from '@asyncapi/generator-react-sdk';

/**
* @typedef {'python' | 'javascript' | 'dart'} Language
* Supported programming languages.
*/

/**
* Configuration for method syntax based on programming language.
* @type {Record<Language, { returnType?: string, openingTag?: string, closingTag?: string, indentSize?: number }>}
*/
const defaultMethodConfig = {
python: { returnType: 'def', openingTag: ':', indentSize: 2 },
javascript: { openingTag: '{', closingTag: '}', indentSize: 2 },
dart: { returnType: 'void', openingTag: '{', closingTag: '}', indentSize: 2 }
};

/**
* Generic Method rendering component.
*
* @param {Object} props - Component props.
* @param {Language} props.language - Programming language used for method formatting.
* @param {string} props.methodName - Name of the method.
* @param {string[]} [props.methodParams=[]] - Method parameters.
* @param {string} [props.methodDocs=''] - Optional documentation string.
* @param {string} [props.methodLogic=''] - Core method logic.
* @param {string} [props.preExecutionCode=''] - Code before main logic.
* @param {string} [props.postExecutionCode=''] - Code after main logic.
* @param {number} [props.indent=2] - Indentation for the method block.
* @param {number} [props.newLines=1] - Number of new lines after method.
* @param {{ returnType?: string, openingTag?: string, closingTag?: string, indentSize?: number }} [props.customMethodConfig] - Optional custom syntax configuration for the current language.
*/
export function MethodGenerator({
language,
methodName,
methodParams = [],
methodDocs = '',
methodLogic = '',
preExecutionCode = '',
postExecutionCode = '',
indent = 2,
newLines = 1,
customMethodConfig
}) {
const {
returnType = '',
openingTag = '',
closingTag = '',
indentSize = 2
} = customMethodConfig || defaultMethodConfig[language];

const params = methodParams.join(', ');

let completeCode = methodLogic;

if (preExecutionCode) {
completeCode = `${preExecutionCode}\n${completeCode}`;
}
if (postExecutionCode) {
completeCode = `${completeCode}\n${postExecutionCode}`;
}

const innerIndent = ' '.repeat(indentSize);
const indentedLogic = completeCode
.split('\n')
.map(line => (line ? `${innerIndent}${line}` : ''))
.join('\n');

const methodCode = `${methodDocs}
${returnType} ${methodName}(${params}) ${openingTag}
${indentedLogic}
${closingTag}`;

return (
<Text indent={indent} newLines={newLines}>
{methodCode}
</Text>
);
}
63 changes: 63 additions & 0 deletions packages/components/src/components/RegisterMessageHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { MethodGenerator } from './MethodGenerator';

/**
* @typedef {'python' | 'javascript' | 'dart'} Language
* Supported programming languages.
*/

/**
* Configuration for WebSocket message handler registration method logic per language.
* @type {Record<Language, { methodDocs?: string, methodLogic: string }>}
*/
const websocketMessageRegisterConfig = {
python: {
methodLogic: `if callable(handler):
self.message_handlers.append(handler)
else:
print("Message handler must be callable")`
},
javascript: {
methodDocs: '// Method to register custom message handlers',
methodLogic: `if (typeof handler === 'function') {
this.messageHandlers.push(handler);
} else {
console.warn('Message handler must be a function');
}`
},
dart: {
methodDocs: '/// Method to register custom message handlers',
methodLogic: '_messageHandlers.add(handler);'
}
};

/**
* Renders a WebSocket message handler registration method with optional pre and post execution logic.
*
* @param {Object} props - Component props.
* @param {Language} props.language - Programming language used for method formatting.
* @param {string} props.methodName='registerMessageHandler' - Name of the method to generate.
* @param {string[]} props.methodParams=[] - List of parameters for the method.
* @param {string} props.preExecutionCode - Code to insert before the main function logic.
* @param {string} props.postExecutionCode - Code to insert after the main function logic.
* @returns {JSX.Element} Rendered method block with appropriate formatting.
*/
export function RegisterMessageHandler({ language, methodName = 'registerMessageHandler', methodParams = [], preExecutionCode = '', postExecutionCode = '' }) {
const {
methodDocs = '',
methodLogic = ''
} = websocketMessageRegisterConfig[language];

return (
<MethodGenerator
language={language}
methodName={methodName}
methodParams={methodParams}
methodDocs={methodDocs}
methodLogic={methodLogic}
preExecutionCode={preExecutionCode}
postExecutionCode={postExecutionCode}
indent={2}
newLines={2}
/>
);
}
4 changes: 3 additions & 1 deletion packages/components/src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export { Models } from './components/Models';
export { FileHeaderInfo } from './components/FileHeaderInfo';
export { CloseConnection } from './components/CloseConnection';
export { DependencyProvider } from './components/DependencyProvider';
export { DependencyProvider } from './components/DependencyProvider';
export { RegisterMessageHandler } from './components/RegisterMessageHandler';
export { MethodGenerator } from './components/MethodGenerator';
111 changes: 111 additions & 0 deletions packages/components/test/components/MethodGenerator.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { render } from '@asyncapi/generator-react-sdk';
import { MethodGenerator } from '../../src/index';

describe('MethodGenerator', () => {
test('renders default python method', () => {
const result = render(
<MethodGenerator
language="python"
methodName="connect"
methodParams={['self', 'url']}
methodLogic="print('Connecting...')"
/>
);
expect(result.trim()).toMatchSnapshot();
});

test('renders default javascript method', () => {
const result = render(
<MethodGenerator
language="javascript"
methodName="connect"
methodParams={['url']}
methodLogic="console.log('Connecting...');"
/>
);
expect(result.trim()).toMatchSnapshot();
});

test('renders default dart method', () => {
const result = render(
<MethodGenerator
language="dart"
methodName="connect"
methodParams={['String url']}
methodLogic="print('Connecting...');"
/>
);
expect(result.trim()).toMatchSnapshot();
});

test('renders with customMethodConfig override', () => {
const result = render(
<MethodGenerator
language="javascript"
customMethodConfig={{ returnType: 'async function', openingTag: '{', closingTag: '}', indentSize: 4 }}
methodName="fetchData"
methodLogic="await getData();"
/>
);
expect(result.trim()).toMatchSnapshot();
});

test('renders with methodDocs', () => {
const result = render(
<MethodGenerator
language="python"
methodName="processData"
methodDocs='"""Process the input data."""'
methodLogic="pass"
/>
);
expect(result.trim()).toMatchSnapshot();
});

test('renders with preExecutionCode and postExecutionCode', () => {
const result = render(
<MethodGenerator
language="python"
methodName="registerHandler"
methodParams={['self', 'handler']}
preExecutionCode="# Before handler registration"
methodLogic="self.handlers.append(handler)"
postExecutionCode="# After handler registration"
/>
);
expect(result.trim()).toMatchSnapshot();
});

test('renders with custom indentation', () => {
const result = render(
<MethodGenerator
language="javascript"
methodName="customIndent"
methodLogic="console.log('Indented');"
customMethodConfig={{ openingTag: '{', closingTag: '}', indentSize: 6 }}
/>
);
expect(result.trim()).toMatchSnapshot();
});

test('renders method with no logic', () => {
const result = render(
<MethodGenerator
language="dart"
methodName="emptyMethod"
/>
);
expect(result.trim()).toMatchSnapshot();
});

test('renders method with multiline logic', () => {
const result = render(
<MethodGenerator
language="javascript"
methodName="multiLineLogic"
methodLogic={'console.log(\'Line 1\');\nconsole.log(\'Line 2\');'}
/>
);
expect(result.trim()).toMatchSnapshot();
});
});
Loading
Loading