1import React from 'react'; 2 3import MonoText from '../MonoText'; 4import { EnumParameter, FunctionArgument, FunctionParameter, ObjectParameter } from './index.types'; 5import { isCurrentPlatformSupported } from './utils'; 6 7export default function FunctionSignature(props: { 8 namespace: string; 9 name: string; 10 parameters: FunctionParameter[]; 11 args: FunctionArgument[]; 12}) { 13 return <MonoText>{generateFunctionSignature(props)}</MonoText>; 14} 15 16export function generateFunctionSignature({ 17 namespace, 18 name, 19 parameters, 20 args, 21}: { 22 namespace: string; 23 name: string; 24 parameters: FunctionParameter[]; 25 args: FunctionArgument[]; 26}) { 27 return `${namespace}.${name}(${argumentsToString(args, parameters)})`; 28} 29 30function argumentsToString(args: FunctionArgument[], parameters: FunctionParameter[]) { 31 return parameters 32 .map((parameter, idx) => { 33 if (!isCurrentPlatformSupported(parameter.platforms)) { 34 return; 35 } 36 switch (parameter.type) { 37 case 'object': 38 return convertObjectArgumentToString(args[idx], parameter); 39 case 'enum': 40 return convertEnumArgumentToString(args[idx], parameter); 41 case 'constant': 42 return parameter.name; 43 default: 44 return String(args[idx]); 45 } 46 }) 47 .filter((arg) => !!arg) // filter out all void values 48 .join(', '); 49} 50 51function convertObjectArgumentToString(arg: FunctionArgument, parameter: ObjectParameter) { 52 const properties = parameter.properties 53 .map((property) => { 54 // skip object properties unsupported on the current platform 55 if (!isCurrentPlatformSupported(property.platforms)) { 56 return; 57 } 58 59 if (typeof arg !== 'object' || Array.isArray(arg) /** filter out tuples/arrays */) { 60 throw new Error( 61 `Value ${arg} is not an object. Expecting object for ${parameter.name} argument` 62 ); 63 } 64 65 if (!(property.name in arg)) { 66 throw new Error( 67 `Property ${ 68 property.name 69 } is missing in argument. Available parameter properties: ${parameter.properties 70 .map((p) => p.name) 71 .join(', ')} and argument properties: ${Object.keys(arg).join(', ')}` 72 ); 73 } 74 75 const value = arg[property.name]; 76 77 // skip `undefined` values 78 if (value === undefined) { 79 return; 80 } 81 82 if (property.type === 'enum') { 83 return `${property.name}: ${convertEnumArgumentToString(value, property)}`; 84 } 85 86 return `${property.name}: ${property.type === 'string' ? `"${value}"` : value}`; 87 }) 88 .filter((entry) => !!entry) // filter out all void values 89 .join(',\n '); 90 91 return `{\n ${properties}\n}`; 92} 93 94function convertEnumArgumentToString(arg: FunctionArgument, { name, values }: EnumParameter) { 95 // this should always find the current value for the enum, if failed something is messed up somewhere else 96 // eslint-disable-next-line no-case-declarations 97 const value = values.find(({ value }) => 98 typeof value === 'object' && typeof arg === 'object' 99 ? JSON.stringify(value) === JSON.stringify(arg) // for tuple case 100 : value === arg 101 ); 102 if (!value) { 103 throw new Error( 104 `Value ${arg} not found in available values for enum parameter ${name}. Available values: ${values 105 .map((v) => `${v.name} -> ${v.value}`) 106 .join(', ')}` 107 ); 108 } 109 return value.name; 110} 111