Skip to content

Repository files navigation

asimo

🚀 Full Documentation · API Reference

A zero-dependency, fully type-safe Inversion of Control (IoC) container for TypeScript — browser and server.

import { syncIID, factory, createContainer } from "@asimojs/asimo";

interface Logger { log(msg: string): void; }
const LOGGER = syncIID<Logger>()("app.services.Logger");

const app = createContainer({
    name: "app",
    services: [
        factory({
            provide: LOGGER,
            load: () => ({ log: (msg) => console.log(`[app] ${msg}`) }),
        }),
    ],
});

const logger = app.get(LOGGER);  // type: Logger
logger.log("hello world");

Why asimo?

  • Zero dependencies — ~2 KB gzipped, no decorators, no reflect-metadata
  • Full compile-time safety — missing dependencies, wrong IID types, retry-on-sync are all TypeScript errors, not runtime crashes
  • Automatic dependency inferencedependencies: [A, B] types the load context as Container<A | B>
  • Lazy bundles — wrap import() in bundle() and services load only on first access
  • Hierarchical containers — child containers inherit from parents, enabling request-scoped DI
  • Retry with exponential backoff — async services retry on failure, configurable per-service or globally
  • Runs everywhere — browser, Node.js, Bun, Deno, Cloudflare Workers

Installation

npm install @asimojs/asimo
pnpm add @asimojs/asimo
yarn add @asimojs/asimo

Quick Start

Define an IID token

import { syncIID, asyncIID } from "@asimojs/asimo";

interface Logger { log(msg: string): void; }
const LOGGER = syncIID<Logger>()("app.Logger");

interface Config { apiUrl: string; }
const CONFIG = asyncIID<Config>()("app.Config");

Create a container with services

import { factory, bundle, createContainer } from "@asimojs/asimo";

const app = createContainer({
    name: "app",
    services: [
        // Sync service — retrieved with get()
        factory({
            provide: LOGGER,
            load: () => ({ log: (msg) => console.log(msg) }),
        }),
        // Async service — retrieved with fetch()
        factory({
            provide: CONFIG,
            load: async () => {
                const resp = await fetch("/config.json");
                return resp.json();
            },
        }),
        // Lazy bundle — loaded on first access
        bundle({
            provide: [ANALYTICS],
            load: () => import("./analytics-bundle"),
        }),
    ],
});

Retrieve services

const logger = app.get(LOGGER);              // synchronous, type: Logger
const config = await app.fetch(CONFIG);       // asynchronous, type: Config
const optional = app.getOptional(OPTIONAL);   // null if not registered

Services with dependencies

factory({
    provide: USER_SERVICE,
    dependencies: [DB, LOGGER],
    load: (c) => {
        // c is typed as Container<typeof DB | typeof LOGGER>
        const db = c.get(DB);
        const log = c.get(LOGGER);
        return new UserService(db, log);
    },
});

Per-request container

const reqCtx = createContainer({
    name: "request-42",
    extends: [app],  // inherits all app services
    services: [
        factory({ provide: REQUEST, load: () => currentRequest }),
    ],
});

Documentation

Full documentation is available at asimojs.github.io/asimo:

Development

Command Description
pnpm test Run tests
pnpm build Build the library
pnpm docs:dev Start docs dev server
pnpm docs:build Build docs to docs-dist/
pnpm lint Lint source

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages