{"id":39589577,"url":"https://github.com/pcafstockf/async-injection","last_synced_at":"2026-03-11T05:09:20.865Z","repository":{"id":42031847,"uuid":"245703506","full_name":"pcafstockf/async-injection","owner":"pcafstockf","description":"A robust lightweight dependency injection library for TypeScript.","archived":false,"fork":false,"pushed_at":"2026-01-17T21:05:58.000Z","size":1369,"stargazers_count":24,"open_issues_count":0,"forks_count":5,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-18T15:58:25.309Z","etag":null,"topics":["async","dependency-injection","di","ioc","typescript"],"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/pcafstockf.png","metadata":{"files":{"readme":"ReadMe.md","changelog":"Changelog.md","contributing":null,"funding":null,"license":"License.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":"support/README.md","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":"2020-03-07T20:49:53.000Z","updated_at":"2026-01-17T21:05:35.000Z","dependencies_parsed_at":"2024-05-21T22:48:00.765Z","dependency_job_id":null,"html_url":"https://github.com/pcafstockf/async-injection","commit_stats":{"total_commits":78,"total_committers":4,"mean_commits":19.5,"dds":0.4871794871794872,"last_synced_commit":"915ae43573c155ffa4a98d4f5ecab65c318cc1ef"},"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"purl":"pkg:github/pcafstockf/async-injection","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pcafstockf%2Fasync-injection","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pcafstockf%2Fasync-injection/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pcafstockf%2Fasync-injection/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pcafstockf%2Fasync-injection/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pcafstockf","download_url":"https://codeload.github.com/pcafstockf/async-injection/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pcafstockf%2Fasync-injection/sbom","scorecard":{"id":725018,"data":{"date":"2025-08-11","repo":{"name":"github.com/pcafstockf/async-injection","commit":"03043e09988036a791995f2eabcf725e7d92ce05"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.5,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 1/24 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/publish.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":3,"reason":"dependency not pinned by hash detected -- score normalized to 3","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/pcafstockf/async-injection/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/pcafstockf/async-injection/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/pcafstockf/async-injection/publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/pcafstockf/async-injection/publish.yml/master?enable=pin","Info:   0 out of   4 GitHub-owned GitHubAction dependencies pinned","Info:   2 out of   2 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: License.txt:0","Info: FSF or OSI recognized license: MIT License: License.txt:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 7 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-22T12:31:56.359Z","repository_id":42031847,"created_at":"2025-08-22T12:31:56.359Z","updated_at":"2025-08-22T12:31:56.359Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29469907,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-15T04:35:06.950Z","status":"ssl_error","status_checked_at":"2026-02-15T04:33:41.357Z","response_time":118,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":["async","dependency-injection","di","ioc","typescript"],"created_at":"2026-01-18T07:42:19.611Z","updated_at":"2026-02-15T05:01:40.355Z","avatar_url":"https://github.com/pcafstockf.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Async-Injection\n[![CI Actions](https://github.com/pcafstockf/async-injection/workflows/CI/badge.svg)](https://github.com/pcafstockf/async-injection/actions)\n[![Publish Actions](https://github.com/pcafstockf/async-injection/workflows/NPM%20Publish/badge.svg)](https://github.com/pcafstockf/async-injection/actions)\n[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)\n![OSS Lifecycle](https://img.shields.io/osslifecycle/pcafstockf/async-injection.svg)\n[![npm version](https://img.shields.io/npm/v/async-injection)](https://www.npmjs.com/package/async-injection)\n\nA robust lightweight dependency injection library for TypeScript.\n\n## About\nAsync-Injection is a small IoC container with support for both synchronous and asynchronous dependency injection, as well as isolated and/or hierarchical scopes.\n\n## Installation\n\nYou can get the latest release from [npm](https://www.npmjs.com/package/async-injection):\n\n```\n$ npm install async-injection --save\n```\n\nTo enhance flexibility, Async-Injection does not dictate which Reflect API implementation you use.  However, you will need to explicitly choose and load one.  \nYou can use:\n\n- [reflect-metadata](https://www.npmjs.com/package/reflect-metadata)\n- [core-js (core-js/es7/reflect)](https://www.npmjs.com/package/core-js)\n- [reflection](https://www.npmjs.com/package/@abraham/reflection)\n\nThe Reflect polyfill import should only be added once, and before Async-Injection is used:\n\n```typescript\n// entry.ts\nimport \"reflect-metadata\";\n// Your code here...\n```\n\nPlease note that this library supports a wide variety of runtimes and is distributed as both esm and cjs modules, side by side.  \n\n## Basic Usage (synchronous)\nHere we 'get' a new transaction handling object, that itself, relies on a shared service:\n\n```typescript\n@Injectable()\nclass SharedService {\n    constructor(@Inject('LogLevel') @Optional('warn') private logLevel: string) { }\n}\n\n@Injectable()\nclass TransactionHandler {\n    constructor(svc: SharedService) { }\n}\n\n// Create a simple container (we will bind providers into it).\nconst container = new Container();\n\n// A single instance will be created and shared by everyone.\ncontainer.bindClass(SharedService).asSingleton();\n\n// A new instance will be created each time one is requested.\ncontainer.bindClass(TransactionHandler);\n\n// If we omit this line, the logLevel of SharedService will be initialized to 'warn'\ncontainer.bindConstant('LogLevel', 'info');\n\n// In our request processing code (which would be an anti-pattern)...\n// Instantiate a new transaction handler (it will be injected with the shared service).\nconst tx = container.get(TransactionHandler);\n```\n**NOTE:**  \nThe examples in this ReadMe are contrived to quickly communicate concepts and usage.  \nYour real world project should of course follow best practices like [separation of concerns](https://medium.com/machine-words/separation-of-concerns-1d735b703a60), having a [composition root](https://medium.com/@cfryerdev/dependency-injection-composition-root-418a1bb19130), and should avoid anti-patterns like [service locator](http://scotthannen.org/blog/2018/11/27/stop-worrying-love-service-locator.html).\n\n## Scopes\nScopes can be created using multiple Containers, and/or a hierarchy of Containers.\n\n## IoC Modules\nWhy reinvent the wheel?  TypeScript is great!  \nImplement the \"module\" you want and just import it:\n\n`my-http-ioc-module.ts`\n```typescript\nimport {myContainer} from './app';\nimport {Logger, HttpClient} from './services';\nimport {HttpClientGotWrapper} from './impl';\n\nmyContainer.bind(Logger).asSingleton();\nmyContainer.bind(HttpClient, HttpClientGotWrapper);\n```\n\n## Asynchronous Support\nFor simplicity, it is recommended that you use traditional synchronous injection for any class where that is possible.  \nBut when that's just to much work, you can \"blend\" synchronous and asynchronous injection.\nTo support \"blending\", we introduce three new methods on the `Container` which will be explained below.\n\n## Asynchronous Usage\nPerhaps in the example above, our `SharedService` is useless until it has established a database connection.  \nOf course such a simple scenario could easily be handled in user-land code, but as application complexity grows, this becomes more tedious and difficult to maintain.  \nLet's modify the example as follows:\n```typescript\n@Injectable()\nclass SharedService {\n    constructor() { }\n    connect(): Promise\u003cvoid\u003e { ... }\n}\n\nconst container = new Container();\n\n// Bind a factory function that awaits until it can fully create a SharedService.\ncontainer.bindAsyncFactory(SharedService, async () =\u003e {\n    let svc = new SharedService();\n    return await svc.connect();\n}).asSingleton();\n\n// A new transient instance will be created each time one is requested.\ncontainer.bindClass(TransactionHandler);    \n\n// Wait for all bound asynchronous factory functions to complete.\n// This step is optional.  You could omit and use Container.resolve instead (see alternative below).\nawait container.resolveSingletons(true);\n// We are now connected to the database\n\n// In our request processing code...\nconst tx = container.get(TransactionHandler);\n```\nAs an alternative, we could **remove** the call to `Container.resolveSingletons`, and in our request processing code, simply call `Container.resolve`.\n```typescript\nconst tx = await container.resolve(TransactionHandler);\n```\n\n## Important - Container.resolve vs Container.get\nBlending synchronous and asynchronous injection adds complexity to your application.  \nThe key to successful blending is to think of the object you are requesting, not as an object, but as a tree of objects with your object at the top.  \nKeep in mind that you may have **transient** objects which need to be created each time, as well as existing **singleton** objects in your dependency tree.  \nIf you know ahead of time that every object which you depend on is immediately (synchronously) available, **or** if they are asynchronous **singletons** which have already been resolved (via `Container.resolveSingletons`, or a previous call to `Container.resolve`), then no need to wait, you can just `Container.get` the tree.  \nOtherwise you need to await the full resolution of the tree with `await Container.resolve`.  \n\n## @PostConstruct Support\nIt is not always possible to fully initialize your object in the class constructor.\nThis (albeit contrived) demo shows that the `Employee` class is not yet initialized when the `Person` subclass tries to call the overridden `state` method.\n```typescript\nclass Person {\n\tpublic constructor() { this.describe(); }\n\tprotected state() { return \"relaxing\"; }\n\tpublic describe() { console.log(\"Hi I'm '\" + this.state() + \"'\"); }\n}\nclass Employee extends Person {\n\tconstructor(private manager: boolean) {\tsuper(); }\n\tprotected state() { return this.manager ? \"busy\" : \"producing\"; }\n}\n// This will print: \n//  \"Hi I'm 'producing\", even though the author probably expected \n//  \"Hi I'm busy\", because they passed true for the 'manager' parameter.\nnew Employee(true); \n```\nCan we refactor code to work around this?  Sure.  You may have to submit a couple of PR's, re-write legacy code that has no unit tests, trash encapsulation, skip a few nights sleep, etc.  But why?  \nA PostConstruct annotation ensure's your initialization method is working on a fully constructed version of your object.\nEven better, since constructors cannot be asynchronous, PostConstruct gives you an easy way to asynchronously prepare an object before it's put into service.\n\n## @PostConstruct Usage\nPost construction methods can be either synchronous or asynchronous.\n\n```typescript\nclass A {\n    public constructor() { }\n\n    // Called before the object is placed into the container (or is returned from get/resolve)\n    @PostConstruct()\n    public init(): void { ... } \n}\nclass D {\n    public constructor() { }\n\n    // Will not be placed into the container (or returned) until the Promise has been resolved.\n    @PostConstruct()\n    public init(): Promise\u003cvoid\u003e { ... }    \n}\n```\n\n### @PostConstruct Guidelines:\n- Ensure your post construction method signature properly **declares** it's return type.  \n**WARNING!**  An unspecified return type signature where the type is implied by `return new Promise(...)` is not sufficient!  You must explicitly declare the return type.  \n- `Container.get` will throw an exception if you try to retrieve a class with `@PostConstruct` on a method that returns a `Promise`, but which does not **declare** it's return type to be `Promise`.\n- The library will not invoke @PostConstruct on an object returned from a factory.  It is the factory's responsibility to construct and initialize before returning.\n- You will likely want a `Container.resolveSingletons(true)` call between your last `Container.bindXXX()` call and any `Container.get` call.\n\n## API Overview\nAsync-Injection tries to follow the common API patterns found in most other DI implementations.  Please refer to the examples above or the linked elements below for specific syntax.\n- The \n[Container](https://pcafstockf.github.io/async-injection/api-docs/container.html) class implements a \n[Binder](https://pcafstockf.github.io/async-injection/api-docs/binder.html) interface, which allows you to bind a \n[Constant](https://pcafstockf.github.io/async-injection/api-docs/container.html#bindconstant), \n[Factory](https://pcafstockf.github.io/async-injection/api-docs/container.html#bindfactory), \n[AsyncFactory](https://pcafstockf.github.io/async-injection/api-docs/container.html#bindasyncfactory), or \n[Class](https://pcafstockf.github.io/async-injection/api-docs/container.html#bindclass) value to an \n[InjectableId](https://pcafstockf.github.io/async-injection/api-docs/globals.html#injectableid) (aka key) within a \n[Container](https://pcafstockf.github.io/async-injection/api-docs/container.html).\n- The \n[Container](https://pcafstockf.github.io/async-injection/api-docs/container.html) also implements an \n[Injector](https://pcafstockf.github.io/async-injection/api-docs/injector.html) interface which allows you to synchronously \n[get](https://pcafstockf.github.io/async-injection/api-docs/container.html#get) or asynchronously \n[resolve](https://pcafstockf.github.io/async-injection/api-docs/container.html#resolve) anything that has been bound.\n- When binding a \n[Factory](https://pcafstockf.github.io/async-injection/api-docs/container.html#bindfactory), \n[AsyncFactory](https://pcafstockf.github.io/async-injection/api-docs/container.html#bindasyncfactory) or \n[Class](https://pcafstockf.github.io/async-injection/api-docs/container.html#bindclass) to an \n[InjectableId](https://pcafstockf.github.io/async-injection/api-docs/globals.html#injectableid), you can chain the result of the call to specify the binding as a \n[Singleton](https://pcafstockf.github.io/async-injection/api-docs/bindas.html#assingleton), and/or configure an \n[Error Handler](https://pcafstockf.github.io/async-injection/api-docs/bindas.html#onerror).\n- Containers may be nested by passing a parent Container to the \n[constructor](https://pcafstockf.github.io/async-injection/api-docs/container.html#constructor) of a child Container.\n- To bind a \n[Class](https://pcafstockf.github.io/async-injection/api-docs/container.html#bindclass) into the \n[Container](https://pcafstockf.github.io/async-injection/api-docs/container.html), you must add the \n[@Injectable](https://pcafstockf.github.io/async-injection/api-docs/globals.html#injectable) decorator (aka annotation) to your class (see examples above).\n- You may optionally add a \n[@PostConstruct](https://pcafstockf.github.io/async-injection/api-docs/globals.html#postconstruct) decorator to a method of your class to perform synchronous or asynchronous initialization of a new instance.\n- By default, Async-Injection will examine the parameters of a class constructor and do it's best to match those to a bound \n[InjectableId](https://pcafstockf.github.io/async-injection/api-docs/globals.html#injectableid).  \n- You may use the \n[@Inject](https://pcafstockf.github.io/async-injection/api-docs/globals.html#inject) decorator to explicitly declare which \n[InjectableId](https://pcafstockf.github.io/async-injection/api-docs/globals.html#injectableid) should be used (generally required for a \n[Constant](https://pcafstockf.github.io/async-injection/api-docs/container.html#bindconstant) binding as in the logLevel example above).\n- The \n[@Optional](https://pcafstockf.github.io/async-injection/api-docs/globals.html#optional) decorator allows you to specify a default value for a class constructor parameter in the event that no matching \n[InjectableId](https://pcafstockf.github.io/async-injection/api-docs/globals.html#injectableid) can be found.\n- The Container's \n[resolveSingletons](https://pcafstockf.github.io/async-injection/api-docs/container.html#resolvesingletons) method may be used to wait for any bound (a)synchronous [Singletons](https://en.wikipedia.org/wiki/Singleton_pattern) to finish initialization before continuing execution of your application.\n\n## Acknowledgements\nThanks to all the contributors at [InversifyJS](https://github.com/inversify/InversifyJS).  It is a powerful, clean, flexible, inspiring design.\n\nThanks to everyone at [NestJS](https://docs.nestjs.com/fundamentals/async-providers) for giving us Asynchronous providers.\n\nThanks to Darcy Rayner for describing a [DI implementation](https://dev.to/darcyrayner/typescript-dependency-injection-in-200-loc-12j7) so simply and clearly.\n\nThanks to Carlos Delgado for the idea of a [\"QuerablePromise\"](https://ourcodeworld.com/articles/read/317/how-to-check-if-a-javascript-promise-has-been-fulfilled-rejected-or-resolved) which allowed us to blend asynchronous DI with the simplicity of synchronous DI.\n\n## MIT License\n\nCopyright (c) 2020-2023 Frank Stock\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpcafstockf%2Fasync-injection","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpcafstockf%2Fasync-injection","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpcafstockf%2Fasync-injection/lists"}