{"id":17703221,"url":"https://github.com/maou-shonen/hono-simple-di","last_synced_at":"2025-05-07T02:43:42.403Z","repository":{"id":259348889,"uuid":"877160818","full_name":"maou-shonen/hono-simple-DI","owner":"maou-shonen","description":"A small, type-safe DI library optimized for hono.js.","archived":false,"fork":false,"pushed_at":"2025-02-05T06:00:02.000Z","size":225,"stargazers_count":30,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-16T05:18:37.865Z","etag":null,"topics":["dependency-injection","hono","honojs","inversion-of-control","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/maou-shonen.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}},"created_at":"2024-10-23T07:35:37.000Z","updated_at":"2025-04-11T16:45:41.000Z","dependencies_parsed_at":"2024-10-24T18:17:22.079Z","dependency_job_id":"a27fc849-1e82-4802-9543-80aa7afceebc","html_url":"https://github.com/maou-shonen/hono-simple-DI","commit_stats":null,"previous_names":["maou-shonen/hono-simple-di"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maou-shonen%2Fhono-simple-DI","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maou-shonen%2Fhono-simple-DI/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maou-shonen%2Fhono-simple-DI/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maou-shonen%2Fhono-simple-DI/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maou-shonen","download_url":"https://codeload.github.com/maou-shonen/hono-simple-DI/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252802608,"owners_count":21806537,"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","hono","honojs","inversion-of-control","ioc","typescript"],"created_at":"2024-10-24T20:05:51.995Z","updated_at":"2025-05-07T02:43:42.370Z","avatar_url":"https://github.com/maou-shonen.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Hono simple DI\n\n[![npm version][npm-version-src]][npm-version-href]\n[![npm downloads][npm-downloads-src]][npm-downloads-href]\n[![bundle][bundle-src]][bundle-href]\n[![Codecov][codecov-src]][codecov-href]\n[![License][license-src]][license-href]\n\nA small, type-safe DI library optimized for Hono.js.\n\n\u003e [!IMPORTANT]\n\u003e This package is optimized for [Hono.js](https://github.com/honojs/hono) and is not designed for large projects. If you require advanced DI features such as automatic circular injection, dynamic binding, and multi-binding, etc. you may need a dedicated DI library.\n\n## Installation\n\n```bash\n# npm\nnpm install hono-simple-di\n# pnpm\npnpm add hono-simple-di\n# bun\nbun add hono-simple-di\n```\n\n## Usage\n\n### Basic usage\n\n#### 1. Define a service\n\nFirst, you define a service that you want to inject. This could be any class or function that handles your business logic.\n\n```ts\n// services/UserService.ts\nexport class UserService {\n  findOne(id: number) {\n    return { id, name: `User ${id}` };\n  }\n}\n```\n\n#### 2. Create a Dependency\n\nNext, you create a dependency for your service, specifying how it should be initialized. You can also choose whether it should be a singleton (default) or multi-instance (per request).\n\n```ts\nimport { Dependency } from \"hono-simple-di\";\nimport { UserService } from \"./services/UserService\";\n\n// Define the dependency for UserService\nconst userServiceDep = new Dependency(() =\u003e new UserService());\n```\n\n#### 3. Inject dependency via middleware\n\nUse the middleware method to inject the dependency into your Hono.js context. Once injected, the service will be accessible through the context's c.get method.\n\n```ts\nimport { Hono } from \"hono\";\nimport { userServiceDep } from \"./dependencies\";\n\nconst app = new Hono()\n  // Use the dependency as middleware\n  .use(userServiceDep.middleware(\"userService\"))\n\n  .get(\"/\", (c) =\u003e {\n    // Retrieve the injected service\n    const { userService } = c.var;\n    // or const userService = c.get('userService')\n\n    const user = userService.findOne(1);\n\n    return c.json(user);\n  });\n```\n\n#### 4. Override Service with injection\n\nYou can override the service instance at runtime using the injection method. This is useful in testing or when dynamically providing service instances.\n\n```ts\n// Inject a custom service instance\nuserServiceDep.injection({\n  findOne(id: number) {\n    return { id, name: \"Injected User\" };\n  },\n});\n```\n\n---\n\n### Reference another dependency\n\n```ts\nconst postServiceDep = new Dependency(\n  async (c) =\u003e new PostService(await userServiceDep.resolve(c)),\n);\n```\n\n---\n\n### A service can also be something other than a class\n\nFor example, using headers from `c.req.headers`.\n\n```ts\nconst uaDep = new Dependency(\n  (c) =\u003e new UAParser(c.req.header(\"User-Agent\") ?? \"\"),\n  {\n    scope: \"request\",\n  },\n);\n\nconst app = new Hono()\n  .use(uaDep.middleware(\"ua\"))\n\n  .get(\"/\", (c) =\u003e {\n    const ua = c.get(\"ua\");\n    return c.text(`You are running on ${ua.getOS().name}!`);\n  });\n```\n\n---\n\n### Using request scope service\n\nIf you need a new instance of the service for each request (multi-instance), set the scope option to `request`.\n\n```ts\nconst requestIdDep = new Dependency((c) =\u003e Math.random(), {\n  scope: \"request\",\n});\n\nconst app = new Hono()\n  // Inject a unique ID for each request\n  .use(requestIdDep.middleware(\"requestId\"))\n\n  .get(\"/id\", (c) =\u003e {\n    const requestId = c.get(\"requestId\");\n    return c.text(`Request ID: ${requestId}`);\n  });\n```\n\n---\n\n### Do not provide an initialization function\n\n```ts\nconst userServiceDep = new Dependency\u003cUserService | null\u003e(() =\u003e null);\n```\n\n## API\n\n### `Dependency` Interface\n\n```ts\ninterface Dependency\u003cService\u003e {\n  constructor(\n    /** A function to initialize the service. */\n    private serviceInitializer: (c: Context) =\u003e MaybePromise\u003cService\u003e,\n    private opts?: {\n      /**\n       * The scope of the dependency.\n       * @default 'default'\n       * @remarks\n       * - 'default': Service will be initialized only once.\n       * - 'request': Service is initialized once per request and reused across requests.\n       */\n      scope?: Scope\n    },\n  ): Dependency\n\n  /**\n   * Injects a service instance directly. Useful for overriding the default service.\n   * @param service - The service instance to be injected.\n   * @returns this - The instance of the dependency for chaining.\n   */\n  injection(service: Service): this\n\n  /**\n   * Clear injected service.\n   */\n  clearInjected(): this {\n    this.service = undefined;\n    return this;\n  }\n\n  /**\n   * Creates a middleware that injects the service into the context.\n   * @param contextKey - Optionally override the key used to store the service in the context.\n   * @returns MiddlewareHandler - A Hono.js middleware function.\n   */\n  middleware\u003cContextKey extends string\u003e(\n    /** The key used to store the service in the context. */\n    contextKey?: ContextKey,\n  ): MiddlewareHandler\u003c{\n    Variables: {\n      [key in ContextKey]: Service\n    }\n  }\u003e\n}\n```\n\n\u003c!-- Refs --\u003e\n\n[npm-version-src]: https://img.shields.io/npm/v/hono-simple-di\n[npm-version-href]: https://npmjs.com/package/hono-simple-di\n[npm-downloads-src]: https://img.shields.io/npm/dm/hono-simple-di\n[npm-downloads-href]: https://npmjs.com/package/hono-simple-di\n[codecov-src]: https://img.shields.io/codecov/c/gh/maou-shonen/hono-simple-di/main\n[codecov-href]: https://codecov.io/gh/maou-shonen/hono-simple-di\n[bundle-src]: https://img.shields.io/bundlephobia/minzip/hono-simple-di\n[bundle-href]: https://bundlephobia.com/result?p=hono-simple-di\n[license-src]: https://img.shields.io/github/license/maou-shonen/hono-simple-di.svg\n[license-href]: https://github.com/maou-shonen/hono-simple-di/blob/main/LICENSE\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaou-shonen%2Fhono-simple-di","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaou-shonen%2Fhono-simple-di","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaou-shonen%2Fhono-simple-di/lists"}