{"id":20252446,"url":"https://github.com/ivandotv/pumpit","last_synced_at":"2026-03-15T21:42:40.628Z","repository":{"id":37985308,"uuid":"484215791","full_name":"ivandotv/pumpit","owner":"ivandotv","description":"PumpIt is a small (\u003c2KB) dependency injection container without the decorators, suitable for the browser.","archived":false,"fork":false,"pushed_at":"2026-03-12T14:48:40.000Z","size":955,"stargazers_count":29,"open_issues_count":10,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-12T20:46:29.402Z","etag":null,"topics":["dependency-injection","dependency-injection-container","dependency-inversion","ioc","ioc-container"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/ivandotv.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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-04-21T21:54:41.000Z","updated_at":"2026-02-06T20:17:55.000Z","dependencies_parsed_at":"2024-01-16T20:01:34.438Z","dependency_job_id":"6135f416-796c-4971-981c-133fad62f902","html_url":"https://github.com/ivandotv/pumpit","commit_stats":{"total_commits":114,"total_committers":6,"mean_commits":19.0,"dds":"0.24561403508771928","last_synced_commit":"827595f57c5651999fca2f7c3d35f6a5ffb5bbd5"},"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/ivandotv/pumpit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivandotv%2Fpumpit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivandotv%2Fpumpit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivandotv%2Fpumpit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivandotv%2Fpumpit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ivandotv","download_url":"https://codeload.github.com/ivandotv/pumpit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivandotv%2Fpumpit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30551833,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-15T15:03:43.933Z","status":"ssl_error","status_checked_at":"2026-03-15T15:03:37.630Z","response_time":61,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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","dependency-injection-container","dependency-inversion","ioc","ioc-container"],"created_at":"2024-11-14T10:16:46.327Z","updated_at":"2026-03-15T21:42:40.598Z","avatar_url":"https://github.com/ivandotv.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PumpIt\n\n[![Test](https://github.com/ivandotv/pumpit/actions/workflows/CI.yml/badge.svg)](https://github.com/ivandotv/pumpit/actions/workflows/CI.yml)\n[![Codecov](https://img.shields.io/codecov/c/gh/ivandotv/pumpit)](https://app.codecov.io/gh/ivandotv/pumpit)\n[![GitHub license](https://img.shields.io/github/license/ivandotv/pumpit)](https://github.com/ivandotv/pumpit/blob/main/LICENSE)\n\n`PumpIt` is a small [(~2KB)](https://bundlephobia.com/package/pumpit) dependency injection container without the decorators and zero dependencies, suitable for the browser.\nIt supports different injection scopes, child containers, hooks etc...\n\n\u003c!-- toc --\u003e\n\n- [Motivation](#motivation)\n- [Getting Started](#getting-started)\n  * [Registering classes](#registering-classes)\n    + [Class injection inheritance](#class-injection-inheritance)\n      - [Combining injection dependencies](#combining-injection-dependencies)\n  * [Registering factories](#registering-factories)\n  * [Registering values](#registering-values)\n- [Resolving container data](#resolving-container-data)\n- [Injection tokens](#injection-tokens)\n- [Injection scopes](#injection-scopes)\n  * [Singleton](#singleton)\n  * [Transient](#transient)\n  * [Request](#request)\n  * [Container singleton](#container-singleton)\n- [Optional injections](#optional-injections)\n- [~~Circular dependencies~~](#circular-dependencies)\n- [~~Injecting arrays~~](#injecting-arrays)\n  * [Post construct method](#post-construct-method)\n- [Removing values from the container](#removing-values-from-the-container)\n  * [Calling the dispose method](#calling-the-dispose-method)\n  * [Removing all the values from the container](#removing-all-the-values-from-the-container)\n  * [Locking the container](#locking-the-container)\n- [Child containers](#child-containers)\n  * [Shadowing values](#shadowing-values)\n  * [Checking for values](#checking-for-values)\n  * [Child singletons](#child-singletons)\n  * [Validating bindings](#validating-bindings)\n- [Helpers](#helpers)\n  * [Register injections](#register-injections)\n- [API docs](#api-docs)\n- [License](#license)\n\n\u003c!-- tocstop --\u003e\n\n## Motivation\n\nDependency injection is a powerful concept, and there are some excellent solutions like [tsyringe](https://github.com/microsoft/tsyringe), [awilix](https://github.com/jeffijoe/awilix), and [inversify](https://github.com/inversify/InversifyJS), however, they all use decorators (which are great, but not a standard), and their file size is not suitable for front-end development. So I've decided to create an implementation of a dependency injection container that is small and doesn't use decorators. I also believe that I've covered all the functionality of the above-mentioned libraries.\n\n## Getting Started\n\nInstallation:\n\n```sh\nnpm i pumpit\n```\n\nSince `PumpIt` does not rely on the decorators the injection is done via the `injection` property. When used with `classes`, `inject` will be a static property on the class, and it will hold an array of registered injection `tokens` that will be injected into the constructor in the same order when the class instance is created (in case of factory functions it will be a property on the function itself, more on that [later](#registering-factories)).\n\n### Registering classes\n\n```ts\nimport { PumpIt } from 'pumpit'\n\nconst container = new PumpIt()\nconst bindKeyB = 'b'\n\nclass TestA {\n  static inject = [bindKeyB]\n\n  constructor(b: B) {}\n}\n\nclass TestB {}\n\n// bind (register)  classes to the injection container.\ncontainer.bindClass(TestA, TestA).bindClass(bindKeyB, TestB)\n\n//resolve values\nconst instanceA = container.resolve\u003cTestA\u003e(TestA)\nconst instanceB = container.resolve\u003cTestA\u003e(bindKeyB)\n\ninstanceA.b // injected B instance\n```\n\nThere is also alternative syntax that you can use when you don't want to use the static `inject` property, or you are importing a class from third-party packages.\n\n```ts\nimport { PumpIt } from 'pumpit'\n\nconst container = new PumpIt()\nclass TestA {\n  constructor(b: TestB) {}\n}\n\nclass TestB {}\n\n//`bind`(register)  class to the injection container.\ncontainer.bindClass(TestA, { value: TestA, inject: [TestB] })\n//or\ncontainer.bindClass('some_key_to_bind', { value: TestA, inject: [TestB] })\n```\n\nYou can also use a special `INJECT_KEY` value (which is actually a `Symbol`) to inject the dependencies, this also helps when you can't use\na static `inject` property on a class (maybe the property already exists or it's a third party class)\n\n```ts\nimport { PumpIt, INJECT_KEY } from 'pumpit'\n\nconst container = new PumpIt()\n\nclass TestB {}\n\nclass TestA {\n  static [INJECT_KEY] = [TestB]\n  constructor(b: TestB) {}\n}\n\n//or you can also use this\nTestA[INJECT_KEY] = [TestB]\n\ncontainer.bindClass(TestA,TestA)\ncontainer.bindClass(TestB,TestB)\n\n```\n\n\n#### Class injection inheritance\n\nClass injection inheritance is supported out of the box, which means that the child class will get dependencies that are set to be injected to the parent.\n\n```ts\nconst pumpIt = new PumpIt()\n\nclass TestB {}\n\nclass TestA {\n  static inject = [TestB]\n}\n\nclass TestC extends TestA {\n  //TestB will be injected by reading `inject` array from the parent (TestA)\n  constructor(public b: TestB) {\n    super()\n  }\n}\n\npumpIt.bindClass(TestA, TestA)\npumpIt.bindClass(TestB, TestB)\npumpIt.bindClass(TestC, TestC)\n\nconst instance = pumpIt.resolve\u003cTestC\u003e(TestC)\n\nexpect(instance.b).toBeInstanceOf(TestB)\n```\n\n##### Combining injection dependencies\n\nChild class can define their own dependencies and combine them with the parent dependencies.\n\n```ts\nclass TestB {}\nclass TestD {}\n\nclass TestA {\n  static inject = [TestB]\n\n  constructor(public b: TestB) {}\n}\n\nclass TestC extends TestA {\n  // use dependencies from the parent and add your own (TestD class)\n  static inject = [...TestA.inject, TestD]\n\n  constructor(\n    public b: TestB,\n    public d: TestD\n  ) {\n    super()\n  }\n}\n\npumpIt.bindClass(TestA, TestA)\npumpIt.bindClass(TestB, TestB)\npumpIt.bindClass(TestC, TestC)\npumpIt.bindClass(TestD, TestD)\n\nconst instance = pumpIt.resolve\u003cTestC\u003e(TestC)\n\nexpect(instance.b).toBeInstanceOf(TestB)\nexpect(instance.d).toBeInstanceOf(TestD)\n```\n\n### Registering factories\n\nWhen registering function factories, `function` needs to be provided as the value, and when that `value` is requested,\nthe function will be executed and returned result will be the value that will be injected where it is needed.\n\n```ts\nconst container = new PumpIt()\n\nconst myFactory = () =\u003e 'hello world'\n\ncontainer.bindFactory(myFactory, myFactory)\n\nconst value: string = container.resolve(myFactory)\n\nvalue === 'hello world'\n```\n\nFactories can also have dependencies injected. They will be passed as the arguments to the factory function when it is executed.\n\n```ts\nconst container = new PumpIt()\nclass A {\n  hello() {\n    return 'hello from A'\n  }\n}\n\nconst myFactory = (a: A) =\u003e {\n  return a.hello()\n}\nmyFactory.inject = [A]\n\ncontainer.bindClass(A, A)\ncontainer.bindFactory(myFactory, myFactory)\n\nconst value: string = container.resolve(myFactory) //hello from A\n```\n\nOr alternative syntax (same as `class` alternative syntax):\n\n```ts\nconst container = new PumpIt()\n\nclass A {\n  hello() {\n    return 'hello from A'\n  }\n}\n\nconst myFactory = (a: A) =\u003e {\n  return a.hello()\n}\n\ncontainer.bindClass(A, A)\ncontainer.bindFactory(myFactory, { value: myFactory, inject: [A] })\n\nconst value: string = container.resolve(myFactory)\nvalue === 'hello from A'\n```\n\nYou can also use a special `INJECT_KEY` value (which is actually a `Symbol`) to inject the dependencies. This is not that much useful when\nworking with factories, but it can be [very useful when working with classes](#registering-classes)\n\n```ts\nimport { PumpIt, INJECT_KEY } from 'pumpit'\n\nconst container = new PumpIt()\nclass A {\n  hello() {\n    return 'hello from A'\n  }\n}\n\nconst myFactory = (a: A) =\u003e {\n  return a.hello()\n}\n\nmyFactory[INJECT_KEY] = [A]\n\ncontainer.bindClass(A, A)\ncontainer.bindFactory(myFactory, myFactory)\n\nconst value: string = container.resolve(myFactory) //hello from A\n```\n\nI encourage you to experiment with factories because they enable you to return anything you want.\n\n### Registering values\n\nValues should be used when you just want to get back the same thing that is passed in to be registered.\n\n```ts\nconst container = new PumpIt()\n\nconst myConfig = { foo: 'bar' }\n\ncontainer.bindValue('app_config', myConfig)\n\nconst resolvedConfig = container.resolve('app_config')\n\nresolvedConfig === myConfig\n```\n\n## Resolving container data\n\nWhen the container data is resolved, if the key that is requested to be resolved is not found, the container will throw an error.\n\n```ts\nconst container = new PumpIt()\n\ncontainer.resolve('key_does_not_exist') // will throw\n```\n## Injection tokens\n\nInjection tokens are the values by which the injection container knows how to resolve registered data. They can be `string`, `Symbol`, or any object.\n\n```ts\nconst container = new PumpIt()\nconst symbolToken = Symbol('my symbol')\n\nclass A {}\n\n//bind to container\ncontainer.bindClass('my_token', A)\ncontainer.bindClass(symbolToken, A)\ncontainer.bindClass(A, A)\n\n//resolve\ncontainer.resolve\u003cA\u003e('my_token')\ncontainer.resolve\u003cA\u003e(symbolToken)\ncontainer.resolve\u003cA\u003e(A)\n\n//inject tokens\nclass B {\n  static inject = [symbolToken, 'my_token', A]\n  constructor(aOne: A, aTwo: A, aThree: A) {}\n}\n```\n\n## Injection scopes\n\nThere are four types of injection scopes:\n\n### Singleton\n\nOnce the value is resolved the value will not be changed as long as the same container is used.\n\nIn the next example, both `A` and `B` instances have the same instance of `C`\n\n```ts\nimport { PumpIt, SCOPE } from 'pumpit'\n\ncontainer = new PumpIt()\n\nclass A {\n  static inject = [C, B]\n  constructor(\n    public c: C,\n    public b: B\n  ) {}\n}\nclass B {\n  static inject = [C]\n  constructor(public c: C) {}\n}\n\nclass C {}\n\ncontainer.bindClass(A, A)\ncontainer.bindClass(B, B)\ncontainer.bindClass(C, C, { scope: SCOPE.SINGLETON })\n\n// A -\u003e B,C,\n// B -\u003e C\nconst instanceA = container.resolve(A)\n\n//A and B share the same instance C\ninstanceA.c === instanceA.b.c\n```\n\n### Transient\n\nThis is the **default scope**. Every time the value is requested, a new value will be returned (resolved).\nIn the case of `classes`, it will be a new instance every time, in the case of factories, the factory function will be executed every time.\n\nIn the next example, both `A` and `B` instances will have a different `C` instance.\n\n```ts\nimport { PumpIt, SCOPE } from 'pumpit'\ncontainer = new PumpIt()\n\nclass A {\n  static inject = [C, B]\n  constructor(\n    public c: C,\n    public b: B\n  ) {}\n}\nclass B {\n  static inject = [C]\n  constructor(public c: C) {}\n}\n\nclass C {}\n\ncontainer.bindClass(A, A)\ncontainer.bindClass(B, B)\ncontainer.bindClass(C, C, { scope: SCOPE.TRANSIENT })\n\n// A -\u003e B,C,\n// B -\u003e C\nconst instanceA = container.resolve(A)\n\n//C instance is created two times\n//A and B have different instances of C\ninstanceA.c !== instanceA.b.c //C\n```\n\n### Request\n\nThis is similar to the `singleton` scope except the value is resolved **once** per resolve request chain.\nEvery new call to `container.resolve()` will create a new value.\n\n```ts\nimport { PumpIt, SCOPE } from 'pumpit'\n\ncontainer = new PumpIt()\n\nclass A {\n  static inject = [C, B]\n  constructor(\n    public c: C,\n    public b: B\n  ) {}\n}\nclass B {\n  static inject = [C]\n  constructor(public c: C) {}\n}\n\nclass C {}\n\ncontainer.bindClass(A, A)\ncontainer.bindClass(B, B)\ncontainer.bindClass(C, C, { scope: SCOPE.REQUEST })\n\nconst firstA = container.resolve(A)\nconst secondA = container.resolve(A)\nfirstA.c === firstA.b.c // A and B share C\n\nsecondA.c === secondA.b.c // A and B share C\n\nsecondA.c !== firstA.c //C from first request is different to the C from the second request\n```\n\n### Container singleton\n\nThis scope is similar to the regular `singleton` scope, but in the case of [child containers](#child-containers), the child container will create its version of the singleton instance.\n\nIn the next example, the child container will create its own version of the singleton instance.\n\n```ts\nimport { PumpIt, SCOPE } from 'pumpit'\n\ncontainer = new PumpIt()\nconst childContainer = container.child()\n\nclass A {\n  static count = 0\n  constructor() {\n    A.count++\n  }\n}\n\ncontainer.bindClass(A, A, { scope: SCOPE.CONTAINER_SINGLETON })\n\nconst parentOneA = container.resolve(A)\nconst parentTWoA = container.resolve(A)\n\nparentOneA === parentTWoA\nA.count === 1\n\nconst childOneA = childContainer.resolve(A)\nconst childTwoA = childContainer.resolve(A)\n\nchildOneA === childTwoA\nA.count === 2\n\n// parent and child have different instances\nchildOneA !== parentOneA\n```\n\n\u003e Injection scopes do not apply to bound values (`bindValue`)\n\n## Optional injections\n\nWhenever the injection container **can't** resolve the requested dependency anywhere in the chain, it will immediately **throw**.\n\nBut you can make the dependency optional, and if it cant be resolved, the container will not throw, and `undefined` will be injected in place of the requested dependency. For this, you need to use the `get()` helper function.\n\n```ts\nimport { PumpIt, get } from 'pumpit'\n\nconst container = new PumpIt()\n\nclass A {\n  //make B optional dependency\n  static inject = [get(B, { optional: true })]\n  constructor(public b: B) {}\n}\nclass B {}\n\n//NOTE: B is NOT registered with the container\ncontainer.bindClass(A, A)\n\nconst instanceA = container.resolve(A)\n\ninstanceA.b // undefined\n```\n\n## ~~Circular dependencies~~\n\n\u003e NOTE: Circular dependency functionality has been removed in version 6.\n\u003e If you want to use circular dependency you can use [version 5](https://github.com/ivandotv/pumpit/tree/v5.0.0)\n\n## ~~Injecting arrays~~\n\n\u003e NOTE: Injecting array as a dependency has been removed in version 6.\n\u003e If you want to use this feature you can use [version 5](https://github.com/ivandotv/pumpit/tree/v5.0.0)\n\n### Post construct method\n\nIf the class that is being constructed (resolved) has a \"postConstruct\" method defined it will be called automatically when the class instance is created, in the case of singleton instances it will be called only once. One more important thing about `postConstruct` method is that it will be called in the reverse order of the resolution chain. [Please refer to this test for a concrete example](src/__tests__/instance/post-construct.test.ts#L22)\n\n## Removing values from the container\n\nRegistered values can be removed from the container. When the value is removed, trying to resolve the value will throw an error.\n\n```ts\nconst container = new PumpIt()\n\ncontainer.bindValue('name', 'Mario')\n\ncontainer.unbind('name')\n\ncontainer.resolve('name') // throws error\n```\n\n### Calling the dispose method\n\nIf the class has a method `dispose()` it will automatically be called on the disposed of value, but **only** if the value is a `singleton`.\n\nInternally, the container will remove the value from its internal pool, and if the value was registered with the scope: `singleton` and the value has been resolved before (class has been instantiated or factory function executed). That means that the container holds an instance of the value, and it will try to call the `dispose of` method on that instance, or in the case of the factory, on whatever was returned from the factory.\n\n```ts\nconst container = new PumpIt()\n\nclass TestA {\n  static count = 0\n  dispose() {\n    TestA.count++\n  }\n}\n\npumpIt.bindClass(TestA, TestA, { scope: 'SINGLETON' })\npumpIt.unbind(TestA)\n\npumpIt.has(TestA) // false\n\nTestA.count === 1\n```\n\nIf you don't want to call the `dispose` method, pass `false` as the second parameter `container.unbind(TestA, false)`\n\n### Removing all the values from the container\n\nYou can remove all the values from the container by calling `container.unbindAll()`. This method will remove all the keys from the container, so the container will be empty. All the same, rules apply as for the `container.unbind()` method.\n\n```ts\nconst container = new PumpIt()\nconst callDispose = true\ncontainer.unbindAll(callDispose)\n```\n\n### Locking the container\n\nIf the container is `locked` that particular container can't accept new bindings or unbind the values already in the container.\nLocking the container does not affect child containers.\n\n```ts\nconst container = new PumpIt()\n\nclass TestA {}\nclass TestB {}\n\ncontainer.bindClass(TestA, TestA)\n\ncontainer.lock()\n\ncontainer.isLocked() // returns true\n\ncontainer.bindClass(TestB,TestB) //throws error\n\ncontainer.unbind(TestA) //throws error\n\n```\n## Child containers\n\nEvery container instance can create a **child** container. Or every container can set it's parent.\n\nThe child container is a new `PumpIt` instance that is connected to the parent container instance and it inherits all the values that are registered with the parent.\n\nThe great thing about the child container is that it can _shadow_ the parent value by registering a value with the same key.\n\n### Shadowing values\n\nThe child container can have the same `key` as the parent, in that case when the value is resolved, the child container value will be returned.\n\n```ts\nconst parent = new PumpIt()\nconst child = parent.child()\n//or child = new Pumpit()\n// child.setParent(parent)\nconst key = 'some_key'\n\nclass ParentClass {}\nclass ChildClass {}\n\nparent.bindClass(key, ParentClass)\n\nchild.bindClass(key, ChildClass)\n\nconst instance = child.resolve(key) // ChildClass\n```\n\n\u003e Parent -\u003e child chains can be as long as you like `grand parent -\u003e parent -\u003e child` ...\n\n### Checking for values\n\nWhen you check if the value exists on the child, the parent instance is also\nsearched. You can optionally disable searching on the parent.\n\n```ts\nconst parent = new PumpIt()\nconst child = parent.child()\n\nclass TestA {}\n\nparent.bindClass(TestA, TestA)\n\nchild.has(TestA) //true\n\n// disable search on the parent\nchild.has(TestA, false) // false\n```\n\n### Child singletons\n\nIf the `parent` container has registered a value with a scope `SINGLETON` all child containers will share the same instance however, if the parent has registered the value with the scope `CONTAINER_SINGLETON` then child containers\nwill create their versions of singleton instances.\n\n```ts\nconst parent = new PumpIt()\nconst child = parent.child()\n\nclass TestA {\n  static count = 0\n\n  constructor() {\n    TestA.count++\n  }\n}\n\nparent.bindClass(TestA, TestA, { scope: SCOPE.CONTAINER_SINGLETON })\n\nconst parentInstance = parent.resolve\u003cTestA\u003e(TestA)\nconst childInstance = child.resolve\u003cTestA\u003e(TestA)\n\nparentInstance !== childInstance\nTestA.count === 2\n```\n### Validating bindings\n\nCalling `validate` or `validateSafe` will validate the bindings in the container.\nIt will check if all the dependencies that are required by other bindings are present in the container.\n\n`validate` method will throw an error, while `validateSafe` will return a validation result. Calling these methods will not instantiate classes or run factory functions, so there is still a possibility that you will not get what you want when dependencies are resolved at runtime.\n\nIn the next example `RequestTest` class is not present in the container, but is needed in class `TestB`\n\n```ts\n\nconst pumpIt = new PumpIt()\n\nclass TestA {}\n\nclass TestB {\n  static inject = [TestA]\n\n  constructor(\n    public a: TestA,\n  ) {}\n}\n\n//bind only TestB\npumpIt.bindClass(TestB, TestB)\n\nconst result = pumpIt.validateSafe()\n\nexpect(result).toEqual({\n  valid: false,\n  errors: [{ key: TestA, wantedBy: [TestB] }],\n})\n\n```\n\n## Helpers\n\n### Register injections\n\n`registerInjections` helper function with a class or factory. It will automatically create `inject` property on the class or factory function.\n\n```ts\ntest(\"use helper to inject in to class\", () =\u003e {\n  const pumpIt = new PumpIt()\n\n  class TestA {}\n  class TestB {}\n  class TestC {\n    constructor(\n      public a: TestA,\n      public b: TestB,\n    ) {}\n  }\n\n  registerInjections(TestC, [TestA, TestB])\n\n  pumpIt\n    .bindClass(TestA, TestA)\n    .bindClass(TestB, TestB)\n    .bindClass(TestC, TestC)\n\n  const result = pumpIt.resolve\u003cTestC\u003e(TestC)\n\n  expect(result.a).toBeInstanceOf(TestA)\n  expect(result.b).toBeInstanceOf(TestB)\n})\n```\n## API docs\n\n`PumpIt` is written in TypeScript, [auto generated API documentation](docs/api/README.md) is available.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivandotv%2Fpumpit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fivandotv%2Fpumpit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivandotv%2Fpumpit/lists"}