CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-effect

The missing standard library for TypeScript, for writing production-grade software.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

context-services.mddocs/

Context & Dependency Injection

Type-safe service management and dependency injection system using Context and Tag for organizing and providing services throughout your application with complete compile-time safety.

Capabilities

Context System

The Context system provides a type-safe way to manage services and dependencies.

/**
 * A Context is a collection of services
 */
interface Context<in Services> {}

/**
 * A Tag identifies a specific service type
 */
interface Tag<in in out Self, in Type> {
  readonly _tag: "Tag";
  readonly identifier: string;
}

declare namespace Context {
  /**
   * Creates an empty context
   */
  function empty(): Context<never>;
  
  /**
   * Creates a context with services
   */
  function make<Services>(): Context<Services>;
  
  /**
   * Adds a service to the context
   */
  function add<T>(tag: Tag<T, T>, service: T): <Services>(self: Context<Services>) => Context<Services | T>;
  
  /**
   * Gets a service from the context
   */
  function get<Services, T>(tag: Tag<T, T>): (self: Context<Services>) => T;
  
  /**
   * Checks if a service exists in the context
   */
  function has<T>(tag: Tag<T, T>): <Services>(self: Context<Services>) => boolean;
  
  /**
   * Removes a service from the context
   */
  function omit<T>(tag: Tag<T, T>): <Services>(self: Context<Services>) => Context<Exclude<Services, T>>;
  
  /**
   * Merges two contexts
   */
  function merge<Services1, Services2>(that: Context<Services2>): (self: Context<Services1>) => Context<Services1 | Services2>;
  
  /**
   * Picks specific services from a context
   */
  function pick<Services, S extends Services>(...tags: Tag<S, S>[]): (self: Context<Services>) => Context<S>;
}

Service Creation

Functions for creating and managing service tags and implementations.

/**
 * Creates a generic service tag
 */
function GenericTag<Self, Type = Self>(identifier: string): Tag<Self, Type>;

/**
 * Creates a service tag with validation
 */
function Tag<Self, Type = Self>(identifier: string): Tag<Self, Type>;

Usage Examples:

import { Context, Effect } from "effect";

// Define services
interface Logger {
  log(message: string): Effect<void>;
}

interface Database {
  query(sql: string): Effect<unknown[]>;
}

// Create service tags
const Logger = Context.GenericTag<Logger>("Logger");
const Database = Context.GenericTag<Database>("Database");

// Create service implementations  
const logger: Logger = {
  log: (message) => Effect.sync(() => console.log(message))
};

const database: Database = {
  query: (sql) => Effect.sync(() => [{ id: 1, name: "test" }])
};

// Build context
const context = pipe(
  Context.empty(),
  Context.add(Logger, logger),
  Context.add(Database, database)
);

// Use services in effects
const program = Effect.gen(function* () {
  const logger = yield* Logger;
  const database = yield* Database;
  
  yield* logger.log("Starting query");
  const results = yield* database.query("SELECT * FROM users");
  yield* logger.log(`Found ${results.length} users`);
  
  return results;
});

// Run with context
const result = await Effect.runPromise(
  pipe(program, Effect.provideContext(context))
);

Effect Context Operations

Functions for working with services in Effect computations.

declare namespace Effect {
  /**
   * Access a service from the context
   */
  function service<T>(tag: Tag<T, T>): Effect<T, never, T>;
  
  /**
   * Provide a service to an Effect
   */
  function provideService<T>(tag: Tag<T, T>, service: T): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, Exclude<R, T>>;
  
  /**
   * Provide multiple services at once
   */
  function provideContext<R>(context: Context<R>): <A, E>(self: Effect<A, E, R>) => Effect<A, E>;
  
  /**
   * Access the entire context
   */
  function context<R>(): Effect<Context<R>, never, R>;
  
  /**
   * Provide a service using an Effect
   */
  function provideServiceEffect<T, E, R>(
    tag: Tag<T, T>,
    effect: Effect<T, E, R>
  ): <A, E1, R1>(self: Effect<A, E1, R1 | T>) => Effect<A, E | E1, R | Exclude<R1, T>>;
}

Usage Examples:

import { Context, Effect, pipe } from "effect";

// Service-based architecture
interface ApiClient {
  get(url: string): Effect<unknown, Error>;
  post(url: string, data: unknown): Effect<unknown, Error>;
}

interface UserService {
  getUser(id: string): Effect<User, Error>;
  createUser(data: CreateUserData): Effect<User, Error>;
}

const ApiClient = Context.GenericTag<ApiClient>("ApiClient");
const UserService = Context.GenericTag<UserService>("UserService");

// Implementation that depends on other services
const userService: UserService = {
  getUser: (id) => Effect.gen(function* () {
    const client = yield* ApiClient;
    const user = yield* client.get(`/users/${id}`);
    return user as User;
  }),
  
  createUser: (data) => Effect.gen(function* () {
    const client = yield* ApiClient;
    const user = yield* client.post("/users", data);
    return user as User;
  })
};

// Usage in application
const app = Effect.gen(function* () {
  const userSvc = yield* UserService;
  const user = yield* userSvc.getUser("123");
  yield* Effect.log(`Retrieved user: ${user.name}`);
  return user;
});

Types

// Service identifier type
type ServiceIdentifier = string;

// Context variance
interface Context<in Services> {
  readonly [ContextTypeId]: {
    readonly _Services: Contravariant<Services>;
  };
}

// Tag variance  
interface Tag<in in out Self, in Type> {
  readonly [TagTypeId]: {
    readonly _Self: Invariant<Self>;
    readonly _Type: Contravariant<Type>;
  };
}

// Variance markers
interface Contravariant<T> {
  readonly _T: (_: T) => void;
}

interface Invariant<T> {
  readonly _T: {
    readonly _A: (_: never) => T;
    readonly _B: (_: T) => void;
  };
}

Install with Tessl CLI

npx tessl i tessl/npm-effect

docs

concurrency-fibers.md

context-services.md

data-structures.md

effect-core.md

error-observability.md

function-utilities.md

index.md

layer-system.md

schema-validation.md

streaming.md

tile.json