Skip to content

Commit 1e7004b

Browse files
Adi-204derberg
andauthored
refactor: move RegisterErrorHandler component to @asyncapi/generator-components (#1675)
Co-authored-by: Adi-204 <adiboghawala@gmail.com> Co-authored-by: Lukasz Gornicki <lpgornicki@gmail.com>
1 parent 78d9412 commit 1e7004b

File tree

16 files changed

+329
-159
lines changed

16 files changed

+329
-159
lines changed

packages/components/src/components/CloseConnection.js

Lines changed: 4 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -57,39 +57,6 @@ print('WebSocket connection closed.');`
5757
}
5858
};
5959

60-
/**
61-
* Helper function to resolve config
62-
* @param {language} language
63-
* @param {framework} framework
64-
* @returns
65-
*/
66-
function resolveCloseConfig(language, framework = '') {
67-
const config = websocketCloseConfig[language];
68-
69-
if (!config) {
70-
return { methodDocs: '', methodLogic: '' };
71-
}
72-
73-
// Handle flat structure (python, javascript, dart)
74-
if (config.methodLogic || config.methodDocs) {
75-
return {
76-
methodDocs: config.methodDocs || '',
77-
methodLogic: config.methodLogic || ''
78-
};
79-
}
80-
81-
// Handle nested structure (java with framework)
82-
if (framework && config[framework]) {
83-
const frameworkConfig = config[framework];
84-
return {
85-
methodDocs: frameworkConfig.methodDocs || '',
86-
methodLogic: frameworkConfig.methodLogic || ''
87-
};
88-
}
89-
90-
return { methodDocs: '', methodLogic: '' };
91-
}
92-
9360
/**
9461
* Renders a WebSocket close connection method with optional pre and post execution logic.
9562
*
@@ -103,19 +70,13 @@ function resolveCloseConfig(language, framework = '') {
10370
* @param {number} props.indent=2 - Indentation level for the method block.
10471
* @returns {JSX.Element} Rendered method block with appropriate formatting.
10572
*/
106-
export function CloseConnection({ language, framework = '', methodName = 'close', methodParams = [], preExecutionCode = '', postExecutionCode = '', indent = 2 }) {
107-
const { methodDocs, methodLogic } = resolveCloseConfig(language, framework);
108-
73+
export function CloseConnection({ methodName = 'close', indent = 2, ...props }) {
10974
return (
11075
<MethodGenerator
111-
language={language}
76+
{...props}
77+
methodConfig={websocketCloseConfig}
11278
methodName={methodName}
113-
methodParams = {methodParams}
114-
methodDocs = {methodDocs}
115-
methodLogic = {methodLogic}
116-
preExecutionCode = {preExecutionCode}
117-
postExecutionCode = {postExecutionCode}
118-
indent = {indent}
79+
indent={indent}
11980
/>
12081
);
12182
}

packages/components/src/components/MethodGenerator.js

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,44 @@ const defaultMethodConfig = {
1616
java: { returnType: '', openingTag: '', closingTag: '', indentSize: 0, parameterWrap: false }
1717
};
1818

19+
/**
20+
* Resolve docs and logic for the given language + framework config.
21+
*/
22+
const resolveDocsAndLogic = ({ language, methodDocs, methodLogic, methodConfig, framework }) => {
23+
let docs = methodDocs;
24+
let logic = methodLogic;
25+
26+
if (methodConfig && methodConfig[language]) {
27+
const config = methodConfig[language];
28+
29+
if (framework && config[framework]) {
30+
const frameworkConfig = config[framework];
31+
docs = frameworkConfig.methodDocs ?? methodDocs ?? '';
32+
logic = frameworkConfig.methodLogic ?? methodLogic ?? '';
33+
} else if (config.methodLogic || config.methodDocs) {
34+
docs = config.methodDocs ?? methodDocs ?? '';
35+
logic = config.methodLogic ?? methodLogic ?? '';
36+
}
37+
}
38+
39+
return { docs, logic };
40+
};
41+
42+
/**
43+
* Build indented method body.
44+
*/
45+
const buildIndentedLogic = (logic, preExecutionCode, postExecutionCode, indentSize) => {
46+
let completeCode = logic;
47+
if (preExecutionCode) completeCode = `${preExecutionCode}\n${completeCode}`;
48+
if (postExecutionCode) completeCode = `${completeCode}\n${postExecutionCode}`;
49+
50+
const innerIndent = ' '.repeat(indentSize);
51+
return completeCode
52+
.split('\n')
53+
.map(line => (line ? `${innerIndent}${line}` : ''))
54+
.join('\n');
55+
};
56+
1957
/**
2058
* Generic Method rendering component.
2159
*
@@ -29,7 +67,9 @@ const defaultMethodConfig = {
2967
* @param {string} [props.postExecutionCode=''] - Code after main logic.
3068
* @param {number} [props.indent=2] - Indentation for the method block.
3169
* @param {number} [props.newLines=1] - Number of new lines after method.
32-
* @param {{ returnType?: string, openingTag?: string, closingTag?: string, indentSize?: number }} [props.customMethodConfig] - Optional custom syntax configuration for the current language.
70+
* @param {{ returnType?: string, openingTag?: string, closingTag?: string, indentSize?: number, parameterWrap?: boolean }} [props.customMethodConfig] - Optional custom syntax configuration for the current language.
71+
* @param {Record<Language, ({ methodDocs?: string, methodLogic?: string } | Record<string, { methodDocs?: string, methodLogic?: string }>)} [props.methodConfig] - Language-level or framework-level configuration.
72+
* @param {string} [props.framework] - Framework name for nested configurations (e.g., 'quarkus' for Java).
3373
*/
3474
export function MethodGenerator({
3575
language,
@@ -41,8 +81,18 @@ export function MethodGenerator({
4181
postExecutionCode = '',
4282
indent = 2,
4383
newLines = 1,
44-
customMethodConfig
84+
customMethodConfig,
85+
methodConfig,
86+
framework
4587
}) {
88+
const { docs: resolvedMethodDocs, logic: resolvedMethodLogic } = resolveDocsAndLogic({
89+
language,
90+
methodDocs,
91+
methodLogic,
92+
methodConfig,
93+
framework
94+
});
95+
4696
const {
4797
returnType = '',
4898
openingTag = '',
@@ -54,22 +104,14 @@ export function MethodGenerator({
54104
const params = methodParams.join(', ');
55105
const parameterBlock = parameterWrap ? `(${params})` : `${params}`;
56106

57-
let completeCode = methodLogic;
58-
59-
if (preExecutionCode) {
60-
completeCode = `${preExecutionCode}\n${completeCode}`;
61-
}
62-
if (postExecutionCode) {
63-
completeCode = `${completeCode}\n${postExecutionCode}`;
64-
}
65-
66-
const innerIndent = ' '.repeat(indentSize);
67-
const indentedLogic = completeCode
68-
.split('\n')
69-
.map(line => (line ? `${innerIndent}${line}` : ''))
70-
.join('\n');
107+
const indentedLogic = buildIndentedLogic(
108+
resolvedMethodLogic,
109+
preExecutionCode,
110+
postExecutionCode,
111+
indentSize
112+
);
71113

72-
const methodCode = `${methodDocs}
114+
const methodCode = `${resolvedMethodDocs}
73115
${returnType} ${methodName}${parameterBlock} ${openingTag}
74116
${indentedLogic}
75117
${closingTag}`;
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { MethodGenerator } from './MethodGenerator';
2+
3+
/**
4+
* @typedef {'python' | 'javascript' | 'dart'} Language
5+
* Supported programming languages.
6+
*/
7+
8+
/**
9+
* Configuration for WebSocket error handler registration method logic per language.
10+
* @type {Record<Language, { methodDocs?: string, methodLogic: string }>}
11+
*/
12+
const websocketErrorRegisterConfig = {
13+
python: {
14+
methodLogic: `if callable(handler):
15+
self.error_handlers.append(handler)
16+
else:
17+
print("Error handler must be callable")`
18+
},
19+
javascript: {
20+
methodDocs: '// Method to register custom error handlers',
21+
methodLogic: `if (typeof handler === 'function') {
22+
this.errorHandlers.push(handler);
23+
} else {
24+
console.warn('Error handler must be a function');
25+
}`
26+
},
27+
dart: {
28+
methodDocs: '/// Method to register custom error handlers',
29+
methodLogic: '_errorHandlers.add(handler);'
30+
}
31+
};
32+
33+
/**
34+
* Renders a WebSocket error handler registration method with optional pre and post execution logic.
35+
*
36+
* @param {Object} props - Component props.
37+
* @param {Language} props.language - Programming language used for method formatting.
38+
* @param {string} props.methodName='registerErrorHandler' - Name of the method to generate.
39+
* @param {string[]} props.methodParams=[] - List of parameters for the method.
40+
* @param {string} props.preExecutionCode - Code to insert before the main function logic.
41+
* @param {string} props.postExecutionCode - Code to insert after the main function logic.
42+
* @param {Object} [props.customMethodConfig] - Optional overrides for default method configuration.
43+
* @returns {JSX.Element} Rendered method block with appropriate formatting.
44+
*/
45+
export function RegisterErrorHandler({ methodName = 'registerErrorHandler', ...props }) {
46+
return (
47+
<MethodGenerator
48+
{...props}
49+
methodConfig={websocketErrorRegisterConfig}
50+
methodName={methodName}
51+
indent={2}
52+
newLines={2}
53+
/>
54+
);
55+
}

packages/components/src/components/RegisterMessageHandler.js

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,12 @@ else:
4141
* @param {string} props.postExecutionCode - Code to insert after the main function logic.
4242
* @returns {JSX.Element} Rendered method block with appropriate formatting.
4343
*/
44-
export function RegisterMessageHandler({ language, methodName = 'registerMessageHandler', methodParams = [], preExecutionCode = '', postExecutionCode = '' }) {
45-
const {
46-
methodDocs = '',
47-
methodLogic = ''
48-
} = websocketMessageRegisterConfig[language];
49-
44+
export function RegisterMessageHandler({ methodName = 'registerMessageHandler', ...props }) {
5045
return (
5146
<MethodGenerator
52-
language={language}
47+
{...props}
48+
methodConfig={websocketMessageRegisterConfig}
5349
methodName={methodName}
54-
methodParams={methodParams}
55-
methodDocs={methodDocs}
56-
methodLogic={methodLogic}
57-
preExecutionCode={preExecutionCode}
58-
postExecutionCode={postExecutionCode}
5950
indent={2}
6051
newLines={2}
6152
/>

packages/components/src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ export { CloseConnection } from './components/CloseConnection';
44
export { DependencyProvider } from './components/DependencyProvider';
55
export { RegisterMessageHandler } from './components/RegisterMessageHandler';
66
export { MethodGenerator } from './components/MethodGenerator';
7+
export { RegisterErrorHandler } from './components/RegisterErrorHandler';
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import { render } from '@asyncapi/generator-react-sdk';
2+
import { RegisterErrorHandler } from '../../src/index';
3+
4+
describe('Testing of RegisterErrorHandler function', () => {
5+
test('render javascript websocket register error handler method', () => {
6+
const result = render(
7+
<RegisterErrorHandler language='javascript' methodParams={['handler']} />
8+
);
9+
const actual = result.trim();
10+
expect(actual).toMatchSnapshot();
11+
});
12+
13+
test('render python websocket register error handler method', () => {
14+
const result = render(
15+
<RegisterErrorHandler
16+
language='python'
17+
methodParams={['self', 'handler']}
18+
preExecutionCode='"""Register a callable as a error handler."""'
19+
/>
20+
);
21+
const actual = result.trim();
22+
expect(actual).toMatchSnapshot();
23+
});
24+
25+
test('render dart websocket register error handler method', () => {
26+
const result = render(
27+
<RegisterErrorHandler
28+
language='dart'
29+
methodParams={['void Function(Object) handler']}
30+
/>
31+
);
32+
const actual = result.trim();
33+
expect(actual).toMatchSnapshot();
34+
});
35+
36+
test('render javascript method with custom name', () => {
37+
const result = render(
38+
<RegisterErrorHandler
39+
language='javascript'
40+
methodName='addHandler'
41+
methodParams={['handler']}
42+
/>
43+
);
44+
const actual = result.trim();
45+
expect(actual).toMatchSnapshot();
46+
});
47+
48+
test('render dart method with parameters', () => {
49+
const result = render(
50+
<RegisterErrorHandler
51+
language='dart'
52+
methodParams={['handler']}
53+
/>
54+
);
55+
const actual = result.trim();
56+
expect(actual).toMatchSnapshot();
57+
});
58+
59+
test('render python with pre and post execution code', () => {
60+
const result = render(
61+
<RegisterErrorHandler
62+
language='python'
63+
methodParams={['self', 'handler']}
64+
preExecutionCode='# Pre-register operations'
65+
postExecutionCode='# Post-register cleanup'
66+
/>
67+
);
68+
const actual = result.trim();
69+
expect(actual).toMatchSnapshot();
70+
});
71+
72+
test('render dart with all the props', () => {
73+
const customMethodConfig = {
74+
returnType: 'int',
75+
openingTag: '{',
76+
closingTag: '}',
77+
indentSize: 2
78+
};
79+
const result = render(
80+
<RegisterErrorHandler
81+
language='dart'
82+
methodName='bindHandler'
83+
methodParams={['handler']}
84+
preExecutionCode='// Preparing to bind handler'
85+
postExecutionCode='// Handler bound successfully'
86+
customMethodConfig={customMethodConfig}
87+
/>
88+
);
89+
const actual = result.trim();
90+
expect(actual).toMatchSnapshot();
91+
});
92+
});

0 commit comments

Comments
 (0)