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

@smonn/container

v2.0.0

Published

TypeScript-based dependency injection container

Downloads

2

Readme

@smonn/container

Dependency injection container. Attempts to avoid fixed dependencies via decorators. It also always returns the same instance unless you explicitly ask for a new instance. Instances are lazily created, meaning nothing is created until you request an instance. TypeScript optional, but attempts to infer types as much as possible.

Install

npm install @smonn/container
yarn add @smonn/container

Usage

Example usage. See more examples in the test files.

import { expect, test } from "vitest";
import { createContainer, createToken, IContainer } from "../src/index";

// Interfaces are optional, but can help to ensure you depend on abstractions only.
interface IGreeter {
  sayHello(): string;
}
interface IShouter {
  shoutHello(): string;
}

class Greeter implements IGreeter {
  // Can either define tokens along with the class implementation...
  static token = createToken<IGreeter>("greeter");

  constructor(private readonly name: string) {}

  sayHello(): string {
    return `Hello, ${this.name}!`;
  }
}

class Shouter implements IShouter {
  static token = createToken<IShouter>("shouter");

  constructor(private readonly greeter: IGreeter) {}

  shoutHello(): string {
    return this.greeter.sayHello().toUpperCase();
  }
}

class Other {
  ping() {
    return "pong";
  }
}

// Or define token types in a central location to help avoid circular imports.
const Tokens = {
  // Token type can also be inferred from the function signature
  name: createToken("name", String),

  // Or use explicit type and infer name from class
  other: createToken("other", Other),
} as const;

// Group together related classes in a single function to avoid a single
// massive function defining hundreds of dependencies. Also note that thanks to
// the token spec, explicitly declaring the generic type is not required.
function provideModule(container: IContainer) {
  // Literal/basic values are allowed
  container.set(Tokens.name, "Joy");
  container.set(Tokens.other, new Other());

  // Use factory functions to help resolve dependencies
  container.set(Greeter.token, (c) => new Greeter(c.get(Tokens.name)));
  container.set(Shouter.token, (c) => new Shouter(c.get(Greeter.token)));
}

const container = createContainer();
container.register(provideModule);

// Here shouter will have the correct type (the IShouter interface)
const shouter = container.get(Shouter.token);

test('returns "HELLO, JOY!"', () => {
  expect(shouter.shoutHello()).toBe("HELLO, JOY!");
});

test("always get the same instance", () => {
  expect(container.get(Shouter.token)).toBe(container.get(Shouter.token));
});

test("always get a new instance", () => {
  expect(container.create(Shouter.token)).not.toBe(
    container.create(Shouter.token)
  );
});

test("other will never create a new instance", () => {
  expect(container.create(Tokens.other)).toBe(container.create(Tokens.other));
});