Skip to content

Commit

Permalink
feat(defaults): add support for fallback defaults
Browse files Browse the repository at this point in the history
Added extra jsdocs documentation
Updated tests
  • Loading branch information
danielo515 committed May 26, 2018
1 parent ff5ee6e commit 8a0393d
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 3 deletions.
83 changes: 83 additions & 0 deletions __tests__/index.test.js
Expand Up @@ -92,7 +92,90 @@ describe(`object-translate`, () => {

});
});
describe(`Using defaults`, () => {
it(`Should pick non existing values from matching defaults`, () => {

const original = {
a: {
b: {
c: `cvalue`
}
}
};
const defaults = {
d: {
e: {
f: `fvalue`
}
}
};
const expected = {
c: `cvalue`,
f: `fvalue`
};

const converter = Generator({c: `a.b.c`, f: `d.e.f`}, defaults);
const result = converter(original);
expect(result).toEqual(expected);

});
it(`Values not existing on original neither on defaults should fallback to the $default path`, () => {

const original = {
a: {
b: {
c: `cvalue`
}
}
};
const defaults = {
$default: `NA`,
d: {
e: {
f: `fvalue`
}
}
};
const expected = {
c: `cvalue`,
f: `fvalue`,
x: `NA`
};

const converter = Generator({c: `a.b.c`, f: `d.e.f`, x: `d.e.f.x`}, defaults);
const result = converter(original);
expect(result).toEqual(expected);

});
it(`The default fallback path should be configurable`, () => {

const original = {
a: {
b: {
c: `cvalue`
}
}
};
const defaults = {
$myDefault: `NA`,
d: {
e: {
f: `fvalue`
}
}
};
const expected = {
c: `cvalue`,
f: `fvalue`,
x: `NA`
};

const converter = Generator({c: `a.b.c`, f: `d.e.f`, x: `d.e.f.x`}, defaults, {defaultPath: `$myDefault`});
const result = converter(original);
expect(result).toEqual(expected);

});
});
describe(`Advanced usage`, () => {

it(`Should pick the first alternative that matches`, () => {
Expand Down
20 changes: 17 additions & 3 deletions src/index.js
@@ -1,8 +1,20 @@
'use strict';
const Op = require(`object-path`);
const Traverse = require(`traverse`);
const tryDefault = (method, src, path, altPath) => {
const def = Op[method](src, path);
return def === undefined ? Op[method](src, altPath) : def;
};

module.exports = (mapDefinition, defaults) => {
/**
* @function {function name}
* @param {Object} mapDefinition Mapping description describing the final shape you want and paths to where those values are
* @param {Object} defaults An object with default values on the same paths as the expected object
* @param {Object} options An object containing additional options
* @param {String = $default} Options.defaultPath Name of the default path when something does not exist on the defaults object
* @return {Function} A converter function with the provided configuration
*/
module.exports = (mapDefinition, defaults, {defaultPath = `$default`} = {}) => {

defaults = defaults || {};

Expand All @@ -19,7 +31,7 @@ module.exports = (mapDefinition, defaults) => {
const hasAlternatives = isObject && Array.isArray(item.alternatives);
const hasProcessor = isObject && typeof item.processor === `function`;
// not leaf, not alternatives, no processor, this means a regular object so skip
// it
// it to traverse it later
if (!hasAlternatives && !hasProcessor) {
return;
}
Expand All @@ -41,7 +53,9 @@ module.exports = (mapDefinition, defaults) => {

let originalValue = Op[getMethod](originalObj, path);
// try to use a default value ONLY if the original value is undefined. Values like false, 0, '', null, will pass as they are
originalValue = originalValue === undefined ? Op[getMethod](defaults, path) : originalValue;
originalValue = originalValue === undefined
? tryDefault(getMethod, defaults, path, defaultPath)
: originalValue;

const newValue = process(originalValue, originalObj);

Expand Down

0 comments on commit 8a0393d

Please sign in to comment.