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

@totra/base-ts

v0.0.43

Published

CQRS / Authorization / FeatureFlag / Event-Driven / DDD / Observable framework for typescript. Innovate and rewrite fearlessly. Keep your core logic intact.

Downloads

665

Readme

TOTRA

The one to rule all

TOTRA is an extraordinarily flexible business logic framework designed to manage complex projects. Instead of being prescriptive about infrastructure or deployment, TOTRA focuses solely on building manageable and adaptable software.

When NOT to Use TOTRA

  • ❌ If your application is primarily CRUD with minimal business logic.
  • ❌ If performance is your top priority (e.g., dev tools, MMORPGs).
  • ❌ If your application primarily acts as a glue between services with minimal business logic.

While TOTRA is capable of handling CRUD and integration tasks, its core strengths lie in its design principles, which include:

  • ✅ Easy to test
  • ✅ Clear and understandable system fundamentals
  • ✅ Seamless upgrades of external dependencies without impacting core logic
  • ✅ Simplified rewrites of large application components without disrupting core logic
  • ✅ A standardized format that helps LLMs understand the codebase, reducing context tokens
  • ✅ First-class support for feature flags and authorization

TOTRA is built for software that leverages current innovations while remaining adaptable to future changes.

Features

  • Modular Design: Clearly defined roles for entities, use cases, repositories, and services promote separation of concerns, making the codebase easier to understand and maintain.
  • Type Safety: Leveraging TypeScript's capabilities to provide strong typing throughout the library, enhancing developer experience with better autocompletion, error checking, and documentation.
  • Flexible and Extensible: Easily swap out repositories and services to adapt to different storage solutions (e.g., PostgreSQL, MongoDB), allowing for seamless integration with various databases and external systems.
  • Built-in Validation: Commands include validation logic to ensure only valid data is processed, helping to enforce business rules at the entry point of command handling.
  • Event-Driven Architecture: Internal and domain events promote reactive handling of state changes, making the system scalable and efficient in processing asynchronous workflows.
  • Testability: Encourages a test-driven development (TDD) approach, with easily testable modules that ensure the reliability and correctness of the application.
  • Custom Observers: Integrate custom observers for logging, monitoring, and analytics, providing insights into application behavior and performance.

TL;DR

Explore the examples directory for a sample application featuring a partially implemented warehouse service. You can envision how the authorization policy could be integrated via middleware (e.g., Express, API Gateway) or any preferred authorization manager. Any context provider can create commands for processing.

Overview

TOTRA is inspired by the principles of inversion of control and closely resembles Uncle Bob's Clean Architecture, with some deviations. The framework emphasizes the following core concepts:

Entities: The Core

An Entity is a unified collection of elements that change in response to relevant commands. Entities are structured around collections of behavior, enhancing performance, observability, and scalability. Each entity has several responsibilities:

  1. Define the necessary context for working with the entity.
  2. Validate and map context into live state.
  3. Define internal events that indicate how the entity can change.
  4. Define domain events that other entities would care about.

Example of a WarehousedProduct entity:

export class WarehousedProduct extends Entity<
  WarehouseInternalEvent,
  WarehouseDomainEvent
> {
  protected state: {
    id: string;
    lots: {
      id: string;
      location: string;
      quantity: number;
    }[];
  };

  constructor(context: {
    id: string;
    lotTransactions: {
      id: string;
      location: string;
      quantityIn: number;
      quantityOut: number;
    }[];
  }) {
    super();
    // Validate / map context into state
    this.state = context;
  }

  reduceInternalEventsToDomainEvents(
    events: WarehouseInternalEvent[]
  ): WarehouseDomainEvent[] {
    // Map internal to domain
    return [];
  }
}

Use Cases - Entity Behavior

UseCases encapsulate specific behaviors related to entities. Each behavior is implemented as an inherited child of the entity, promoting:

  • Clear testing processes
  • Extensibility with minimal changes to the base entity
  • Scalability with isolated use cases

Commands

Commands are validated data containers processed by corresponding UseCases. Their encapsulation allows for queuing, batching, and other processing techniques, enhancing scalability and resource management.

Repositories

Repositories handle the retrieval and persistence of entity state, providing all necessary context for business logic to execute.

Feature Flags

Feature flags in TOTRA offer advanced capabilities beyond simple toggles, enabling A/B testing, separation of deployment and release, and gradual rollouts. They are integral to the framework.

Event Bus

The Event Bus facilitates the translation of internal events into domain events, allowing other services to respond appropriately.

Services

Services compose FeatureFlags, Repositories, and UseCases into a unified package, simplifying coordination between different components. They support both backend and frontend operations, promoting isomorphism.

Conclusion

This documentation serves as an initial introduction to the framework. To fully grasp its capabilities, dive in and start experimenting!

Q&As

Why use classes instead of functions?

While functional programming is appealing, classes provide a more ergonomic and type-safe experience. TOTRA balances ease of use with the power of object-oriented design.

How will breaking changes be managed?

The goal is to maintain a stable interface, minimizing breaking changes. TOTRA's core has no external dependencies, allowing for straightforward updates.

What's the release roadmap?

TOTRA is being validated in various projects to ensure interface stability. The roadmap includes:

  • Interface verification and adjustments
  • Enable granular resource access in access policies
  • Publishing

We aim to publish in the coming months.

For LLMs

Overview TOTRA is a TypeScript-based library designed for building event-driven applications. It emphasizes a modular architecture with support for commands, events, and services. This prompt provides guidance on how to interact with and leverage the TOTRA library for application development.

Key Concepts Entities: Entities represent core business objects with internal and domain events. Understand how to define entities using the Entity class and manage their state. Commands: Commands are requests to change the state of an entity. Learn to create commands by extending the Command class and validating input. Use Cases: Use cases encapsulate business logic and define how commands are handled. Implement use cases as classes that process commands and manage domain events. Repositories: Repositories manage the persistence of entities. They abstract data access and can be swapped out for different databases. Event Buses: Event buses facilitate communication between different components by dispatching events. Understand how to implement and use the EventBus. Observers: Observers allow for logging, monitoring, and analytics. They can be integrated into services to track operations and events. Getting Started Installation: Ensure that you have TOTRA installed in your TypeScript project. Use npm install @totra/base-ts to add the library. Creating an Entity: Define an entity by extending the Entity class. Implement the reduceInternalEventsToDomainEvents method to convert internal events to domain events. Implementing Commands: Create a command by extending the Command class. Validate the input in the command constructor. Defining Use Cases: Implement use cases as classes that handle commands and trigger events. Ensure that the handle method does not rely on external systems for easier testing. Best Practices Keep Commands Simple: Focus on single actions for commands to enhance readability and maintainability. Use Feature Flags: Integrate feature flags at the service level to enable or disable functionalities dynamically. Modular Services: Structure services around specific functionalities, allowing for easier testing and integration. Error Handling: Implement custom error types to handle validation and operational errors gracefully. Example Workflow Define Your Entity with its associated InternalEvents and DomainEvents:

class Channel extends Entity<ChannelInternalEvent, ChannelDomainEvent> {
  // Define properties and methods
}

Create a Command:

class AddMemberCommand extends Command<"Channel:AddMember", { userId: string }> {
  constructor(channelId: string, payload: { userId: string }) {
    // Validate and initialize command
  }
}

Implement a Use Case:

class AddMember extends Channel implements UseCase<AddMemberCommand> {
  handle(command: AddMemberCommand) {
    // Business logic for adding a member
  }
}

Implement a Repository:

export abstract class ChannelRepository
  implements Repository<typeof WarehousedProduct, {transaction: TX}>
{
  abstract hydrateEntity(entityId: string): Promise<
    [
      ChannelConstructorContext,
      {transaction: TX}
    ]
  >;
  abstract applyInternalEvents(
    entityId: string,
    internalEvents: ChannelInternalEvent[],
    repositoryMeta: {transaction: TX}
  ): Promise<void>;
}

Set Up Your Service:

const channelService = new Service({
  entity: Channel,
  repository: new ChannelRepository(),
  observer,
  eventBus,
});

channelService.register(AddMemberCommand, [
  [
    // Feature Flag
    {
      name: 'AddMemberDefault',
      enabled: async () => true,
    },
    AddMember,
  ]
])

Testing Write unit tests for commands and use cases to ensure they behave as expected. Use frameworks like Vitest to test your implementation.