{"id":21240796,"url":"https://github.com/mrtimofey/mini-ioc","last_synced_at":"2025-07-02T22:33:06.822Z","repository":{"id":47357855,"uuid":"326640883","full_name":"mrTimofey/mini-ioc","owner":"mrTimofey","description":"Minimalistic IoC/DI container for TypeScript","archived":false,"fork":false,"pushed_at":"2024-11-03T23:24:59.000Z","size":460,"stargazers_count":12,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-22T01:48:27.252Z","etag":null,"topics":["container","decorators","dependency-injection","di","di-container","ioc","ioc-container","typescript","vue"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mrTimofey.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2021-01-04T10:02:39.000Z","updated_at":"2024-11-03T23:25:02.000Z","dependencies_parsed_at":"2024-10-27T13:02:03.782Z","dependency_job_id":"1019029f-de61-4d43-b410-6d5544b4719b","html_url":"https://github.com/mrTimofey/mini-ioc","commit_stats":{"total_commits":73,"total_committers":2,"mean_commits":36.5,"dds":0.0273972602739726,"last_synced_commit":"2dad6ea79a56dc9d9bde605c8e539d98e95dd7d5"},"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/mrTimofey/mini-ioc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrTimofey%2Fmini-ioc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrTimofey%2Fmini-ioc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrTimofey%2Fmini-ioc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrTimofey%2Fmini-ioc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mrTimofey","download_url":"https://codeload.github.com/mrTimofey/mini-ioc/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrTimofey%2Fmini-ioc/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263226744,"owners_count":23433769,"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":["container","decorators","dependency-injection","di","di-container","ioc","ioc-container","typescript","vue"],"created_at":"2024-11-21T00:53:29.771Z","updated_at":"2025-07-02T22:33:06.786Z","avatar_url":"https://github.com/mrTimofey.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# IoC/DI container for TypeScript\n\nMinimalistic IoC/DI container for TypeScript without dependencies which does exactly what it should and not more. Proof of concept that IoC/DI container implementation can be that simple.\n\nOut-of-the-box it can only provide you with singleton or everytime-new instances of any class. In case you need something more complex you can register a custom resolver.\n\nDoesn't support primitive values. Because it shouldn't.\n\nDoesn't support TypeScript `interface` and `type`. Actually there are no libraries supporting them since types and interfaces are ephemeral build time entities and they just don't exist in runtime.\n\nIntegrates smoothly to Vue.js 2/3 projects with [vue-class-component](https://github.com/vuejs/vue-class-component) or composition API.\n\n## How to use\n\n```bash\nnpm i mini-ioc\n```\n\nIf you want to resolve classes automatically, you have 2 options.\n\n1. Use decorators with type metadata\n\t-   Install `reflect-metadata` to be able to pass type information about constructor arguments and properties to runtime\n\t-   Add `import 'reflect-metadata'` to the entry point of your application to make TypeScript provide decorated entities with reflection metadata\n\t-   Configure TypeScript to support decorators and runtime type metadata with flags `compilerOptions.experimentalDecorators = true` and `compilerOptions.emitDecoratorMetadata = true`  in your `tsconfig.json`\n2. Use `inject` function. It is available within a class constructor and can be used to resolve dependencies without metadata provided by decorators.\n\nThen you can use an IOC container like this:\n\n```typescript\nimport { Resolvable } from \"mini-ioc\";\n\n// Any class you are going to resolve with container should be decorated with Resolvable...\n@Resolvable\nclass SomeClass {}\n\n@Resolvable\nclass SomeOtherClass {\n\tpublic constructor(\n\t\t// Constructor arguments will be resolved by a container automatically based on metadata\n\t\tpublic someInstance: SomeClass\n\t);\n}\n\n// ...or use `inject` instead\nimport { inject } from \"mini-ioc\";\n\nclass SomeClass {}\n\n@Resolvable\nclass SomeOtherClass {\n\tpublic constructor(\n\t\t// Constructor arguments will be resolved by the inject function on constructor call\n\t\tpublic someInstance = inject(SomeClass)\n\t);\n}\n\nimport Container from \"mini-ioc\";\n\n// Container instance\nconst container = new Container();\n\n// Resolve class as a single instance every time (like singleton)\nconst single = container.get(SomeOtherClass);\nconsole.log(single === container.get(SomeOtherClass)); // true\n\n// Resolve a fresh class instance\nconst newInstance = container.create(SomeOtherClass);\nconsole.log(single === newInstance); // false\n\n// Constructor arguments are resolved automatically as single instances with container.get\nconsole.log(single.someInstance === newInstance.someInstance); // true\n```\n\nYou can provide any subclass to create a class instance from.\n\n```typescript\nimport Container, { Resolvable } from \"mini-ioc\";\n\nabstract class BaseClass {}\n@Resolvable\nclass SubClass extends BaseClass {}\n\nconst container = new Container();\n\n// Bind abstract class to its implementation\ncontainer.bind(BaseClass, SubClass);\n\nconsole.log(container.get(BaseClass) instanceof SubClass); // true\n```\n\nYou can completely override default behavior for a class instance creation.\n\n```typescript\nimport Container from \"mini-ioc\";\n\nabstract class BaseClass {}\n\nclass SubClass extends BaseClass {\n\tprotected field!: string;\n\n\tpublic static function makeInstance() {\n\t\tconst instance = new SubClass();\n\t\tinstance.field = \"Hello there\";\n\t\treturn instance;\n\t}\n}\n\nconst container = new Container();\n\n// Register custom function as a resolver for BaseClass\n// Mind that you don't have to use Resolvable decorator nor `inject` for custom resolvers.\n// Helpful for third-party libraries.\ncontainer.registerResolver(BaseClass, (classCtor, container) =\u003e SubClass.makeInstance());\n\n// Make instance using default resolving behavior and add some initialization logic.\ncontainer.registerResolver(BaseClass, (classCtor, container) =\u003e {\n\tconst instance = new SubClass(...container.getResolvedArguments(SubClass));\n\tinstance.initSomethingImportant(42);\n\treturn instance;\n});\n\nconsole.log(container.get(BaseClass) instanceof SubClass); // true\n```\n\n## Vue.js support\n\n```bash\nnpm i mini-ioc mini-ioc-vue\n```\n\nTo make things work in Vue.js components you should register mini-ioc container in app root `provide`:\n\n```typescript\nimport Container from \"mini-ioc\";\nimport { injectKey } from \"mini-ioc-vue\";\n\nconst container = new Container();\n\n// configure container bindings here\n\n// for Vue 2\nimport Vue from \"vue\";\n\nconst app = new Vue({\n\tprovide: {\n\t\t[injectKey]: container,\n\t},\n});\n\n// for Vue 3\nimport { createApp } from \"vue\";\n\nconst app = createApp();\napp.provide(injectKey, container);\n```\n\n### Vue 3 options API (Vue 2 support is limited)\n\nResolving will work for both Vue 2 and 3, but **typing** will be available only for **Vue 3** with `defineComponent`.\n\n```typescript\nimport { defineComponent } from \"vue\";\nimport { injectMixin, computedResolver } from \"mini-ioc-vue\";\nimport SomeClass from \"./anywhere\";\n\ndefineComponent({\n\tmixins: [injectMixin],\n\tcomputed: {\n\t\t// resolve as a singleton (container.get)\n\t\tsomeInstance: computedResolver(SomeClass),\n\t\t// resolve as an everytime-new instance (container.create)\n\t\tfreshSomeInstance: computedResolver(SomeClass, true),\n\t},\n});\n```\n\n### Vue 3 composition API (or Vue 2 + @vue/composition-api)\n\nFirst you should provide additional type information for `inject` somewhere in `.d.ts` file within your project (`src/mini-ioc.d.ts` for example).\n\n*Library itself could provide that too but in this case it will only support one of Vue 2 + `@vue/composition-api` or Vue 3. So some manual actions here are the compromise to support both. Sorry for the inconvenience :)*\n\n```typescript\ndeclare module 'mini-ioc-vue' {\n\timport type Container from 'mini-ioc';\n\timport type { InjectionKey } from 'vue'; // for Vue 3\n\t// import type { InjectionKey } from '@vue/composition-api'; // for Vue 2\n\n\texport const injectKey: InjectionKey\u003cContainer\u003e;\n}\n```\n\n```typescript\nimport { defineComponent, inject } from \"vue\";\nimport { injectKey } from \"mini-ioc-vue\";\nimport SomeClass from \"./anywhere\";\n\ndefineComponent({\n\tsetup() {\n\t\tconst container = inject(injectKey);\n\t\tif (!container) throw new Error(\"No container - no component, pal. Come back when have one.\");\n\t\tconst someInstance = container.get(SomeClass);\n\t\tconst freshSomeInstance = container.create(SomeClass);\n\t},\n});\n```\n\n### Vue 2/3 + vue-class-component\n\n```bash\nnpm i mini-ioc mini-ioc-vue mini-ioc-vue-class\n```\n\nDecorators are using `computedResolver` under-the-hood so the result is the same as using options API.\n\n```typescript\nimport { Inject, InjectNew } from \"mini-ioc-vue-class\";\nimport SomeClass from \"./anywhere\";\n\nclass MyComponent {\n\t// resolve as a singleton (container.get)\n\t@Inject\n\tsomeInstance!: SomeClass;\n\n\t// resolve as an everytime-new instance (container.create)\n\t@InjectNew\n\tfreshSomeInstance!: SomeClass;\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrtimofey%2Fmini-ioc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmrtimofey%2Fmini-ioc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrtimofey%2Fmini-ioc/lists"}