Skip to content

Commit

Permalink
Replace lodash.get with local function; support array paths. (#177)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidtheclark committed Mar 9, 2019
1 parent 71da326 commit bf8e534
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 5 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,10 @@
# Changelog

## HEAD

- Added: `packageProp` values can be arrays of strings, to allow for property names that include periods. (This was possible before, but not documented or deliberately supported.)
- Chore: Replaced the `lodash.get` dependency with a locally defined function.

## 5.1.0

- Added: `packageProp` values can include periods to describe paths to nested objects within `package.json`.
Expand Down
29 changes: 27 additions & 2 deletions README.md
Expand Up @@ -405,12 +405,14 @@ Examples:

### packageProp

Type: `string`.
Type: `string | Array<string>`.
Default: `` `${moduleName}` ``.

Name of the property in `package.json` to look for.

Use periods to describe a path to nested properties. For example, the value `'configs.myPackage'` will get you the `"myPackage"` value in a `package.json` like this:
Use a period-delimited string or an array of strings to describe a path to nested properties.

For example, the value `'configs.myPackage'` or `['configs', 'myPackage']` will get you the `"myPackage"` value in a `package.json` like this:

```json
{
Expand All @@ -420,6 +422,29 @@ Use periods to describe a path to nested properties. For example, the value `'co
}
```

If nested property names within the path include periods, you need to use an array of strings. For example, the value `['configs', 'foo.bar', 'baz']` will get you the `"baz"` value in a `package.json` like this:

```json
{
"configs": {
"foo.bar": {
"baz": {..}
}
}
}
```

If a string includes period but corresponds to a top-level property name, it will not be interpreted as a period-delimited path. For example, the value `'one.two'` will get you the `"three"` value in a `package.json` like this:

```json
{
"one.two": "three",
"one": {
"two": "four"
}
}
```

### stopDir

Type: `string`.
Expand Down
1 change: 0 additions & 1 deletion package.json
Expand Up @@ -86,7 +86,6 @@
"import-fresh": "^2.0.0",
"is-directory": "^0.3.1",
"js-yaml": "^3.9.0",
"lodash.get": "^4.4.2",
"parse-json": "^4.0.0"
},
"devDependencies": {
Expand Down
7 changes: 5 additions & 2 deletions src/createExplorer.js
Expand Up @@ -2,11 +2,11 @@
'use strict';

const path = require('path');
const get = require('lodash.get');
const loaders = require('./loaders');
const readFile = require('./readFile');
const cacheWrapper = require('./cacheWrapper');
const getDirectory = require('./getDirectory');
const getPropertyByPath = require('./getPropertyByPath');

const MODE_SYNC = 'sync';

Expand Down Expand Up @@ -174,7 +174,10 @@ class Explorer {

loadPackageProp(filepath: string, content: string) {
const parsedContent = loaders.loadJson(filepath, content);
const packagePropValue = get(parsedContent, this.config.packageProp);
const packagePropValue = getPropertyByPath(
parsedContent,
this.config.packageProp
);
return packagePropValue || null;
}

Expand Down
23 changes: 23 additions & 0 deletions src/getPropertyByPath.js
@@ -0,0 +1,23 @@
// @flow
'use strict';

// Resolves property names or property paths defined with period-delimited
// strings or arrays of strings. Property names that are found on the source
// object are used directly (even if they include a period).
// Nested property names that include periods, within a path, are only
// understood in array paths.
function getPropertyByPath(source: Object, path: string | Array<string>): any {
if (typeof path === 'string' && source.hasOwnProperty(path)) {
return source[path];
}

const parsedPath = typeof path === 'string' ? path.split('.') : path;
return parsedPath.reduce((previous, key) => {
if (previous === undefined) {
return previous;
}
return previous[key];
}, source);
}

module.exports = getPropertyByPath;
91 changes: 91 additions & 0 deletions test/getPropertyByPath.test.js
@@ -0,0 +1,91 @@
'use strict';

const getPropertyPath = require('../src/getPropertyByPath');

const source = {
ant: {
beetle: {
cootie: {
flea: 'foo',
},
louse: {
vermin: 'bar',
},
},
'fancy.name': {
'another.fancy.name': 9,
},
},
'ant.beetle.cootie': 333,
};

describe('with a property name that includes a period', () => {
test('does not treat it as a period-delimited path', () => {
expect(getPropertyPath(source, 'ant.beetle.cootie')).toBe(333);
});
});

describe('with period-delimited string path', () => {
test('returns a defined value', () => {
expect(getPropertyPath(source, 'ant')).toBe(source.ant);

expect(getPropertyPath(source, 'ant.beetle.cootie.flea')).toBe('foo');

expect(getPropertyPath(source, 'ant.beetle.louse')).toBe(
source.ant.beetle.louse
);
});

test('returns undefined', () => {
expect(getPropertyPath(source, 'beetle')).toBeUndefined();

expect(getPropertyPath(source, 'ant.beetle.cootie.fleeee')).toBeUndefined();

expect(getPropertyPath(source, 'ant.beetle.vermin')).toBeUndefined();

expect(getPropertyPath(source, 'ant.fancy.name')).toBeUndefined();
});
});

describe('with array path', () => {
test('returns a defined value', () => {
expect(getPropertyPath(source, ['ant'])).toBe(source.ant);

expect(getPropertyPath(source, ['ant', 'beetle', 'cootie', 'flea'])).toBe(
'foo'
);

expect(getPropertyPath(source, ['ant', 'beetle', 'louse'])).toBe(
source.ant.beetle.louse
);
});

test('returns undefined', () => {
expect(getPropertyPath(source, ['beetle'])).toBeUndefined();

expect(
getPropertyPath(source, ['ant', 'beetle', 'cootie', 'fleeee'])
).toBeUndefined();

expect(
getPropertyPath(source, ['ant', 'beetle', 'vermin'])
).toBeUndefined();
});

test('handles property names with periods', () => {
expect(
getPropertyPath(source, ['ant', 'fancy.name', 'another.fancy.name'])
).toBe(9);

expect(
getPropertyPath(source, [
'ant',
'fancy.name',
'another.fancy.name',
'foo',
])
).toBeUndefined;

expect(getPropertyPath(source, ['ant', 'fancy.namez'])).toBeUndefined;
});
});

0 comments on commit bf8e534

Please sign in to comment.