126 lines
3.9 KiB
JavaScript
126 lines
3.9 KiB
JavaScript
'use strict';
|
|
|
|
const splitSkip = require('split-skip');
|
|
const unpack = require('unpack-string');
|
|
const inspectFunction = require('inspect-function');
|
|
const stringifyParameters = require('stringify-parameters');
|
|
const { getParametersNames, inspectParameters, getParametersNamesFromInspection } = require('inspect-parameters-declaration');
|
|
|
|
const isArrayLike = p => p.match(/^\[+/) || undefined;
|
|
const isObjectLike = p => p.match(/^{+/) || undefined;
|
|
const matchObjectProperty = p => p.match(/^([^{]+):(.*)/) || undefined;
|
|
|
|
function setDestructuringParameterArgumentsIntoObject(parameter, data) {
|
|
const unpackedParameter = unpack(parameter);
|
|
const inspectedParameters = inspectParameters(unpackedParameter);
|
|
|
|
return inspectedParameters.reduce((parameterValue, inspectedParameter) => {
|
|
let objectProperty = matchObjectProperty(inspectedParameter.parameter);
|
|
if (objectProperty) {
|
|
let [, key, value] = objectProperty.map(v => v.trim());
|
|
let [valueInspectedParameter] = inspectParameters(value);
|
|
parameterValue[key] = setArgumentValue(valueInspectedParameter, data);
|
|
} else {
|
|
parameterValue[inspectedParameter.parameter] = setArgumentValue(inspectedParameter, data);
|
|
}
|
|
|
|
return parameterValue;
|
|
}, {});
|
|
}
|
|
|
|
function setDestructuringParameterArgumentsIntoArray(parameter, data) {
|
|
const unpackedParameter = unpack(parameter);
|
|
const inspectedParameters = inspectParameters(unpackedParameter);
|
|
return prepareArgumentsArray(inspectedParameters, data);
|
|
}
|
|
|
|
function setDestructuringParameterArguments(parameter, data) {
|
|
if (isArrayLike(parameter)) {
|
|
return setDestructuringParameterArgumentsIntoArray(parameter, data);
|
|
}
|
|
|
|
if (isObjectLike(parameter)) {
|
|
return setDestructuringParameterArgumentsIntoObject(parameter, data);
|
|
}
|
|
}
|
|
|
|
function setArgumentValue({ parameter, expectsDestructuring, defaultValue } = {}, data) {
|
|
if (!expectsDestructuring) {
|
|
return data[parameter];
|
|
}
|
|
|
|
if (defaultValue) {
|
|
const someDestructuringParameterIsSet = getParametersNames(parameter).some(parameterName => data[parameterName]);
|
|
if (!someDestructuringParameterIsSet) {
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
return setDestructuringParameterArguments(parameter, data);
|
|
}
|
|
|
|
function prepareArgumentsArray(inspectedParameters, data = {}) {
|
|
return inspectedParameters.map(inspectedParameter => setArgumentValue(inspectedParameter, data));
|
|
}
|
|
|
|
function prepareArgs(fn, object, ...args) {
|
|
if (!fn) {
|
|
return [];
|
|
}
|
|
|
|
if (!object) {
|
|
return args;
|
|
}
|
|
|
|
if (object && object.constructor === String) {
|
|
try {
|
|
object = JSON.parse(object);
|
|
} catch (ex) {
|
|
if(!args.length){
|
|
return [];
|
|
}
|
|
|
|
object = {};
|
|
}
|
|
}
|
|
|
|
const dataKeys = Object.keys(object);
|
|
if (!dataKeys.length) {
|
|
return args;
|
|
}
|
|
|
|
let argumentsArray = [];
|
|
const parameters = stringifyParameters(fn);
|
|
const inspectedParameters = parameters && inspectParameters(parameters);
|
|
|
|
if(inspectedParameters && inspectedParameters.length){
|
|
const restParameter = inspectedParameters.find(inspectedParameter => inspectedParameter.isRestParameter);
|
|
const inspectedParametersExcludingRestParameter = inspectedParameters.filter(inspectedParameter => inspectedParameter !== restParameter);
|
|
|
|
argumentsArray = argumentsArray.concat(prepareArgumentsArray(inspectedParametersExcludingRestParameter, object));
|
|
|
|
if (restParameter && object[restParameter.parameter]) {
|
|
if(object[restParameter.parameter].constructor === Array){
|
|
argumentsArray = argumentsArray.concat(object[restParameter.parameter]);
|
|
} else {
|
|
argumentsArray.push(object[restParameter.parameter]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Include unexpected parameters names at the end of the arguments list
|
|
const expectedArgumentsNames = getParametersNamesFromInspection(inspectedParameters);
|
|
dataKeys.forEach(key => {
|
|
if (!expectedArgumentsNames.includes(key)) {
|
|
argumentsArray.push(object[key]);
|
|
}
|
|
});
|
|
|
|
return argumentsArray.concat(args);
|
|
}
|
|
|
|
function prepareArgsAndCall(fn, object = {}, ...args) {
|
|
return fn(...prepareArgs(fn, object, ...args));
|
|
}
|
|
|
|
module.exports = { prepareArgs, prepareArgsAndCall }; |