Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/andrewbastin/dioc
A 'too simple' and opinionated dependency injection library
https://github.com/andrewbastin/dioc
Last synced: about 1 month ago
JSON representation
A 'too simple' and opinionated dependency injection library
- Host: GitHub
- URL: https://github.com/andrewbastin/dioc
- Owner: AndrewBastin
- License: mit
- Created: 2023-12-08T17:58:36.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2024-04-26T12:02:37.000Z (7 months ago)
- Last Synced: 2024-04-27T12:48:48.544Z (7 months ago)
- Language: TypeScript
- Size: 49.8 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
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
```ts
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 {
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.
```ts
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:
```ts
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:
```vue
import { TodoService } from "./demo.ts" // The above demo
import { useService } from "dioc/vue"const todoService = useService(TodoService) // Returns an instance of the TodoService class
```
# Developing
`dioc` repo uses [pnpm](https://pnpm.io/) for package management. Install it and run `pnpm install` to install dependencies.