Skip to content

Commit 57c0be5

Browse files
authored
refactor(lodash): Removes most of the lodash dependencies in favor of native js (#117)
* refactor(lodash): Removes most of the lodash dependencies in favor of native js Most of these lodash dependencies have a native replacement. The only reason they seem to have been used was to wrap the natives with safe checks and returns. For example the use of `_forEach(list, () => ...)` is a safe version of: ``` (list || []).forEach((item) => ...); ``` Lodash protects against undefined, null. Others such as _.map also protect by returning an empty map so that chaining is safely allowed, some es6 doesn't allow native. * Version bump to 2.1.0 in prep of release
1 parent 29fe5f0 commit 57c0be5

9 files changed

+102
-90
lines changed

package-lock.json

+2-44
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "spur-ioc",
33
"description": "Dependency Injection library for Node.js",
4-
"version": "2.0.1",
4+
"version": "2.1.0",
55
"main": "./src/Injector",
66
"scripts": {
77
"lint": "eslint .",
@@ -52,13 +52,6 @@
5252
"dependencies": {
5353
"lodash.assign": "4.2.0",
5454
"lodash.bindall": "4.4.0",
55-
"lodash.compact": "3.0.1",
56-
"lodash.foreach": "4.5.0",
57-
"lodash.get": "4.4.2",
58-
"lodash.isfunction": "3.0.9",
59-
"lodash.isobject": "3.0.2",
60-
"lodash.keys": "4.2.0",
61-
"lodash.map": "4.6.0",
6255
"require-all": "3.0.0"
6356
},
6457
"devDependencies": {

src/ContainerManagement.js

+15-11
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
1-
const _forEach = require('lodash.foreach');
2-
const _get = require('lodash.get');
3-
const _isFunction = require('lodash.isfunction');
4-
const _isObject = require('lodash.isobject');
51
const Dependency = require('./Dependency');
2+
const Utils = require('./Utils');
63

74
const rall = /.+/;
85

96
module.exports = {
107

118
getDependencySourceHint(dependency) {
12-
if (_isFunction(dependency)) {
13-
return _get(dependency, 'name') || '<anonymous function>';
9+
if (Utils.isFunction(dependency)) {
10+
return dependency.name || '<anonymous function>';
1411
}
1512

16-
if (_isObject(dependency)) {
17-
return _get(dependency, 'constructor.name') || '<object>';
13+
if (Utils.isObject(dependency)) {
14+
return (dependency.constructor && dependency.constructor.name)
15+
? dependency.constructor.name
16+
: '<object>';
1817
}
1918

2019
return `<${typeof dependency}>`;
@@ -74,13 +73,18 @@ module.exports = {
7473
},
7574

7675
shouldIgnoreDependency(dependency) {
77-
return Boolean(_get(dependency, 'spurIocIgnore', false));
76+
const spurIocIgnore = (dependency && dependency.spurIocIgnore)
77+
? dependency.spurIocIgnore
78+
: false;
79+
80+
return Boolean(spurIocIgnore);
7881
},
7982

8083
merge(otherInjector, suppressWarning = false) {
81-
const dependencies = otherInjector.dependencies;
84+
const dependencies = otherInjector.dependencies || {};
85+
const names = Object.keys(dependencies) || [];
8286

83-
_forEach(dependencies, (value, name) => {
87+
names.forEach((name) => {
8488
const dependency = dependencies[name];
8589
this.addConstructedDependency(name, dependency, suppressWarning);
8690
});

src/DependencyResolver.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
const _bindAll = require('lodash.bindall');
2-
const _keys = require('lodash.keys');
32
const CallChain = require('./CallChain');
43

54
class DependencyError {
@@ -82,7 +81,7 @@ class DependencyResolver {
8281
}
8382

8483
resolveRegex(regex) {
85-
const deps = _keys(this.container.dependencies)
84+
const deps = (Object.keys(this.container.dependencies) || [])
8685
.filter((key) => { // eslint-disable-line
8786
return regex.test(key) && key !== '$injector' && key !== this.container.privateInjectorName();
8887
});

src/FunctionArgumentsParser.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
const _map = require('lodash.map');
2-
const _compact = require('lodash.compact');
3-
41
const NEWLINE = /\n/g;
52
const AT = /_at_/g;
63
const ARROW_ARG = /^([^(]+?)=>/;
@@ -21,11 +18,14 @@ class FunctionArgumentsParser {
2118

2219
argsDeclaration[1].split(FN_ARG_SPLIT).forEach(function (arg) {
2320
arg.replace(FN_ARG, function(name) {
24-
args.push(name);
21+
const cleanName = (name || '').trim();
22+
if (cleanName.length > 0) {
23+
args.push(cleanName);
24+
}
2525
});
2626
});
2727

28-
return _compact(_map(args, (p) => p.trim()));
28+
return args;
2929
}
3030

3131
extractArgs(fn) {

src/Logger.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
const _bindAll = require('lodash.bindall');
2-
const _forEach = require('lodash.foreach');
32

43
class Level {
54
constructor(level, name, ascii, exit = false) {
@@ -38,7 +37,8 @@ class Logger {
3837
}
3938

4039
addLoggingMethods() {
41-
_forEach(LEVELS, (value, name) => {
40+
const names = Object.keys(LEVELS) || [];
41+
names.forEach((name) => {
4242
if (Object.prototype.hasOwnProperty.call(LEVELS, name)) {
4343
this[name] = LEVELS[name].log;
4444
}

src/RegistrationManagement.js

+14-18
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
1-
const requireAll = require('require-all');
21
const path = require('path');
3-
const _forEach = require('lodash.foreach');
4-
const _isFunction = require('lodash.isfunction');
5-
const _isObject = require('lodash.isobject');
2+
const requireAll = require('require-all');
63

4+
const Utils = require('./Utils');
75
const fileFilterExpression = require('./FileFilterExpression');
86

9-
const hasOwnProp = function (source, propertyName) {
10-
return Object.prototype.hasOwnProperty.call(source, propertyName);
11-
};
12-
137
module.exports = {
148
registerFolder(rootDir, dir) {
159
const dirname = path.resolve(rootDir, dir);
@@ -21,28 +15,30 @@ module.exports = {
2115
return this;
2216
},
2317

24-
registerLibMap(libs) {
25-
_forEach(libs, (value, name) => {
26-
if (hasOwnProp(libs, name)) {
18+
registerLibMap(libs = {}) {
19+
const names = Object.keys(libs) || [];
20+
names.forEach((name) => {
21+
if (Utils.hasOwnProp(libs, name)) {
2722
const lib = libs[name];
28-
if (_isFunction(lib)) {
23+
if (Utils.isFunction(lib)) {
2924
this.addResolvableDependency(name, lib);
30-
} else if (_isObject(lib)) {
25+
} else if (Utils.isObject(lib)) {
3126
this.registerLibMap(lib);
3227
}
3328
}
3429
});
3530
return this;
3631
},
3732

38-
registerFolders(rootDir, dirs) {
39-
_forEach(dirs, (dir) => this.registerFolder(rootDir, dir));
33+
registerFolders(rootDir, dirs = []) {
34+
dirs.forEach((dir) => this.registerFolder(rootDir, dir));
4035
return this;
4136
},
4237

43-
registerDependencies(dependencies) {
44-
_forEach(dependencies, (value, name) => {
45-
if (hasOwnProp(dependencies, name)) {
38+
registerDependencies(dependencies = {}) {
39+
const names = Object.keys(dependencies) || [];
40+
names.forEach((name) => {
41+
if (Utils.hasOwnProp(dependencies, name)) {
4642
const lib = dependencies[name];
4743
this.addDependency(name, lib);
4844
}

src/Utils.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module.exports = {
2+
hasOwnProp(source, propertyName) {
3+
return Object.prototype.hasOwnProperty.call(source, propertyName);
4+
},
5+
6+
isFunction(value) {
7+
return typeof value === 'function';
8+
},
9+
10+
isObject(value) {
11+
const type = typeof value;
12+
return value != null && (type === 'object' || type === 'function');
13+
}
14+
};

test/unit/Utils.spec.js

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
const Utils = require('../../src/Utils');
2+
3+
describe('Utils', function () {
4+
describe('hasOwnProp', () => {
5+
it('should return true if the source object has the specified property', () => {
6+
const source = { name: 'John', age: 30 };
7+
const propertyName = 'name';
8+
const result = Utils.hasOwnProp(source, propertyName);
9+
expect(result).toBe(true);
10+
});
11+
12+
it('should return false if the source object does not have the specified property', () => {
13+
const source = { name: 'John', age: 30 };
14+
const propertyName = 'address';
15+
const result = Utils.hasOwnProp(source, propertyName);
16+
expect(result).toBe(false);
17+
});
18+
});
19+
20+
describe('isFunction', () => {
21+
it('should return true if the value is a function', () => {
22+
const value = () => {};
23+
const result = Utils.isFunction(value);
24+
expect(result).toBe(true);
25+
});
26+
27+
it('should return false if the value is not a function', () => {
28+
const value = 'Hello, World!';
29+
const result = Utils.isFunction(value);
30+
expect(result).toBe(false);
31+
});
32+
});
33+
34+
describe('isObject', () => {
35+
it('should return true if the value is an object', () => {
36+
const value = { name: 'John', age: 30 };
37+
const result = Utils.isObject(value);
38+
expect(result).toBe(true);
39+
});
40+
41+
it('should return false if the value is not an object', () => {
42+
const value = 'Hello, World!';
43+
const result = Utils.isObject(value);
44+
expect(result).toBe(false);
45+
});
46+
});
47+
48+
});

0 commit comments

Comments
 (0)