{"id":15638829,"url":"https://github.com/nikku/didi","last_synced_at":"2025-05-16T02:07:24.046Z","repository":{"id":15182258,"uuid":"17910165","full_name":"nikku/didi","owner":"nikku","description":"Dependency Injection for JavaScript","archived":false,"fork":false,"pushed_at":"2025-05-04T13:35:12.000Z","size":810,"stargazers_count":100,"open_issues_count":4,"forks_count":17,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-04T14:29:02.908Z","etag":null,"topics":["dependency-injection","ioc","javascript","nodejs"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nikku.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["nikku"]}},"created_at":"2014-03-19T15:46:11.000Z","updated_at":"2025-05-04T13:34:25.000Z","dependencies_parsed_at":"2024-02-03T13:23:01.699Z","dependency_job_id":"25d73b18-c7ab-4439-91e4-2ae6139f4c73","html_url":"https://github.com/nikku/didi","commit_stats":{"total_commits":231,"total_committers":7,"mean_commits":33.0,"dds":"0.16883116883116878","last_synced_commit":"2ff5c7a3504ae1729dddd2f4772580da99df8be7"},"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikku%2Fdidi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikku%2Fdidi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikku%2Fdidi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikku%2Fdidi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nikku","download_url":"https://codeload.github.com/nikku/didi/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254453652,"owners_count":22073617,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dependency-injection","ioc","javascript","nodejs"],"created_at":"2024-10-03T11:23:22.890Z","updated_at":"2025-05-16T02:07:24.028Z","avatar_url":"https://github.com/nikku.png","language":"JavaScript","funding_links":["https://github.com/sponsors/nikku"],"categories":[],"sub_categories":[],"readme":"# `didi`\n\n[![CI](https://github.com/nikku/didi/actions/workflows/CI.yml/badge.svg)](https://github.com/nikku/didi/actions/workflows/CI.yml)\n\nA tiny [inversion of control](https://en.wikipedia.org/wiki/Inversion_of_control) container for JavaScript.\n\n\n## About\n\nUsing [`didi`](https://github.com/nikku/didi) you follow the [dependency injection](https://en.wikipedia.org/wiki/Dependency_injection) / [inversion of control](https://en.wikipedia.org/wiki/Inversion_of_control) pattern, decoupling component declaration from instantiation. Once declared, `didi` instantiates components as needed, transitively resolves their dependencies, and caches instances for re-use.\n\n\n## Example\n\n```ts\nimport { Injector } from 'didi';\n\nfunction Car(engine) {\n  this.start = function() {\n    engine.start();\n  };\n}\n\nfunction createPetrolEngine(power) {\n  return {\n    start: function() {\n      console.log('Starting engine with ' + power + 'hp');\n    }\n  };\n}\n\n// define a (didi) module - it declares available\n// components by name and specifies how these are provided\nconst carModule = {\n\n  // asked for 'car', the injector will call new Car(...) to produce it\n  'car': ['type', Car],\n\n  // asked for 'engine', the injector will call createPetrolEngine(...) to produce it\n  'engine': ['factory', createPetrolEngine],\n\n  // asked for 'power', the injector will give it number 1184\n  'power': ['value', 1184] // probably Bugatti Veyron\n};\n\n// instantiate an injector with a set of (didi) modules\nconst injector = new Injector([\n  carModule\n]);\n\n// use the injector API to retrieve components\ninjector.get('car').start();\n\n// alternatively invoke a function, injecting the arguments\ninjector.invoke(function(car) {\n  console.log('started', car);\n});\n\n// if you work with a TypeScript code base, retrieve\n// a typed instance of a component\nconst car: Car = injector.get\u003cCar\u003e('car');\n\ncar.start();\n```\n\nFor real-world examples, check out [Karma](https://github.com/karma-runner/karma), [diagram-js](https://github.com/bpmn-io/diagram-js) or [Wuffle](https://github.com/nikku/wuffle/tree/main/packages/app)—libraries that heavily use dependency injection at their core. You can also check out [the tests](https://github.com/nikku/didi/blob/master/test/injector.spec.js) to learn about all supported use cases.\n\n\n## Usage\n\nLearn how to [declare](#declaring-components), [inject](#injecting-components) and [initialize](#initializing-components) your components.\n\n\n### Declaring Components\n\nBy declaring a component as part of a `didi` module, you make it available to other components.\n\n#### `type(token, Constructor)`\n\n`Constructor` will be called with `new` operator to produce the instance:\n\n```js\nconst module = {\n  'engine': ['type', DieselEngine]\n};\n```\n\n#### `factory(token, factoryFn)`\n\nThe injector produces the instance by calling `factoryFn` without any context. It uses the factory's return value:\n\n```js\nconst module = {\n  'engine': ['factory', createDieselEngine]\n};\n```\n\n#### `value(token, value)`\n\nRegister a static value:\n\n```js\nconst module = {\n  'power': ['value', 1184]\n};\n```\n\n\n### Injecting Components\n\nThe injector looks up dependencies based on explicit annotations, comments, or function argument names.\n\n#### Argument Names\n\nIf no further details are provided the injector parses dependency names from function arguments:\n\n```js\nfunction Car(engine, license) {\n  // will inject components bound to 'engine' and 'license'\n}\n```\n\n#### Function Comments\n\nYou can use comments to encode names:\n\n```js\nfunction Car(/* engine */ e, /* x._weird */ x) {\n  // will inject components bound to 'engine' and 'x._weird'\n}\n```\n\n#### `$inject` Annotation\n\nYou can use a static `$inject` annotation to declare dependencies in a minification safe manner:\n\n```js\nfunction Car(e, license) {\n  // will inject components bound to 'engine' and 'license'\n}\n\nCar.$inject = [ 'engine', 'license' ];\n```\n\n#### Array Notation\n\nYou can also the minification save array notation known from [AngularJS][AngularJS]:\n\n```js\nconst Car = [ 'engine', 'trunk', function(e, t) {\n  // will inject components bound to 'engine' and 'trunk'\n}];\n```\n\n#### Partial Injection\n\nSometimes it is helpful to inject only a specific property of some object:\n\n```js\nfunction Engine(/* config.engine.power */ power) {\n  // will inject 1184 (config.engine.power),\n  // assuming there is no direct binding for 'config.engine.power' token\n}\n\nconst engineModule = {\n  'config': ['value', {engine: {power: 1184}, other : {}}]\n};\n```\n\n\n### Initializing Components\n\nModules can use an `__init__` hook to declare components that shall eagerly load or functions to be invoked, i.e., trigger side-effects during initialization:\n\n```javascript\nimport { Injector } from 'didi';\n\nfunction HifiComponent(events) {\n  events.on('toggleHifi', this.toggle.bind(this));\n\n  this.toggle = function(mode) {\n    console.log(`Toggled Hifi ${mode ? 'ON' : 'OFF'}`);\n  };\n}\n\nconst injector = new Injector([\n  {\n    __init__: [ 'hifiComponent' ],\n    hifiComponent: [ 'type', HifiComponent ]\n  },\n  ...\n]);\n\n// initializes all modules as defined\ninjector.init();\n```\n\n\n### Overriding Components\n\nYou can override components by name. That can be beneficial for testing but also for customizing:\n\n```js\nimport { Injector } from 'didi';\n\nimport coreModule from './core';\nimport HttpBackend from './test/mocks';\n\nconst injector = new Injector([\n  coreModule,\n  {\n    // overrides already declared `httpBackend`\n    httpBackend: [ 'type', HttpBackend ]\n  }\n]);\n```\n\n\n### Type-safety\n\n[`didi`](https://github.com/nikku/didi) ships type declarations that allow you to use it in a type safe manner.\n\n#### Explicit Typing\n\nPass a type attribute to `Injector#get` to retrieve a service as a known type:\n\n```typescript\nconst hifiComponent = injector.get\u003cHifiComponent\u003e('hifiComponent');\n\n// typed as \u003cHifiComponent\u003e\nhifiComponent.toggle();\n```\n\n#### Implicit Typing\n\nConfigure the `Injector` through a service map and automatically cast services\nto known types:\n\n```typescript\ntype ServiceMap = {\n  'hifiComponent': HifiComponent\n};\n\nconst injector = new Injector\u003cServiceMap\u003e(...);\n\nconst hifiComponent = injector.get('hifiComponent');\n// typed as \u003cHifiComponent\u003e\n```\n\n\n## Credits\n\nThis library builds on top of the (now unmaintained) [node-di][node-di] library. `didi` is a maintained fork that adds support for ES6, the minification safe array notation, and other features.\n\n\n## Differences to [node-di][node-di]\n\n- supports array notation\n- supports [ES2015](http://babeljs.io/learn-es2015/)\n- bundles type definitions\n- module initialization + module dependencies\n\n\n## License\n\nMIT\n\n\n[AngularJS]: http://angularjs.org/\n[node-di]: https://github.com/vojtajina/node-di\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnikku%2Fdidi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnikku%2Fdidi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnikku%2Fdidi/lists"}