npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

hono-simple-di

v0.2.1

Published

A small, type-safe DI library optimized for hono.js.

Downloads

360

Readme

Hono simple DI

npm version npm downloads bundle Codecov License

A small, type-safe DI library optimized for Hono.js.

[!IMPORTANT] This package is optimized for Hono.js 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.

Installation

# npm
npm install hono-simple-di
# pnpm
pnpm add hono-simple-di
# bun
bun add hono-simple-di

Usage

Basic usage

1. Define a service

First, you define a service that you want to inject. This could be any class or function that handles your business logic.

// services/UserService.ts
export class UserService {
  findOne(id: number) {
    return { id, name: `User ${id}` };
  }
}

2. Create a Dependency

Next, 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).

import { Dependency } from "hono-simple-di";
import { UserService } from "./services/UserService";

// Define the dependency for UserService
const userServiceDep = new Dependency(() => new UserService());

3. Inject dependency via middleware

Use 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.

import { Hono } from "hono";
import { userServiceDep } from "./dependencies";

const app = new Hono()
  // Use the dependency as middleware
  .use(userServiceDep.middleware("userService"))

  .get("/", (c) => {
    // Retrieve the injected service
    const { userService } = c.var;
    // or const userService = c.get('userService')

    const user = userService.findOne(1);

    return c.json(user);
  });

4. Override Service with injection

You can override the service instance at runtime using the injection method. This is useful in testing or when dynamically providing service instances.

// Inject a custom service instance
userServiceDep.injection({
  findOne(id: number) {
    return { id, name: "Injected User" };
  },
});

Reference another dependency

const postServiceDep = new Dependency(
  async (c) => new PostService(await userServiceDep.resolve(c)),
);

A service can also be something other than a class

For example, using headers from c.req.headers.

const uaDep = new Dependency(
  (c) => new UAParser(c.req.header("User-Agent") ?? ""),
  {
    scope: "request",
  },
);

const app = new Hono()
  .use(uaDep.middleware("ua"))

  .get("/", (c) => {
    const ua = c.get("ua");
    return c.text(`You are running on ${ua.getOS().name}!`);
  });

Using request scope service

If you need a new instance of the service for each request (multi-instance), set the scope option to request.

const requestIdDep = new Dependency((c) => Math.random(), {
  scope: "request",
});

const app = new Hono()
  // Inject a unique ID for each request
  .use(requestIdDep.middleware("requestId"))

  .get("/id", (c) => {
    const requestId = c.get("requestId");
    return c.text(`Request ID: ${requestId}`);
  });

Do not provide an initialization function

const userServiceDep = new Dependency<UserService | null>(() => null);

API

Dependency Interface

interface Dependency<Service> {
  constructor(
    /** A function to initialize the service. */
    private serviceInitializer: (c: Context) => MaybePromise<Service>,
    private opts?: {
      /**
       * The scope of the dependency.
       * @default 'default'
       * @remarks
       * - 'default': Service will be initialized only once.
       * - 'request': Service is initialized once per request and reused across requests.
       */
      scope?: Scope
    },
  ): Dependency

  /**
   * Injects a service instance directly. Useful for overriding the default service.
   * @param service - The service instance to be injected.
   * @returns this - The instance of the dependency for chaining.
   */
  injection(service: Service): this

  /**
   * Clear injected service.
   */
  clearInjected(): this {
    this.service = undefined;
    return this;
  }

  /**
   * Creates a middleware that injects the service into the context.
   * @param contextKey - Optionally override the key used to store the service in the context.
   * @returns MiddlewareHandler - A Hono.js middleware function.
   */
  middleware<ContextKey extends string>(
    /** The key used to store the service in the context. */
    contextKey?: ContextKey,
  ): MiddlewareHandler<{
    Variables: {
      [key in ContextKey]: Service
    }
  }>
}