{"_id":"@6pm/depend","_rev":"1-f2faa41fe098381f4e1540ee34845f38","name":"@6pm/depend","description":"Decorator based dependency injection","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@6pm/depend","version":"1.0.0","author":{"name":"James Andrews","email":"jka6502@gmail.com"},"description":"Decorator based dependency injection","keywords":["dependency","injection","decouple","decorator"],"main":"lib/depend.js","scripts":{"test":"mocha --compilers js:babel-register test/**/*.spec.js","cover":"nyc --reporter=html --reporter=text-summary npm test","coverage":"nyc npm test >/dev/null && nyc --reporter=text-lcov report | coveralls"},"engines":{"node":">=6"},"dependencies":{"@6pm/emit":"^1.0.0"},"devDependencies":{"babel-core":"^6.26.0","babel-plugin-source-map-support-for-6":"0.0.5","babel-plugin-transform-class-properties":"^6.24.1","babel-plugin-transform-decorators-legacy":"^1.3.4","babel-plugin-transform-es2015-modules-umd":"^6.24.1","coveralls":"^2.13.1","mocha":"^3.5.0","nyc":"^11.2.0","should":"^13.0.0"},"directories":{"test":"test"},"repository":{"type":"git","url":"git+https://github.com/6pm-js/depend.git"},"nyc":{"require":["babel-register"],"sourceMap":true,"instrument":true},"license":"MIT","gitHead":"571a87cde284951f2c5934c2e61edf36a717fdc9","bugs":{"url":"https://github.com/6pm-js/depend/issues"},"homepage":"https://github.com/6pm-js/depend#readme","_id":"@6pm/depend@1.0.0","_npmVersion":"5.4.0","_nodeVersion":"8.4.0","_npmUser":{"name":"6pm","email":"jka6510@gmail.com"},"dist":{"integrity":"sha512-SVuaueCtEMLkz7kTVkmbaqUWJxA+XLq/k8dzhACKMuh/rvD9ALfCrB9s2W7OZNfYfhxsuvgY/faw7JnpV4HWtA==","shasum":"5d66d3c596d22f8c862334e738d20e018e9d71a0","tarball":"https://registry.npmjs.org/@6pm/depend/-/depend-1.0.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID8o2P8av7xmmqRVuPqeCmtQapKMRCISIkW0xHNf5dF6AiBmKzWNEomTB7rjefr4CG0BjUMLfqj3eHVPNT08+A1Oxg=="}]},"maintainers":[{"name":"6pm","email":"jka6510@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/depend-1.0.0.tgz_1504641483637_0.2966283611021936"}}},"readme":"# @6pm/depend\r\n\r\n[![npm version](https://badge.fury.io/js/%406pm%2Fdepend.svg)](https://badge.fury.io/js/%406pm%2Fdepend) [![dependencies Status](https://david-dm.org/6pm-js/depend/status.svg)](https://david-dm.org/6pm-js/depend) [![Build Status](https://travis-ci.org/6pm-js/depend.svg?branch=master)](https://travis-ci.org/6pm-js/depend) [![Coverage Status](https://coveralls.io/repos/github/6pm-js/depend/badge.svg?branch=master)](https://coveralls.io/github/6pm-js/depend?branch=master)\r\n\r\nDeclarative dependency injection.\r\n\r\n\r\n## Table of contents\r\n\r\n- [Install](#install)\r\n- [Test](#test)\r\n- [Usage](#usage)\r\n\t- [Declarative vs imperative](#declarative-vs-imperative)\r\n\t- [Declaring dependencies](#declaring-dependencies)\r\n \t- [Creating instances, and satisfying dependencies](#creating-instances-and-satisfying-dependencies)\r\n\t- [Runtime determination of concrete implementations](#runtime-determination-of-concrete-implementations)\r\n\t- [Post injection intialisation](#post-injection-intialisation)\r\n\t- [Inheritance](#inheritance)\r\n\t- [As Promised](#as-promised)\r\n\t\t- [Downstream dependencies as Promises](#downstream-dependencies-as-promises)\r\n\t- [Singletons](#singletons)\r\n\t- [Destructured injection](#destructured-injection)\r\n- [Cyclic dependencies](#cyclic-dependencies)\r\n- [Performance](#performance)\r\n- [Contributing](#contributing)\r\n\r\n\r\n## Install\r\n\r\n```sh\r\nnpm install @6pm/depend --save\r\n```\r\n\r\n\r\n## Test\r\n\r\nTo run the unit test suite.\r\n\r\n```sh\r\ngit clone https://github.com/6pm-js/depend.git\r\ncd depend\r\nnpm install\r\nnpm test\r\n```\r\n\r\nTo run [nyc](https://github.com/istanbuljs/nyc) coverage tests.\r\n\r\n```sh\r\ngit clone https://github.com/6pm-js/depend.git\r\ncd depend\r\nnpm install\r\nnpm run cover\r\n```\r\n\r\nThis will result in a textual summary display, and a detailed html coverage\r\nreport created in `/coverage`.\r\n\r\n\r\n## Usage\r\n\r\nUsage requires two distinct components, declaration of dependencies and\r\ninjection points - and runtime binding of concrete implementations, and creation\r\nof instances / satisfying of dependencies.\r\n\r\n\r\n### Declarative vs imperative\r\n\r\nWhy support two non-standard ES extensions?  Both class properties, and\r\ndecorators are in a state of flux, not yet stable in any upcoming ES spec\r\n(at the time of writing), but there are available implementations that work, and\r\nthere is something eminently readable about declarative approaches.\r\n\r\nThe imperative mechanism allows backwards compatible integration with existing\r\nlibraries, or the *safer* path, if desired - but the declarative approach is\r\na personal preference, as I find it considerably less surprising, and more\r\nexplicit about intent.\r\n\r\nThere is no need to intrument to allow the declarative, decorator approach,\r\nunless you intend to use it within your project, and no capability is unique\r\nto either approach - choose whichever you are comfortable with.\r\n\r\nIn order to use the declarative approach (at the time of writing), two\r\ntransforms are needed, via Babel transpilation:\r\n\r\n- [transform-decorators-legacy](https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy)\r\n- [transform-class-properties](https://www.npmjs.com/package/babel-plugin-transform-class-properties)\r\n\r\n\r\n### Declaring dependencies\r\n\r\nDependencies are declared using either the declarative decorator syntax:\r\n\r\n```js\r\nimport { Inject } from '@6pm/depend';\r\nimport { InjectedType } from 'wherever'\r\n\r\nclass SomeClass {\r\n\r\n\t@Inject(InjectedType)\r\n\tproperty = null;\r\n\r\n}\r\n```\r\n\r\nor imperative syntax:\r\n\r\n```js\r\nimport { Depend } from '@6pm/depend';\r\nimport { InjectedType } from 'wherever'\r\n\r\nclass SomeClass {}\r\n\r\nDepend.inject(SomeClass, 'property', InjectedType);\r\n```\r\n\r\nDependencies can be attached to the whole class, in which case they apply to the\r\nconstructor function, supplying the parameters to it, when created via a\r\n`Container`:\r\n\r\n```js\r\nimport { Inject, Depend } from '@6pm/depend';\r\nimport { InjectedTypeA, InjectedTypeB } from 'wherever'\r\n\r\n// Declarative approach\r\n@Inject(InjectedType, InjectedTypeB)\r\nclass SomeClass1 {\r\n\r\n\tconstructor(injectedInstanceA, injectedInstanceB) {}\r\n\r\n}\r\n\r\n\r\n// Imperative approach\r\nclass SomeClass2 {\r\n\r\n\tconstructor(injectedInstanceA, injectedInstanceB) {}\r\n\r\n}\r\nDepend.inject(SomeClass, null, InjectedTypeA, InjectedTypeB);\r\n// The ^null is important, it specifies that we're not targeting a property of\r\n// SomeClass2, but the constructor.\r\n```\r\n\r\nThe legacy decorator plugin, for Babel, does not allow decoration of\r\nconstructors directly - which is why the declarative approach must decorate the\r\nclass, rather than the actual `constructor` function.\r\n\r\nDependencies can also be injected directly into class methods, which are treated\r\nas setter functions:\r\n\r\n```js\r\nimport { Inject, Depend } from '@6pm/depend';\r\nimport { DatabaseAbstraction } from './database.js'\r\n\r\n// Declarative approach\r\nclass SomeClass1 {\r\n\r\n\t@Inject(DatabaseAbstraction)\r\n\tsetDatabaseAbstraction(dbAPI) {}\r\n}\r\n\r\n\r\n// Imperative approach\r\nclass SomeClass2 {\r\n\r\n\tsetDatabaseAbstraction(dbAPI) {}\r\n\r\n}\r\nDepend.inject(SomeClass, 'setDatabaseAbstraction', DatabaseAbstraction);\r\n```\r\n\r\n\r\n### Creating instances, and satisfying dependencies\r\n\r\nOnce a class is declared as managed by depend, it should not be manually\r\ninstantiated with `new`, but instead created via a managed `Container`.  The\r\n`Container` ensures that any dependencies declared are satisified, including\r\nsub-dependencies before returning an instance.\r\n\r\n```js\r\nimport { Inject, Container } from '@6pm/depend';\r\nimport { DatabaseAbstraction } from './database.js'\r\n\r\n@Inject(DatabaseAbstraction)\r\nclass SomeClass {\r\n\r\n\tconstructor(databaseAbstraction) {\r\n\t\t// This will be called prior to create, below, completing.\r\n\t}\r\n\r\n}\r\n\r\n// A new instance of DatabaseAbstraction will be created, and provided to the\r\n// SomeClass constructor, prior to the new SomeClass instance being returned.\r\nlet instance = new Container().create(SomeClass);\r\n```\r\n\r\n\r\n### Runtime determination of concrete implementations\r\n\r\nThe `Container` class does much more than just create instances, and satisfy\r\ndependencies - it can also be used to specify alternate implementations to use\r\nat runtime, when a particular dependency type is encountered.\r\n\r\nThis is achieved using the `.bind()` method on the `Container` instance.\r\n\r\n```js\r\nimport { Inject, Container } from '@6pm/depend';\r\nimport { DatabaseAbstraction } from './database.js'\r\nimport { DatabaseMySQL } from './database-mysql.js'\r\n\r\n@Inject(DatabaseAbstraction)\r\nclass SomeClass {\r\n\r\n\tconstructor(databaseAbstraction) {\r\n\t\t// This will be called prior to create, below, completing.\r\n\t}\r\n\r\n}\r\n\r\n// A new instance of DatabaseMySQL will be created, and provided to the\r\n// SomeClass constructor, prior to the new SomeClass instance being returned.\r\nlet instance = new Container()\r\n\t.bind(DatabaseAbstraction, DatabaseMySQL)\r\n\t.create(SomeClass);\r\n```\r\n\r\n\r\n### Post injection intialisation\r\n\r\nA single function per class may be marked as an `init` function, which will be\r\nexecuted after all dependency injection has been completed on a new instance of\r\nthe owning class, like so:\r\n\r\n```js\r\nimport { Init } from '@6pm/depend';\r\n\r\nclass SomeClass {\r\n\r\n\t@Init\r\n\tsomeInitFunction() {\r\n\t\t// This will only execute once a Container.created instance of SomeClass\r\n\t\t// has been fully created, and all dependencies injected.\r\n\t}\r\n\r\n}\r\n```\r\n\r\nor, imperatively:\r\n\r\n```js\r\nimport { Depend } from '@6pm/depend';\r\n\r\nclass SomeClass {\r\n\r\n\tsomeInitFunction() {\r\n\t\t// This will only execute once a Container.created instance of SomeClass\r\n\t\t// has been fully created, and all dependencies injected.\r\n\t}\r\n\r\n}\r\n\r\nDepend.init(SomeClass, 'someInitFunction');\r\n```\r\n\r\n\r\n### Inheritance\r\n\r\nDependencies are inherited using the ES2016 class format, or traditional\r\nprototypical inheritance.  So extending a managed class automatically confers\r\nall requirements, and determines overloaded requirements, too.\r\n\r\n```js\r\nclass A {\r\n\r\n\t@Inject(SomeType)\r\n\tproperty;\r\n\r\n}\r\n\r\nclass B extends A {}\r\n\r\nclass C extends A {\r\n\r\n\t@Inject(AlternativeType)\r\n\tproperty;\r\n\r\n}\r\n```\r\n\r\nIn the above example, creating an instance of `B` will inject `SomeType` into\r\n`property`, as an inherited requirement.  Creating an instance `C` will inject\r\nan instance of `AlternativeType`, instead, without requiring, or creating an\r\ninstance of `SomeType` first.\r\n\r\n\r\n### Typical phases of a dependency injected application\r\n\r\nThe phases of a dependency injected application are typically:\r\n\r\n- Declaration of intent / dependencies\r\n\t- Using `@Inject`, `@Abstract` and `@Singleton` to declare intent, and requirements.\r\n\t- This typically occurs throughout the application, where ever components reside.\r\n\r\n- Configuration / binding\r\n\t- Creating a `Container` instance, and binding concrete implementations\r\n\t- This typically occurs in a single *setup* file that applies configuration\r\n\tfor a given environment.\r\n\r\n- Runtime usage\r\n\t- Wherever new instances are required, the `Container` instance created in\r\n\tthe configuration / binding step is used to create new instances, and\r\n\tautomatically satisfy any required dependencies.\r\n\r\nAs an example:\r\n\r\n- Declaration:\r\n\r\n`./service.js`;\r\n```js\r\nimport { Inject, Singleton } from '@6pm/depend';\r\n\r\nclass Service {\r\n\r\n\t@Inject(Logger)\r\n\tlogger;\r\n\r\n\tstart() {\r\n\t\tlogger.log('Started!');\r\n\t}\r\n}\r\n```\r\n\r\n`./interface/someLogger.js`;\r\n```js\r\nclass Logger {\r\n\r\n\t@Abstract\r\n\tlog(message) {}\r\n\r\n}\r\n```\r\n\r\n`./implementation/console-logger.js`;\r\n```js\r\nclass ConcreteConsoleLogger {\r\n\r\n\tlog(message) {\r\n\t\tconsole.log(message);\r\n\t}\r\n\r\n}\r\n```\r\n\r\n- Configuration / binding\r\n\r\n`./configuration/container.js`\r\n``` js\r\nimport { Container } from '@6pm/depend';\r\n\r\nimport Logger from './interface/logger';\r\nimport ConcreteLogger from './implementationconsole-logger';\r\n\r\nfunction configure() {\r\n\tlet container = new Container();\r\n\r\n\tcontainer.bind(Logger, ConcreteLogger);\r\n\r\n\treturn container;\r\n}\r\n\r\nexport let container = configure();\r\n```\r\n\r\n- Runtime usage:\r\n\r\n`main.js`\r\n```js\r\nimport Service from './service.js';\r\nimport container from './configuration/container.js';\r\n\r\nlet service = container.create(Service);\r\nservice.start();\r\n```\r\n\r\n\r\n### As Promised\r\n\r\nSome dependencies cannot be ready for injection until they have accessed remote\r\nresources, whether to obtain configuration, or connections, resources, etc.\r\n\r\nIn order to facilitate this, without introducing surprising levels of variance\r\nin return types, `Promise`s may be returned from three key points within the\r\ndependency injection lifecycle:\r\n\r\n- constructor\r\n- injected property setter\r\n- init\r\n\r\nIf any of the above methods return a `Promise` then `container.create` will also\r\nreturn a `Promise` that resolves to the new instance if, and only if any and\r\nall `Promise`s returned resolve successfully - or reject on the first that\r\nrejects.\r\n\r\nIf all three (or any combination) of the above methods return `Promise`s, then\r\nthey are guaranteed to resolve in the oder listed above, and reject in the same\r\norder.\r\n\r\nIf multiple injected setters are declared on a single class, and return multiple\r\n`Promise`s, then they will occur, effectively, simultaneously, with no order\r\nguarantees between them, but they will be sychronised using `Promise.all` prior\r\nto an `init` function being executed.\r\n\r\n\r\n#### Downstream dependencies as Promises\r\n\r\nIn order to:\r\n\r\n1. Prevent surprise (and cascading requirements to handle Promises)\r\n2. Ensure control flow options remain the preserve of the application developer\r\n\r\nDownstream dependencies that return `Promise`s *DO NOT* automatically promote\r\nan upstream type to a `Promise`.\r\n\r\nThat is, if, say, class `A` declares a dependency injection of an instance of\r\nclass `B`, and `B` is a `Promise`, creating an instance of `A` will not result\r\nin a `Promise`, unless it explicitly returns a `Promise` as described in the\r\nprevious section.\r\n\r\nAs mentioned above, this prevents surprise (concrete implementation `C` is\r\nbound as runtime configuration, and resolves to a `Promise`, where `B` did not),\r\nand ensures that the application programmer can choose how to handle such a\r\nsituation - the dependency injected instance of `A` may not need the downstream\r\ndependency to be resolved from a `Promise` prior to being created -\r\nautomatically doing so would create an automatic synchronicity between steps,\r\npreventing, say, the ability to handle resolving of a `Promise`, and triggering\r\nof any further logic as a consequence, asynchronously.\r\n\r\nHandling of such downstream dependencies is therefore left as an exercise to the\r\napplication developer, and any injected dependencies that resolve to a `Promise`\r\nwill merely deliver the `Promise` - if dependency injection should wait for\r\nresolution of a `Promise`d dependency, that can cascaded manually, by returning\r\na `Promise` from any of the previously mentioned lifecycle methods, or, using\r\n`async` / `await` syntax, if available, like so:\r\n\r\n```js\r\n\r\nimport { Inject, Container } from '@6pm/depend';\r\nimport { DatabaseAbstraction } from './database.js'\r\n\r\n@Inject(DatabaseAbstraction)\r\nclass SomeService {\r\n\r\n\tasync constructor(databaseAbstraction) {\r\n\t\tthis.db = await databaseAbstraction;\r\n\t\treturn this;\r\n\t}\r\n\r\n\t@Init\r\n\tinit() {\r\n\t\t// This method will only be called if the construction succeeded, and\r\n\t\t// the `.db` property has successfully resolved, and is available.\r\n\t}\r\n\r\n}\r\n\r\n\r\nasync function startService() {\r\n\ttry{\r\n\t\tlet someService = await new Container()\r\n\t\t\t// .bind() any runtime configuration here\r\n\t\t\t.create(SomeService);\r\n\r\n\t\t// someService will now exist, with a fully resolved `.db` property.\r\n\t\tsomeService.start();\r\n\r\n\t}catch(e) {\r\n\t\t// someService failed to instantiate, the causal error (from\r\n\t\t// DatabaseAbstraction, or the bound concrete implementation, thereof),\r\n\t\t// will be caught here.\r\n\t}\r\n}\r\n\r\nstartService();\r\n\r\n// Alternatively, using the raw `Promise` flow.\r\nnew Container()\r\n\t// .bind() any runtime configuration here\r\n\t.create(SomeService)\r\n\t.then(function(someService) {\r\n\t\t// Fully resolved `someService` instance now available to use, with a\r\n\t\t// resolved `.db` property.\r\n\t\tsomeService.start();\r\n\t}).catch(function(error) {\r\n\t\t// If the `DatabaseAbstraction` rejects for some reason, `someService`\r\n\t\t// instantiation will fail, calling this function with the causal Error.\r\n\t});\r\n```\r\n\r\n\r\n### Singletons\r\n\r\nIn addition to supplying instances of types, and binding them dynamically at\r\nruntime, certain classes may be designed to be shared, requiring one, and only\r\none instance, which should to be passed to any declared dependency.  This can\r\nbe achieved by declaring a class as a singleton, using either a declarative\r\ndecorator, or imperative style.\r\n\r\n```js\r\nimport { Singleton, Depend } from '@6pm/depend';\r\n\r\n@Singleton\r\nclass A {}\r\n\r\nclass B {}\r\nDepend.singleton(B);\r\n```\r\n\r\nAny class declaring a dependency of `A`, or `B` will only instantiate a single\r\ninstance, and all will receive that single instance.\r\n\r\nThis is particularly useful for injecting common implementations, such as a\r\ndatastore abstraction (that, say, handles connection pooling under the hood), or\r\na configured logging interface, or arbitration mechanism for contentious\r\nresources, common application configuration, etc.\r\n\r\n\r\n## Interfaces in a language without interfaces\r\n\r\nJavaScript does not have any real concept of interfaces, so the depend library\r\nprovides a mechanism to allow an effective approximation of the concept.\r\n\r\nMethods, or entire classes, can be declared as abstract via the decorator or\r\nimperative approach, as so:\r\n\r\n```js\r\nimport { Abstract, Depend } from '@6pm/depend';\r\n\r\n@Abstract\r\nclass A {}\r\n\r\nclass B {\r\n\r\n\t@Abstract\r\n\tsomeMethod() {}\r\n\r\n}\r\n\r\nclass C {}\r\nDepend.abstract(C);\r\n```\r\n\r\nThe abstract property is automatically conferred to the owning class, if a method\r\nis declared abstract, and has the following effects:\r\n\r\n- *For methods* - any attempt to invoke the method will throw an `Error` that the\r\nmethod is abstract, and should be overloaded in a subclass.\r\n\r\n- *For classes* - any attempt to `create` an instance of the class, via a container,\r\nwill throw an `Error` indicating that the class is abstract, and a concrete\r\nextension of the class should be used instead.\r\n\r\nWhile the depend library, and JavaScript do not validate that the contract of\r\nan interface is honoured, this adds a degree of safety, as a failure to `bind` a\r\nconcrete implementation will result in the creation of a new instance failing,\r\nshould an abstract class be requested at any stage as a dependency - which\r\nensures fast failure, at startup - and the potential to catch an erroneous\r\nconfiguration during an integration test of production configuration.\r\n\r\n\r\n### Destructured injection\r\n\r\nIn addition to specifying types to be resolved during dependency injection, the\r\ndepend library can accept a limited form of destructured assignment, providing\r\nmore complex structures, such as array literals, and object literals, like so:\r\n\r\n```js\r\n@Inject({ database: DatabaseAbstraction, logger: LoggerAbstraction })\r\nclass SomeClass {\r\n\r\n\tconstructor(options) {\r\n\t\tthis.database = options.database;\r\n\t\tthis.logger = options.logger;\r\n\t}\r\n\r\n}\r\n```\r\n\r\nAny depth of array and object literal definitions will be traversed and injected\r\nas needed - which works particularly well with ES2016 destructured assignment:\r\n\r\n```js\r\n@Inject([ { sub: A }, [ B, C ] ])\r\nclass SomeClass {\r\n\r\n\tconstructor([ { sub:a }, [ b, c ] ]) {\r\n\t\t// a, b and c receive instances of A, B and C respectively.\r\n\t}\r\n\r\n}\r\n```\r\n\r\n\r\n## Cyclic dependencies\r\n\r\nThe depend library automatically determines if dependencies cause cycles, both\r\nat the point of declaration of dependencies, and when binding concrete\r\nimplementations, and will throw if such a situation occurs - since cyclical\r\ndependencies can never be correctly satisfied.\r\n\r\nIf `A` requires an instance of `B`, that then requires and instance of `C`,\r\nthat then requires `A`, there is no way to determine a *satisfied* state for\r\nany instance along the cyclical chain.\r\n\r\nIf a cycle is detected, an `Error` is thrown from either the dependency\r\ndeclaration (the `@Inject` or `Depend.inject), or the `bind` call that causes\r\nthe cycle.\r\n\r\n\r\n## Performance\r\n\r\nThe depend library is designed to be very performant, using two primary methods:\r\n\r\n- Front loading as much work as possible, to ensure that creating, and satisfying\r\nnew instances is as cheap as possible.  In particular, cycle detection occurs\r\nduring the declaration of dependencies, and the container binding stage -\r\nensuring that the cost does not affect run time performance, and usage patterns.\r\n\r\n- Dynamic code generation, to allow the ES runtime / compiler to optimise away\r\nas much work as possible - while a contentious technique, this is never visible\r\nexternally, but testing during development, (via microbenchmarks - YMMV), proved\r\nto provide more than 3 orders of magnitude difference in instance creation.\r\n\r\nIn addition, the dynamic code generation, on v8 in particular, adds very\r\nlittle startup overhead.\r\n\r\n\r\n## Contributing\r\n\r\nAll issues, requests, questions, PRs, improvements, or merely comments welcome!\r\nAll I ask is to attempt to conform to the rather loose house style, if opening a\r\npull request!\r\n","maintainers":[{"name":"6pm","email":"jka6510@gmail.com"}],"time":{"modified":"2022-04-04T10:48:55.287Z","created":"2017-09-05T19:58:04.711Z","1.0.0":"2017-09-05T19:58:04.711Z"},"homepage":"https://github.com/6pm-js/depend#readme","keywords":["dependency","injection","decouple","decorator"],"repository":{"type":"git","url":"git+https://github.com/6pm-js/depend.git"},"author":{"name":"James Andrews","email":"jka6502@gmail.com"},"bugs":{"url":"https://github.com/6pm-js/depend/issues"},"license":"MIT","readmeFilename":"README.md"}