From b048826d27712b1dbd9abc19ee4d0a58cdeabb28 Mon Sep 17 00:00:00 2001 From: Jack Ellis Date: Sat, 3 Feb 2018 09:22:55 +0000 Subject: [PATCH] feat: strict mode --- README.md | 3 +++ changelog.md | 1 + spec/install.spec.js | 19 +++++++++++++++++++ src/base.js | 3 +++ src/install.js | 15 +++++++++++++-- 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 237e8a3..f87f757 100644 --- a/README.md +++ b/README.md @@ -226,6 +226,9 @@ let injector2 = injector.spawn(); ``` By default this will create a brand new injector, but if you want to share registered services/factories between the two, pass `true` into the function. This will create a new injector that *inherits* the previous one. Any factories registered on the first injector will be available to the second, but not vice versa. +#### strict +If set to `false` then all dependencies will be made optional. If a component's dependency cannot be found, rather than throwing an error it will just be set to `undefined`. Not that this does not affect the `get` function. + ### Lifecycle When registering a factory or service, it's possible to determine the lifecycle. *As of v0.4, the default lifecycle is set to `class`*. diff --git a/changelog.md b/changelog.md index 56bf653..f682fbd 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,7 @@ ## 2.0.0 - Injecting components/mixins/directives is now optional - There is now a default merging strategy for when using mixins with dependencies +- Added a `injector.strict` option which makes all dependencies optional. Note this doesn't affect `injector.get` ## 1.0.0 - Upgraded to Jpex 2.0.0 diff --git a/spec/install.spec.js b/spec/install.spec.js index ad7ce1b..1c244ee 100644 --- a/spec/install.spec.js +++ b/spec/install.spec.js @@ -136,3 +136,22 @@ test('sets option merging strategies', function (t) { t.deepEqual(merged, [ 'apple', { banana: 'b'}]); }); + +// strict +test('strict throws when a dep is not found', function (t) { + let {injector, vue} = t.context; + + vue.dependencies = 'foofactory'; + + t.throws(() => vue.use(injector)); + t.throws(() => injector.get('foofactory')); +}); +test('non-strict does not throw for missing deps', function (t) { + let {injector, vue} = t.context; + + vue.dependencies = 'foofactory'; + injector.strict = false; + + t.notThrows(() => vue.use(injector)); + t.throws(() => injector.get('foofactory')); +}); diff --git a/src/base.js b/src/base.js index 19a61b4..05c5a0c 100644 --- a/src/base.js +++ b/src/base.js @@ -34,5 +34,8 @@ Base.spawn = function (extend) { } }; +// Allow setting a soft mode +Base.strict = true; + // Install method used by Vue.use Base.install = install; diff --git a/src/install.js b/src/install.js index fe28e92..7fcad58 100644 --- a/src/install.js +++ b/src/install.js @@ -3,6 +3,17 @@ module.exports = function (Vue, options) { var self = this; var $typeof = this.$resolve('$typeof'); + var strict = this.strict; + + function fixName(name) { + if (strict) { + return name; + } + if (name.charAt(0) === '_' && name.substr(name.length -1) === '_') { + return name; + } + return '_' + name + '_'; + } function setProperty(target, name, value) { Object.defineProperty(target, name, { @@ -22,7 +33,7 @@ module.exports = function (Vue, options) { .forEach(function (dependency) { switch ($typeof(dependency)){ case 'string': // resolve dependency and attach to the same-named property - setProperty(target, dependency, self.$resolve(dependency, named)); + setProperty(target, dependency, self.$resolve(fixName(dependency), named)); break; case 'object': // resolve each property and use the key as the property name // Aliases @@ -30,7 +41,7 @@ module.exports = function (Vue, options) { .forEach(function (key) { var value = dependency[key]; if ($typeof(value) === 'string'){ - setProperty(target, key, self.$resolve(value, named)); + setProperty(target, key, self.$resolve(fixName(value), named)); } }); break;