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 const stringArgument = convertEnumArgumentToString(value, property); 84 if (!stringArgument) return; 85 return `${property.name}: ${stringArgument}`; 86 } 87 88 return `${property.name}: ${property.type === 'string' ? `"${value}"` : value}`; 89 }) 90 .filter((entry) => !!entry) // filter out all void values 91 .join(',\n '); 92 93 return `{\n ${properties}\n}`; 94} 95 96function convertEnumArgumentToString(arg: FunctionArgument, { name, values }: EnumParameter) { 97 // this should always find the current value for the enum, if failed something is messed up somewhere else 98 // eslint-disable-next-line no-case-declarations 99 const value = values.find(({ value }) => 100 typeof value === 'object' && typeof arg === 'object' 101 ? JSON.stringify(value) === JSON.stringify(arg) // for tuple case 102 : value === arg 103 ); 104 if (!value) { 105 return; 106 } 107 return value.name; 108} 109