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

dioc

v3.0.2

Published

A 'too simple' and opinionated dependency injection library

Downloads

1,970

Readme

dioc

A small and lightweight dependency injection / inversion of control system.

About

dioc is a really simple DI/IOC system where you write services (which are singletons per container) that can depend on each other and emit events that can be listened upon.

Demo

import { Service, Container } from "dioc"

// Here is a simple service, which you can define by extending the Service class
// and providing an ID static field (of type string)
export class PersistenceService extends Service {
  // This should be unique for each container
  public static ID = "PERSISTENCE_SERVICE"

  public read(key: string): string | undefined {
    // ...
  }

  public write(key: string, value: string) {
    // ...
  }
}

type TodoServiceEvent =
  | { type: "TODO_CREATED"; index: number }
  | { type: "TODO_DELETED"; index: number }

// Services have a built in event system
// Define the generic argument to say what are the possible emitted values
export class TodoService extends Service<TodoServiceEvent> {
  public static ID = "TODO_SERVICE"

  // Inject persistence service into this service
  private readonly persistence = this.bind(PersistenceService)

  public todos = []

  // Services cannot(*) have constructors, but init logic can be mentioned here
  override onServiceInit() {
    this.todos = JSON.parse(this.persistence.read("todos") ?? "[]")
  }

  public addTodo(text: string) {
    // ...

    // You can access services via the bound fields
    this.persistence.write("todos", JSON.stringify(this.todos))

    // This is how you emit an event
    this.emit({
      type: "TODO_CREATED",
      index,
    })
  }

  public removeTodo(index: number) {
    // ...

    this.emit({
      type: "TODO_DELETED",
      index,
    })
  }
}

// Services need a container to run in
const container = new Container()

// You can initialize and get services using Container#bind
// It will automatically initialize the service (and its dependencies)
const todoService = container.bind(TodoService) // Returns an instance of TodoService

Demo (Unit Test)

dioc/testing contains TestContainer which lets you bind mocked services to the container.

import { TestContainer } from "dioc/testing"
import { TodoService, PersistenceService } from "./demo.ts" // The above demo code snippet
import { describe, it, expect, vi } from "vitest"

describe("TodoService", () => {
  it("addTodo writes to persistence", () => {
    const container = new TestContainer()

    const writeFn = vi.fn()

    // The first parameter is the service to mock and the second parameter
    // is the mocked service fields and functions
    container.bindMock(PersistenceService, {
      read: () => undefined, // Not really important for this test
      write: writeFn,
    })

    // the peristence service bind in TodoService will now use the
    // above defined mocked implementation
    const todoService = container.bind(TodoService)

    todoService.addTodo("sup")

    expect(writeFn).toHaveBeenCalledOnce()
    expect(writeFn).toHaveBeenCalledWith("todos", JSON.stringify(["sup"]))
  })
})

Demo (Vue)

dioc/vue contains a Vue Plugin and a useService composable that allows Vue components to use the defined services.

In the app entry point:

import { createApp } from "vue"
import { diocPlugin } from "dioc/vue"

const app = createApp()

app.use(diocPlugin, {
  container: new Container(), // You can pass in the container you want to provide to the components here
})

In your Vue components:

<script setup>
import { TodoService } from "./demo.ts" // The above demo
import { useService } from "dioc/vue"

const todoService = useService(TodoService) // Returns an instance of the TodoService class
</script>

Developing

dioc repo uses pnpm for package management. Install it and run pnpm install to install dependencies.