Comparing version 2.2.4 to 2.3.0
{ | ||
"automock": true, | ||
"unmockedModulePathPatterns": ["/node_modules/"], | ||
"collectCoverage": true | ||
"collectCoverage": true, | ||
"testPathIgnorePatterns": ["/node_modules/", "/utils/scripts"] | ||
} |
@@ -104,2 +104,32 @@ # ObjectUtils | ||
### `flat` | ||
Flatterns an object properties into a single level dictionary. | ||
```js | ||
const target = { | ||
propOne: { | ||
propOneSub: 'Charito!', | ||
}, | ||
propTwo: '!!!', | ||
}; | ||
console.log(ObjectUtils.flat(target); | ||
// Will output { 'propOne.propOneSub': 'Charito!', propTwo: '!!!' } | ||
``` | ||
### `unflat` | ||
This method does the exact opposite from `flat`: It takes an already flattern object and restores it structure. | ||
```js | ||
const target = { | ||
'propOne.propOneSub': 'Charito! | ||
propTwo: '!!!', | ||
}; | ||
console.log(ObjectUtils.unflat(target); | ||
// Will output { propOne: { propOneSub: 'Charito!' }, 'propTwo': '!!!' } | ||
``` | ||
## Technical documentation | ||
@@ -113,2 +143,2 @@ | ||
open ./docs/index.html | ||
``` | ||
``` |
@@ -43,5 +43,5 @@ const path = require('path'); | ||
} | ||
// Fix it so all the locations will end with `/`. | ||
if (!location.endsWith('/')) { | ||
location = `${location}/`; | ||
// Fix it so all the locations will end with a separator. | ||
if (!location.endsWith(path.sep)) { | ||
location = `${location}${path.sep}`; | ||
} | ||
@@ -48,0 +48,0 @@ // Add it to the dictionary. |
@@ -5,3 +5,3 @@ { | ||
"homepage": "https://homer0.github.io/wootils/", | ||
"version": "2.2.4", | ||
"version": "2.3.0", | ||
"repository": "homer0/wootils", | ||
@@ -22,3 +22,3 @@ "author": "Leonardo Apiwan (@homer0) <me@homer0.com>", | ||
"eslint-plugin-node": "9.0.1", | ||
"jest-ex": "6.0.1", | ||
"jest-ex": "6.1.0", | ||
"jest-cli": "24.8.0", | ||
@@ -43,6 +43,6 @@ "jasmine-expect": "4.0.1", | ||
"hooks": "./utils/hooks/install", | ||
"test": "./utils/scripts/test", | ||
"test": "node ./utils/scripts/test.js", | ||
"lint": "./utils/scripts/lint", | ||
"lint:full": "./utils/scripts/lint-full", | ||
"predocs": "./utils/scripts/docs-index", | ||
"predocs": "node ./utils/scripts/docs-index.js", | ||
"docs": "./utils/scripts/docs", | ||
@@ -49,0 +49,0 @@ "todo": "./utils/scripts/todo" |
@@ -153,1 +153,7 @@ # Wootils | ||
I use `@todo` comments to write all the pending improvements and fixes, and [Leasot](https://yarnpkg.com/en/package/leasot) to generate a report. The script that runs it is on `./utils/scripts/todo`. | ||
### Windows | ||
You can work with this project on Windows, but it only works if you use [Yarn](https://yarnpkg.com/en/docs/install). The reason is that NPM on Windows doesn't allow you to use paths like `./scripts/something` on the `package.json` scripts, while Yarn does. | ||
Another alternative if you are using Windows is to use [WSL](https://docs.microsoft.com/en-us/windows/wsl/install-win10). |
@@ -153,1 +153,7 @@ # Wootils | ||
I use `@todo` comments to write all the pending improvements and fixes, and [Leasot](https://yarnpkg.com/en/package/leasot) to generate a report. The script that runs it is on `./utils/scripts/todo`. | ||
### Windows | ||
You can work with this project on Windows, but it only works if you use [Yarn](https://yarnpkg.com/en/docs/install). The reason is that NPM on Windows doesn't allow you to use paths like `./scripts/something` on the `package.json` scripts, while Yarn does. | ||
Another alternative if you are using Windows is to use [WSL](https://docs.microsoft.com/en-us/windows/wsl/install-win10). |
@@ -292,4 +292,75 @@ const extend = require('extend'); | ||
} | ||
/** | ||
* Flatterns an object properties into a single level dictionary. | ||
* @example | ||
* const target = { | ||
* propOne: { | ||
* propOneSub: 'Charito!', | ||
* }, | ||
* propTwo: '!!!', | ||
* }; | ||
* console.log(ObjectUtils.flat(target); | ||
* // Will output { 'propOne.propOneSub': 'Charito!', propTwo: '!!!' } | ||
* | ||
* @param {Object} target The object to transform. | ||
* @param {String} [pathDelimiter='.'] The delimiter that will separate | ||
* the path components. | ||
* @param {String} [prefix=''] A custom prefix to be added before | ||
* the name of the properties. This | ||
* can be used on custom cases and | ||
* it's also used when the method | ||
* calls itself in order to flattern | ||
* a sub object. | ||
* @param {?Function(String,*):Boolean} [shouldFlattern=null] A custom function that can be used | ||
* in order to tell the method whether | ||
* an Object or an Array property | ||
* should be flattern or not. It will | ||
* receive the key for the property | ||
* and the Object/Array itself. | ||
* @return {Object} | ||
*/ | ||
static flat(target, pathDelimiter = '.', prefix = '', shouldFlattern = null) { | ||
let result = {}; | ||
const namePrefix = prefix ? `${prefix}${pathDelimiter}` : ''; | ||
Object.keys(target).forEach((key) => { | ||
const name = `${namePrefix}${key}`; | ||
const value = target[key]; | ||
const valueType = typeof value; | ||
if (valueType === 'object' && (!shouldFlattern || shouldFlattern(key, value))) { | ||
result = this.merge(result, this.flat( | ||
value, | ||
pathDelimiter, | ||
name, | ||
shouldFlattern | ||
)); | ||
} else { | ||
result[name] = valueType === 'object' ? this.copy(value) : value; | ||
} | ||
}); | ||
return result; | ||
} | ||
/** | ||
* This method does the exact opposite from `flat`: It takes an already flattern object and | ||
* restores it structure. | ||
* @example | ||
* const target = { | ||
* 'propOne.propOneSub': 'Charito! | ||
* propTwo: '!!!', | ||
* }; | ||
* console.log(ObjectUtils.unflat(target); | ||
* // Will output { propOne: { propOneSub: 'Charito!' }, 'propTwo': '!!!' } | ||
* | ||
* @param {Object} target The object to transform. | ||
* @param {String} [pathDelimiter='.'] The delimiter that will separate the path components. | ||
* @return {Object} | ||
*/ | ||
static unflat(target, pathDelimiter = '.') { | ||
return Object.keys(target).reduce( | ||
(current, key) => this.set(current, key, target[key], pathDelimiter), | ||
{} | ||
); | ||
} | ||
} | ||
module.exports = ObjectUtils; |
@@ -5,2 +5,3 @@ jest.unmock('/node/appConfiguration'); | ||
require('jasmine-expect'); | ||
const path = require('path'); | ||
const { | ||
@@ -28,3 +29,3 @@ AppConfiguration, | ||
const getDefaultFileInfo = (name) => ({ | ||
path: `config/app/app.${name}.config.js`, | ||
path: path.join('config', 'app', `app.${name}.config.js`), | ||
name: `app.${name}.config.js`, | ||
@@ -31,0 +32,0 @@ }); |
@@ -34,3 +34,3 @@ jest.unmock('/node/pathUtils'); | ||
// Given | ||
const home = '/some-folder/'; | ||
const home = `${path.sep}some-folder${path.sep}`; | ||
process.cwd = jest.fn(() => home); | ||
@@ -40,5 +40,3 @@ let sut = null; | ||
let appPath = null; | ||
// The `substr` is to remove the leading `/` | ||
const thisfilePath = __dirname.substr(1); | ||
const expectedAppPath = `${home}${thisfilePath}/`; | ||
const expectedAppPath = path.join(home, __dirname); | ||
// When | ||
@@ -50,3 +48,3 @@ sut = new PathUtils(); | ||
expect(homePath).toBe(home); | ||
expect(appPath).toBe(expectedAppPath); | ||
expect(appPath).toBe(`${expectedAppPath}${path.sep}`); | ||
}); | ||
@@ -53,0 +51,0 @@ |
@@ -550,2 +550,199 @@ jest.unmock('/shared/objectUtils'); | ||
}); | ||
describe('flat', () => { | ||
it('should flattern the properties of an object', () => { | ||
// Given | ||
const name = 'Rosario'; | ||
const nickname = 'Charito'; | ||
const age = 3; | ||
const total = 1; | ||
const numbers = [ | ||
'one', | ||
'two', | ||
'three', | ||
]; | ||
const target = { | ||
total, | ||
person: { | ||
age, | ||
names: { | ||
name, | ||
nickname, | ||
}, | ||
numbers, | ||
}, | ||
}; | ||
let result = null; | ||
const expected = Object.assign( | ||
{ | ||
total, | ||
'person.age': age, | ||
'person.names.name': name, | ||
'person.names.nickname': nickname, | ||
}, | ||
numbers.reduce( | ||
(acc, item, index) => Object.assign({}, acc, { | ||
[`person.numbers.${index}`]: item, | ||
}), | ||
{} | ||
) | ||
); | ||
// When | ||
result = ObjectUtils.flat(target); | ||
// Then | ||
expect(result).toEqual(expected); | ||
}); | ||
it('should flattern the properties of an object using a custom path', () => { | ||
// Given | ||
const name = 'Rosario'; | ||
const nickname = 'Charito'; | ||
const age = 3; | ||
const total = 1; | ||
const numbers = [ | ||
'one', | ||
'two', | ||
'three', | ||
]; | ||
const target = { | ||
total, | ||
person: { | ||
age, | ||
names: { | ||
name, | ||
nickname, | ||
}, | ||
numbers, | ||
}, | ||
}; | ||
const separator = '/'; | ||
let result = null; | ||
const expected = Object.assign( | ||
{ | ||
total, | ||
[`person${separator}age`]: age, | ||
[`person${separator}names${separator}name`]: name, | ||
[`person${separator}names${separator}nickname`]: nickname, | ||
}, | ||
numbers.reduce( | ||
(acc, item, index) => Object.assign({}, acc, { | ||
[`person${separator}numbers${separator}${index}`]: item, | ||
}), | ||
{} | ||
) | ||
); | ||
// When | ||
result = ObjectUtils.flat(target, separator); | ||
// Then | ||
expect(result).toEqual(expected); | ||
}); | ||
it('should flattern the properties except those filtered by a callback', () => { | ||
// Given | ||
const name = 'Rosario'; | ||
const nickname = 'Charito'; | ||
const age = 3; | ||
const total = 1; | ||
const numbers = [ | ||
'one', | ||
'two', | ||
'three', | ||
]; | ||
const target = { | ||
total, | ||
person: { | ||
age, | ||
names: { | ||
name, | ||
nickname, | ||
}, | ||
numbers, | ||
}, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.flat(target, '.', '', (key, value) => !Array.isArray(value)); | ||
// Then | ||
expect(result).toEqual({ | ||
total, | ||
'person.age': age, | ||
'person.names.name': name, | ||
'person.names.nickname': nickname, | ||
'person.numbers': numbers, | ||
}); | ||
}); | ||
}); | ||
describe('unflat', () => { | ||
it('should un-flattern a list of properties into a new object', () => { | ||
// Given | ||
const name = 'Rosario'; | ||
const nickname = 'Charito'; | ||
const age = 3; | ||
const total = 1; | ||
const numbers = [ | ||
'one', | ||
'two', | ||
'three', | ||
]; | ||
const target = { | ||
total, | ||
'person.age': age, | ||
'person.names.name': name, | ||
'person.names.nickname': nickname, | ||
'person.numbers': numbers, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.unflat(target); | ||
// Then | ||
expect(result).toEqual({ | ||
total, | ||
person: { | ||
age, | ||
names: { | ||
name, | ||
nickname, | ||
}, | ||
numbers, | ||
}, | ||
}); | ||
}); | ||
it('should un-flattern a list of properties into a new object using a custom path', () => { | ||
// Given | ||
const name = 'Rosario'; | ||
const nickname = 'Charito'; | ||
const age = 3; | ||
const total = 1; | ||
const numbers = [ | ||
'one', | ||
'two', | ||
'three', | ||
]; | ||
const separator = '/'; | ||
const target = { | ||
total, | ||
[`person${separator}age`]: age, | ||
[`person${separator}names${separator}name`]: name, | ||
[`person${separator}names${separator}nickname`]: nickname, | ||
[`person${separator}numbers`]: numbers, | ||
}; | ||
let result = null; | ||
// When | ||
result = ObjectUtils.unflat(target, separator); | ||
// Then | ||
expect(result).toEqual({ | ||
total, | ||
person: { | ||
age, | ||
names: { | ||
name, | ||
nickname, | ||
}, | ||
numbers, | ||
}, | ||
}); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
561002
73
7232
159
11