lib/fn-params.js

const parse = require('meriyah').parseScript;

/**
 * @module pete/lib/fn-params
 */
module.exports = getParams;

/**
 * List names of function arguments.
 *
 * @alias module:pete/lib/fn-params
 * @throws {Error} when code or function cannot be parsed
 * @param {string|Function}  fn
 * @return {string[]}
 */
function getParams (fn) {
	const code = typeof fn === 'string' ? fn : fn.toString();
	// "wrap" it so function without a name will not trigger an error
	const parsed = parse(`var temp = ${code};`);
	return getParamsNames(parsed.body[0].declarations[0].init.params);
}

/**
 * @private
 * @param {object} params found by Acorn parser
 */
function getParamsNames (params) {
	return params
		.map(param => {
			if (param.type === 'Identifier') {
				return param.name;
			}

			if (param.type === 'AssignmentPattern') {
				return getParamsNames([param.left]);
			}

			if (param.type === 'ArrayPattern') {
				return getParamsNames(param.elements);
			}

			if (param.type === 'ObjectPattern') {
				return getParamsNames(param.properties);
			}

			if (param.type === 'Property' && param.kind === 'init') {
				return getParamsNames([param.value]);
			}

			if (param.type === 'RestElement') {
				return param.argument.name;
			}

			return null;
		})
		.flat()
		.filter(Boolean);
}