Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: proper use of type from ui builder backend #317

Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ exports[`react-component-render-helper buildFixedJsxExpression parsed null 1`] =

exports[`react-component-render-helper buildFixedJsxExpression parsed number 1`] = `"{400}"`;

exports[`react-component-render-helper buildFixedJsxExpression parsed number 2`] = `"{400}"`;

exports[`react-component-render-helper buildFixedJsxExpression parsed object 1`] = `"{{ \\"transponder\\": \\"rocinante\\" }}"`;

exports[`react-component-render-helper buildFixedJsxExpression string 1`] = `"\\"some text\\""`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export default function CustomButton(
<Button
color=\\"#ff0000\\"
width={20}
isDisabled={true}
{...rest}
{...getOverrideProps(overrides, \\"Button\\")}
></Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ describe('react-component-render-helper', () => {

test('parsed number', () => {
assertASTMatchesSnapshot(buildFixedJsxExpression({ value: '400', type: 'Number' }));
assertASTMatchesSnapshot(buildFixedJsxExpression({ value: '400', type: 'number' }));
});

test('boolean', () => {
Expand Down Expand Up @@ -145,5 +146,15 @@ describe('react-component-render-helper', () => {
test('parsed null', () => {
assertASTMatchesSnapshot(buildFixedJsxExpression({ value: 'null', type: 'Object' }));
});

test('type mismatch error', () => {
expect(() => buildFixedJsxExpression({ value: 'true', type: 'number' })).toThrow(
'Parsed value type "boolean" and specified type "number" mismatch',
);
});

test('json parse error', () => {
expect(() => buildFixedJsxExpression({ value: '⭐', type: 'number' })).toThrow('Failed to parse value "⭐"');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
"width": {
"type": "Number",
"value": "20"
},
"isDisabled": {
"type": "boolean",
"value": "true"
}
}
}
59 changes: 33 additions & 26 deletions packages/codegen-ui-react/lib/react-component-render-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,37 +145,44 @@ export function buildFixedJsxExpression(prop: FixedStudioComponentProperty): Str
case 'boolean':
return factory.createJsxExpression(undefined, value ? factory.createTrue() : factory.createFalse());
case 'string':
switch (type) {
case undefined:
return factory.createStringLiteral(value as string);
dpilch marked this conversation as resolved.
Show resolved Hide resolved
case 'String':
return factory.createStringLiteral(value as string);
case 'Object':
case 'Number':
case 'Boolean':
try {
const parsedValue = JSON.parse(value as string);

if (typeof parsedValue === 'number') {
return factory.createJsxExpression(undefined, factory.createNumericLiteral(parsedValue, undefined));
}
if (typeof parsedValue === 'boolean') {
return factory.createJsxExpression(undefined, parsedValue ? factory.createTrue() : factory.createFalse());
}
// object, array, and null
if (typeof parsedValue === 'object') {
return factory.createJsxExpression(undefined, jsonToLiteral(parsedValue));
}
} catch {} // eslint-disable-line no-empty
throw new Error(`Failed to parse value "${value}" as type ${type}`);
default:
throw new Error(`Invalid type ${type} for "${value}"`);
}
return stringToJsxExpression(value as string, type);
default:
throw new Error(`Invalid type ${typeof value} for "${value}"`);
}
}

function stringToJsxExpression(strValue: string, type: string | undefined) {
switch (type) {
case undefined:
case 'String':
case 'string':
return factory.createStringLiteral(strValue);
default:
try {
const parsedValue = JSON.parse(strValue);
if (type && typeof parsedValue !== type.toLowerCase()) {
throw new Error(`Parsed value type "${typeof parsedValue}" and specified type "${type}" mismatch`);
}

switch (typeof parsedValue) {
case 'number':
return factory.createJsxExpression(undefined, factory.createNumericLiteral(parsedValue, undefined));
case 'boolean':
return factory.createJsxExpression(undefined, parsedValue ? factory.createTrue() : factory.createFalse());
// object, array, and null
default:
return factory.createJsxExpression(undefined, jsonToLiteral(parsedValue));
}
} catch (e) {
if (e instanceof SyntaxError) {
throw new Error(`Failed to parse value "${strValue}"`);
} else {
throw e;
}
}
}
}

export function buildFixedAttr(prop: FixedStudioComponentProperty, propName: string): JsxAttribute {
const expr = buildFixedJsxExpression(prop);
return factory.createJsxAttribute(factory.createIdentifier(propName), expr);
Expand Down