Skip to content

Commit e517276

Browse files
acolchadoterry-au
andauthored
Merges the 2.0.0 release candidate branch (#89)
* Adds the ability to read the typescript files (#76) This addition is not meant to be full support of typescript from the library. It's meant to allow the reading of the files in the case you are looking to use TS files and are responsible for the transpilation/compilation of those files. We are experimenting adding this to allow us to use ts files with ts-jest and other tooling in our tests and source files. The compilation is happening locally and doesn't depend on the package having full support for a build pipeline. This will be published a major version so that those who may have .ts files won't have a break in their dev flow but once it's promoted out of release candidate, it will have proper documentation if we opt to keep the support. * v2.0.0-rc.0 (#77) * feat(*): [RO-18670] add ability to ignore dependencies (#78) * feat(*): RO-18670 Extend spur-ioc to add the ability to skip dependency registration add support for skipping dependency injection by setting * feat(*): RO-18670 Extend spur-ioc to add the ability to skip dependency registration improve logging output when warning against dependency registration collisions * feat(*): RO-18670 Extend spur-ioc to add the ability to skip dependency registration fix passing incorrect parameters improve logging * feat(*): RO-18670 Extend spur-ioc to add the ability to skip dependency registration add warning for ignored dependencies * feat(*): RO-18670 Extend spur-ioc to add the ability to skip dependency registration add test cases for registerFolders and addResolvableDependency * feat(*): RO-18670 Extend spur-ioc to add the ability to skip dependency registration add test cases for addDependency * feat(*): RO-18670 Extend spur-ioc to add the ability to skip dependency registration update FileFilterExpression to ignore .d.ts files add test * feat(*): RO-18670 Extend spur-ioc to add the ability to skip dependency registration fix file filter causing issues with some imports update logging to print primitive types * feat(*): RO-18670 Extend spur-ioc to add the ability to skip dependency registration added missing lodash.get dependency * feat(*): RO-18670 Extend spur-ioc to add the ability to skip dependency registration (#80) fix logging * v2.0.0-rc.1 (#79) * refactor(warnings): Removes the noisy ignored dependency warnings (#81) * v2.0.0-rc.2 (#82) --------- Co-authored-by: Terry Lewis <[email protected]>
1 parent aed02fc commit e517276

12 files changed

+225
-12
lines changed

package-lock.json

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

package.json

+2-1
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": "1.2.1",
4+
"version": "2.0.0-rc.2",
55
"main": "./src/Injector",
66
"scripts": {
77
"lint": "eslint .",
@@ -54,6 +54,7 @@
5454
"lodash.bindall": "^4.4.0",
5555
"lodash.compact": "^3.0.1",
5656
"lodash.foreach": "^4.5.0",
57+
"lodash.get": "^4.4.2",
5758
"lodash.isfunction": "^3.0.9",
5859
"lodash.isobject": "^3.0.2",
5960
"lodash.keys": "^4.2.0",

src/ContainerManagement.js

+34-5
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,60 @@
11
const _forEach = require('lodash.foreach');
2+
const _get = require('lodash.get');
3+
const _isFunction = require('lodash.isfunction');
4+
const _isObject = require('lodash.isobject');
25
const Dependency = require('./Dependency');
36

47
const rall = /.+/;
58

69
module.exports = {
710

8-
warnIfNeeded(name) {
11+
getDependencySourceHint(dependency) {
12+
if (_isFunction(dependency)) {
13+
return _get(dependency, 'name') || '<anonymous function>';
14+
}
15+
16+
if (_isObject(dependency)) {
17+
return _get(dependency, 'constructor.name') || '<object>';
18+
}
19+
20+
return `<${typeof dependency}>`;
21+
},
22+
23+
warnOverrideIfNeeded(name, dependency) {
924
if (this.hasDependency(name)) {
10-
this.logger.warn(`warning: ${name} dependency is being overwritten in ${this.name} injector`);
25+
const hint = this.getDependencySourceHint(dependency);
26+
this.logger.warn(`warning: ${name} (${hint}) dependency is being overwritten in ${this.name} injector`);
1127
}
1228
},
1329

1430
addResolvableDependency(name, dependency, suppressWarning = false) {
31+
if (this.shouldIgnoreDependency(dependency)) {
32+
return this;
33+
}
1534
if (!suppressWarning) {
16-
this.warnIfNeeded(name);
35+
this.warnOverrideIfNeeded(name, dependency);
1736
}
1837
this.dependencies[name] = Dependency.resolvableDependency(name, dependency);
1938
return this;
2039
},
2140

2241
addDependency(name, dependency, suppressWarning = false) {
42+
if (this.shouldIgnoreDependency(dependency)) {
43+
return this;
44+
}
2345
if (!suppressWarning) {
24-
this.warnIfNeeded(name);
46+
this.warnOverrideIfNeeded(name, dependency);
2547
}
2648
this.dependencies[name] = Dependency.dependency(name, dependency);
2749
return this;
2850
},
2951

3052
addConstructedDependency(name, dependency, suppressWarning = false) {
53+
if (this.shouldIgnoreDependency(dependency)) {
54+
return this;
55+
}
3156
if (!suppressWarning) {
32-
this.warnIfNeeded(name);
57+
this.warnOverrideIfNeeded(name, dependency);
3358
}
3459
this.dependencies[name] = dependency;
3560
return this;
@@ -48,6 +73,10 @@ module.exports = {
4873
return !!this.dependencies[name];
4974
},
5075

76+
shouldIgnoreDependency(dependency) {
77+
return Boolean(_get(dependency, 'spurIocIgnore', false));
78+
},
79+
5180
merge(otherInjector, suppressWarning = false) {
5281
const dependencies = otherInjector.dependencies;
5382

src/FileFilterExpression.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
The addition of ts (typescript) file registration is only meant to allow the
3+
registration of the file itself. It doesn't guarantee full compilation but it
4+
expects that you have that handled with the use of something like on your end.
5+
6+
TypeScript is not officially supported, but will be available through a
7+
beta/release candidate version.
8+
*/
9+
10+
const expression = /^(?!.*\.d\.ts$)([^\.].*)\.(js|json|ts)?$$/;
11+
12+
module.exports = expression;

src/RegistrationManagement.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const _forEach = require('lodash.foreach');
44
const _isFunction = require('lodash.isfunction');
55
const _isObject = require('lodash.isobject');
66

7-
const rfileFilter = /(.+)\.(js|json)$/;
7+
const fileFilterExpression = require('./FileFilterExpression');
88

99
const hasOwnProp = function (source, propertyName) {
1010
return Object.prototype.hasOwnProperty.call(source, propertyName);
@@ -15,7 +15,7 @@ module.exports = {
1515
const dirname = path.resolve(rootDir, dir);
1616
const libs = requireAll({
1717
dirname,
18-
filter: rfileFilter
18+
filter: fileFilterExpression
1919
});
2020
this.registerLibMap(libs);
2121
return this;

test/fixtures/Fence.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = function () {
2+
return 'Fence';
3+
};

test/fixtures/Wall.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = function () {
2+
return 'Wall';
3+
};

test/fixtures/sub/Fence.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = function () {
2+
return 'Fence ignored';
3+
};
4+
5+
module.exports.spurIocIgnore = true;

test/fixtures/sub/Wall.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = function () {
2+
return 'Wall override';
3+
};
4+
5+
module.exports.spurIocIgnore = false;

test/unit/ContainerSpec.js

+34
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,38 @@ describe('injector - Container Management', () => {
6060
}))
6161
.to.throw('Resolver encountered errors');
6262
});
63+
64+
describe('ignored dependencies', () => {
65+
const initialDep = function () {
66+
return 'initial';
67+
};
68+
69+
const ignoredDep = function() {
70+
throw new Error('this should not be called');
71+
return 'ignored';
72+
};
73+
ignoredDep.spurIocIgnore = true;
74+
75+
const replacementDep = function () {
76+
return 'updated';
77+
};
78+
79+
it('ignores registered dependencies which have spurIocIgnore=true', function () {
80+
this.injector.addDependency('a', initialDep);
81+
this.injector.addDependency('a', ignoredDep);
82+
83+
const dep = this.injector.getDependency('a');
84+
expect(dep.name).to.deep.equal('a');
85+
expect(dep.instance).to.be.eq(initialDep);
86+
});
87+
88+
it('overrides registered dependencies which have spurIocIgnore=false', function() {
89+
this.injector.addDependency('a', initialDep);
90+
this.injector.addDependency('a', replacementDep);
91+
92+
const dep = this.injector.getDependency('a');
93+
expect(dep.name).to.equal('a');
94+
expect(dep.instance).to.be.eq(replacementDep);
95+
});
96+
});
6397
});

test/unit/FileFilterExpressionSpec.js

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
const subject = require('../../src/FileFilterExpression');
2+
3+
describe('FileFilterExpression tests', function () {
4+
5+
it('should match a js file path', () => {
6+
const path1 = 'src/some/path/FileFilterExpression.js';
7+
const path2 = 'src\\somepath\\FileFilterExpression.js';
8+
9+
expect(subject.test(path1)).to.be.true;
10+
expect(subject.test(path2)).to.be.true;
11+
});
12+
13+
it('should match a json file path', () => {
14+
const path1 = 'src/some/path/FileFilterExpression.json';
15+
const path2 = 'src\\somepath\\FileFilterExpression.json';
16+
17+
expect(subject.test(path1)).to.be.true;
18+
expect(subject.test(path2)).to.be.true;
19+
});
20+
21+
it('should match a ts file path', () => {
22+
const path1 = 'src/some/path/FileFilterExpression.ts';
23+
const path2 = 'src\\somepath\\FileFilterExpression.ts';
24+
25+
expect(subject.test(path1)).to.be.true;
26+
expect(subject.test(path2)).to.be.true;
27+
});
28+
29+
it('should match a d.ts file path', () => {
30+
const path1 = 'src/some/path/FileFilterExpression.d.ts';
31+
const path2 = 'src\\somepath\\FileFilterExpression.d.ts';
32+
33+
expect(subject.test(path1)).to.be.false;
34+
expect(subject.test(path2)).to.be.false;
35+
});
36+
37+
it('should not match partial matches', () => {
38+
const path1 = 'src/some/path/FileFilterExpression.js2';
39+
const path2 = 'src/some/path/FileFilterExpression.json2';
40+
const path3 = 'src/some/path/FileFilterExpression.ts2';
41+
42+
expect(subject.test(path1)).to.be.false;
43+
expect(subject.test(path2)).to.be.false;
44+
expect(subject.test(path3)).to.be.false;
45+
});
46+
47+
});

test/unit/InjectorSpec.js

+74
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,80 @@ describe('Injector', () => {
107107
this.injector.inject(function (_, chai, $injector, foo) {});
108108
});
109109

110+
describe('ignored dependencies', () => {
111+
const initialDep = function () {
112+
return 'initial';
113+
};
114+
115+
const ignoredDep = function() {
116+
throw new Error('this should not be called');
117+
return 'ignored';
118+
};
119+
ignoredDep.spurIocIgnore = true;
120+
121+
const replacementDep = function () {
122+
return 'updated';
123+
};
124+
125+
describe('spurIocIgnore=true', () => {
126+
it('ignores registered dependencies which have spurIocIgnore=true', function () {
127+
this.injector.registerDependencies({ a: initialDep, });
128+
this.injector.registerDependencies({ a: ignoredDep });
129+
130+
this.injector.inject(function (a) {
131+
expect(a).to.deep.equal(initialDep);
132+
expect(a()).to.be.eq('initial');
133+
});
134+
});
135+
136+
it('ignores registered folder dependencies which have spurIocIgnore=true', function() {
137+
this.injector.registerFolders(__dirname, ['../fixtures']);
138+
139+
this.injector.inject(function (Wall) {
140+
expect(Wall).to.equal('Wall override');
141+
});
142+
});
143+
144+
it('ignores resolvable dependencies which have spurIocIgnore=true', function() {
145+
this.injector.addResolvableDependency('b', initialDep);
146+
this.injector.addResolvableDependency('b', ignoredDep);
147+
148+
this.injector.inject(function ($injector) {
149+
expect($injector.get('b')).to.equal('initial');
150+
});
151+
});
152+
});
153+
154+
describe('explicitly marked not to be ignored', () => {
155+
it('overrides registered dependencies which have spurIocIgnore=false', function() {
156+
this.injector.registerDependencies({ a: initialDep, });
157+
this.injector.registerDependencies({ a: replacementDep });
158+
159+
this.injector.inject(function (a) {
160+
expect(a).to.equal(replacementDep);
161+
expect(a()).to.be.eq('updated');
162+
});
163+
});
164+
165+
it('overrides registered folder dependencies which have spurIocIgnore=false', function() {
166+
this.injector.registerFolders(__dirname, ['../fixtures']);
167+
168+
this.injector.inject(function (Wall) {
169+
expect(Wall).to.equal('Wall override');
170+
});
171+
});
172+
173+
it('overrides resolvable dependencies which have spurIocIgnore=false', function() {
174+
this.injector.addResolvableDependency('b', initialDep);
175+
this.injector.addResolvableDependency('b', replacementDep);
176+
177+
this.injector.inject(function ($injector) {
178+
expect($injector.get('b')).to.equal('updated');
179+
});
180+
});
181+
});
182+
});
183+
110184
describe('expose and link', () => {
111185
beforeEach(function () {
112186
this.injector.registerDependencies({

0 commit comments

Comments
 (0)