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 🙏

© 2025 – Pkg Stats / Ryan Hefner

ts-node-app

v0.3.0

Published

CLI para geração de componentes em arquiteturas DDD, hexagonal ou Clean Architecture ...

Downloads

212

Readme

Architect CLI

The ts-node-app project is a CLI for generating components in DDD, Hexagonal, Clean Architecture, and MVC architectures. Below are the available features and how to use them.

Getting Started

Before using any other commands, the first step is to initialize your TypeScript project. This sets up all necessary dependencies and configurations.

npx ts-node-app init typescript

This command will prepare your project with the required setup for a TypeScript backend application. The structure of the setup will be saved in an architecture.json file. You can modify this file before running the generate command to adjust the structure to better suit your needs.

Usage: ts-node-app [options] [command]

Options:
  -h, --help             display help for command

Commands:
  pull [options] <path>  Generate 'architecture.json' file by path argument and save it in the root of the project
                         you can ignore some files or directories by comma separated and regex patterns ex: package?,node_modules
  push [options] [type]  Push structure to the project
  generate [options]     Apply structure from file architecture.json
  print [options]        Print current structure file architecture.json
  init [options] [type]  Setup all dependencies for backend TypeScript project
  help [command]         display help for command

Index

Installation

You can install the CLI globally or as a development dependency in your project.

Running with NPX

You can run the CLI directly with npx without the need for installation.

npx ts-node-app <command>

Running with Alias

If you install the package globally or as a development dependency, you can use the alias tsna to run the commands.

Global Installation

npm install -g ts-node-app

Development Dependency

npm install --save-dev ts-node-app

Once installed, you can use the alias:

tsna <command>

Available Commands

init

Sets up all necessary dependencies for a backend project in TypeScript.

npx ts-node-app init <type>
  • type: Project type (default: typescript).
  • -v, --verbose: Prints more information during execution.

pull

Generates an architecture.json file from the current project structure.

npx ts-node-app pull <path>
  • path: Path to the project's root directory (e.g., ./src or ./).
  • -v, --verbose: Prints more information during execution.
  • -i, --ignore <any>: Ignores specific files or directories (e.g., node_modules,coverage,dist).

push

Applies a project structure based on one of the supported patterns.

npx ts-node-app push <type>
  • type: Architecture type (hexagonal, clean, mvc, serverless).
  • -v, --verbose: Prints more information during execution.

generate

Applies the structure defined in the architecture.json file to the project.

npx ts-node-app generate
  • -v, --verbose: Prints more information during execution.

print

Prints the current structure defined in the architecture.json file.

npx ts-node-app print
  • -v, --verbose: Prints more information during execution.

Usage Examples

Set Up TypeScript Project

npx ts-node-app init typescript

Generate Structure File

npx ts-node-app pull ./src

Apply Hexagonal Structure

npx ts-node-app push hexagonal

Generate Structure from File

npx ts-node-app generate

Print Current Structure

npx ts-node-app print

Complete Project Setup

When running the init command, the project will be set up with the following scripts and dependencies:

Scripts

  • dev: dotenv -e .env.development tsx watch src/main.ts
  • start: node dist/main.js
  • build: tsup src/main.ts
  • test: echo "Error: no test specified" && exit 1
  • test:watch: dotenv -e .env.test jest -- --watchAll --no-coverage
  • docker:dev: npm run docker:build:dev && npm run docker:run:dev
  • docker:prod: npm run docker:build:prod && npm run docker:run:prod
  • docker:build:dev: docker build --target development -t application-name:dev .
  • docker:build:prod: docker build --target production -t application-name:prod .
  • docker:run:dev: docker run -p 3000:3000 -d application-name:dev
  • docker:run:prod: docker run -d application-name:prod
  • docker:db:up: docker-compose -f 'docker-compose.yml' up -d --build 'postgis'
  • docker:db:down: docker-compose -f 'docker-compose.yml' down

Development Dependencies

  • @eslint/js: ^9.22.0
  • @types/jest: ^29.5.14
  • @types/supertest: ^6.0.2
  • dotenv-cli: ^8.0.0
  • eslint: ^9.22.0
  • globals: ^16.0.0
  • jest: ^29.7.0
  • supertest: ^7.0.0
  • ts-jest: ^29.2.6
  • ts-node-app: ^0.1.0
  • tsconfig-paths: ^4.2.0
  • tsup: ^8.4.0
  • tsx: ^4.19.3
  • typescript: ^5.8.2
  • typescript-eslint: ^8.26.1

Architecture Concepts

Clean Architecture

Clean Architecture is a software design philosophy that emphasizes the separation of concerns, making the codebase more maintainable, testable, and scalable. It aims to create a clear distinction between the business logic and the infrastructure of an application.

In Clean Architecture, the core business logic is isolated from external dependencies such as databases, frameworks, and user interfaces. This is achieved by organizing the code into layers, each with a specific responsibility.

The main layers are:

  1. Entities: Represent the core business objects and rules.
  2. Use Cases: Contain the application-specific business rules and orchestrate the flow of data between entities and external systems.
  3. Interface Adapters: Convert data from the format most convenient for the use cases and entities to the format most convenient for external systems.
  4. Frameworks and Drivers: Include external systems such as databases, web frameworks, and user interfaces.

Domain-Driven Design (DDD)

Domain-Driven Design (DDD) is a software development approach that focuses on modeling the domain of the application based on the real-world business context. It emphasizes collaboration between technical and domain experts to create a shared understanding of the domain and its complexities.

DDD introduces several key concepts:

  1. Entities: Objects that have a distinct identity and lifecycle.
  2. Value Objects: Immutable objects that describe aspects of the domain with no distinct identity.
  3. Aggregates: Clusters of entities and value objects that are treated as a single unit for data changes.
  4. Repositories: Abstractions that provide access to aggregates.
  5. Services: Operations that do not naturally fit within entities or value objects.
  6. Domain Events: Events that signify something important has happened within the domain.

Some Concepts about Layers and Components

Entity

Domain-Driven Design (DDD) → Used to represent domain objects.

Clean Architecture → Belongs to the domain layer (Core).

  1. Object with a unique identity.
  2. Mutable state over time.
  3. Compared by its identifier (id) and not by attribute values.

Value Object

Domain-Driven Design (DDD) → Used to maintain consistency between entities.

Principle of Immutability → Value objects should not be altered.

  1. Immutable object.
  2. Compared by its content, not by an id.
  3. Encapsulates specific logic within it.
export class Email {
  private readonly value: string;

  constructor(email: string) {
    if (!this.isValidEmail(email)) {
      throw new Error("Invalid email.");
    }
    this.value = email.toLowerCase();
  }

  private isValidEmail(email: string): boolean {
    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
  }

  getValue(): string {
    return this.value;
  }
}

Aggregate

Domain-Driven Design (DDD) → Used to maintain consistency between entities.

Encapsulation → Only the aggregate root can modify its internal entities.

  1. Group of related entities treated as a single unit.
  2. Has an "aggregate root" that controls the other entities.
  3. Ensures internal consistency by allowing changes only through the root.
import { User } from "../entities/User";

export class Account {
  constructor(private owner: User, private balance: number = 0) {}

  deposit(amount: number) {
    if (amount <= 0) throw new Error("Deposit must be greater than zero.");
    this.balance += amount;
  }

  withdraw(amount: number) {
    if (amount > this.balance) throw new Error("Insufficient balance.");
    this.balance -= amount;
  }

  getBalance() {
    return this.balance;
  }
}

Domain Exceptions (exceptions/)

  1. Specific domain errors should have their own classes.
export class DomainException extends Error {
  constructor(message: string) {
    super(message);
    this.name = "DomainException";
  }
}

export class InsufficientBalanceException extends DomainException {
  constructor() {
    super("Insufficient balance.");
  }
}

Interfaces

export interface IUserRepository {
  save(user: User): Promise<void>;
  findByEmail(email: string): Promise<User | null>;
}
  • Domain-Driven Design (domain/contracts)
    • They are in the domain layer because the domain cannot depend on external technologies.
    • Interfaces are used to define repositories, domain services, and factories.
  • Clean Architecture (application/interfaces)
    • In Clean Architecture, this layer is usually called "Interfaces" or "Contracts".
    • It defines Gateways, Repositories, and Services, which will be used by Use Cases.
  • Hexagonal Architecture (core/ports)
    • In Hexagonal Architecture, this layer is called "Ports".
    • Ports define how the domain communicates with the external world, but without implementing anything.

Presentation

The Presentation layer is responsible for the application's input interface, meaning it receives user requests and translates them into use cases (Use Cases or Application Services).

📌 It appears in architectures like Clean Architecture and Hexagonal, it is not a central concept of DDD! 📌 It does NOT contain business rules! Its only role is to interpret inputs and direct them to the use cases. It can contain different types of input adapters, depending on the type of interface:

| Input Type | Example | | ----------- | --------------------------------------- | | REST API | Controllers (Express, Fastify, NestJS) | | GraphQL API | Resolvers (Apollo, Mercurius) | | CLI | Terminal commands (Commander.js, Yargs) | | WebSockets | Real-time connection management | | Messaging | Message queues (Kafka, RabbitMQ) |

Key Differences

DDD: Defines how to model the domain with well-structured business rules.

Clean Architecture: Defines the separation into layers to maintain low coupling.

Hexagonal Architecture: Defines how the domain communicates with the external world through ports & adapters.

Example Simple Structure DDD

src/
├── application/
│   ├── use-cases/
│   │   ├── create-user.use-case.ts
│   │   ├── update-user.use-case.ts
│   │   └── delete-user.use-case.ts
│   └── dto/
│       └── user-dto.ts
├── domain/
│   ├── entities/
│   │   └── user.ts
│   ├── value-objects/
│   │   └── email.ts
│   ├── aggregates/
│   │   └── user.aggregate.ts
│   ├── contracts/
│   │   └── user.contract.ts
│   ├── services/
│   │   └── user.service.ts
│   ├── events/
│   │   └── user.created.event.ts
│   └── exceptions/
│       └── UserNotFoundException.ts
├── infrastructure/
│   ├── config/
│   │   └── app-config.ts
│   ├── repositories
│   │   └── UserRepository.ts
│   ├── logger
│   │   └── logger.ts
│   ├── http
│   │   └── server.ts
│   ├── services
│   │   ├── auth.service.ts
│   │   └── email.service.ts
│   ├── database/
│   │   └── prisma/
│   │       ├── client.ts
│   │       └── user-repository.ts
├── shared/
│   ├── utils/
│   │   ├── date.util.ts
│   │   └── string.util.ts
│   ├── constants/
│   │   └── error-codes.ts
│   ├── mappers/
│   │   └── user.mapper.ts
│   ├── errors/
│   │   ├── app-error.ts
│   │   └── not-found-error.ts
│   └── middlewares/
│       ├── error-handler.middleware.ts
│       └── auth.middleware.ts
└── main.ts

Clean Architecture with Domain-Driven Design (DDD)

Combining Clean Architecture with Domain-Driven Design (DDD) provides a robust framework for building scalable and maintainable applications by clearly defining the boundaries between different parts of the system and focusing on the core business logic.

src/
├── application/
│   ├── dto/
│   │   ├── user-dto.ts
│   │   └── product-dto.ts
│   ├── services/
│   │   ├── notification.service.ts
│   │   └── cache.service.ts
│   └── use-cases/
│       └── user/
│           ├── create-user.use-case.ts
│           ├── update-user.use-case.ts
│           └── delete-user.use-case.ts
├── domain/
│   ├── entities/
│   │   ├── user.ts
│   │   └── product.ts
│   ├── interfaces/
│   │   ├── user-repository.ts
│   │   └── email-service.ts
│   ├── services/
│   │   ├── auth-service.ts
│   │   └── payment-service.ts
│   └── value-objects/
│       ├── email.ts
│       └── price.ts
├── infrastructure/
│   ├── cache/
│   │   └── redis.ts
│   ├── database/
│   │   └── prisma/
│   │       ├── client.ts
│   │       ├── migrations/
│   │       └── user.repository.ts
│   ├── http/
│   │   ├── controllers/
│   │   │   ├── user.controller.ts
│   │   │   └── product.controller.ts
│   │   ├── routes/
│   │   │   ├── user.routes.ts
│   │   │   └── product.routes.ts
│   │   └── interfaces/
│   │       └── http-server.ts
│   ├── queue/
│   │   ├── bull.config.ts
│   │   └── process-job.ts
│   ├── repositories/
│   │   └── user-repository.ts
│   ├── config/
│   │   └── app-config.ts
│   └── services/
│       ├── email.service.ts
│       └── logger.service.ts
├── presentaion/
│   ├── controllers/
│   │   ├── user.controller.ts
│   │   └── product.controller.ts
│   ├── routes/
│   │   ├── user.routes.ts
│   │   └── product.routes.ts
│   ├── middlewares/
│   │   ├── error-handler.middleware.ts
│   │   └── auth.middleware.ts
│   ├── graphql/
│   │   ├── resolvers/
│   │   │   ├── user.resolver.ts
│   │   │   └── product.resolver.ts
│   │   └── schema.ts
│   ├── websockets/
│   │   ├── socket-server.ts
│   │   └── socket-events.ts
│   └── cli/
│       └── user-cli.ts
├── shared/
│   ├── config/
│   │   └── env.ts
│   ├── errors/
│   │   ├── app-error.ts
│   │   └── not-found-error.ts
│   ├── mappers/
│   │   ├── user.mapper.ts
│   │   └── product.mapper.ts
│   ├── constants/
│   │   └── error-codes.ts
│   ├── middlewares/
│   │   ├── error-handler.middleware.ts
│   │   └── auth.middleware.ts
│   └── utils/
│       ├── date.util.ts
│       └── string.util.ts
└── main.ts

This structure ensures that the core business logic is isolated from external dependencies, making the codebase more maintainable, testable, and scalable. The use cases orchestrate the flow of data between the domain and external systems, while the infrastructure layer handles the implementation details of these systems.

Hexagonal Architecture

Hexagonal Architecture, also known as Ports and Adapters, is a design pattern that aims to create loosely coupled application components that can be easily connected to their software environment through ports and adapters. This architecture promotes separation of concerns, making the application more modular, testable, and maintainable.

In a Hexagonal Architecture, the core logic of the application is isolated from external systems such as databases, user interfaces, and third-party services. The core interacts with these external systems through well-defined interfaces (ports), and the actual implementation of these interfaces (adapters) can be swapped without affecting the core logic.

| Adapter Type | Function | Implementation Example | | ----------------- | ------------------------------------------ | ---------------------------------- | | Persistence | Save and retrieve data from the database | Prisma, Sequelize, MongoDB, Redis | | Controllers | Adapt HTTP input for use cases | Express, Fastify, NestJS, HapiJS | | Gateways | Communication with external services | Stripe, SendGrid, Twilio, Firebase | | Messaging | Asynchronous communication (message queue) | Kafka, RabbitMQ, AWS SQS | | CLI Adapters | Command line input (CLI) | Commander.js, yargs | | GraphQL Resolvers | Adapters for GraphQL | Apollo Server, Mercurius | | WebSockets | Real-time bidirectional communication | Socket.io, WebRTC |

  • When to Use Each Adapter?

  • Persistence: Use when the system needs to store data in databases like PostgreSQL, MongoDB, Redis.

  • Controllers: Use to expose REST endpoints.

  • Gateways: Use to consume external APIs (payments, emails, notifications).

  • Messaging: Use for asynchronous communication via queues (Kafka, RabbitMQ).

  • CLI: Use for terminal input (e.g., administrative scripts).

  • GraphQL: Use if the API uses GraphQL instead of REST.

  • WebSockets: Use for real-time events (chat, notifications).

🔥 Final Summary 📌 Adapters are all the concrete implementations that connect the domain to the external world. 📌 The domain should never depend directly on these implementations. 📌 Each type of adapter has a specific responsibility, avoiding excessive coupling.

Example Structure

src/
├── adapters/
│   ├── persistence
│   │   ├── PrismaUserRepository.ts
│   │   └── MongoUserRepository.ts
│   ├── controllers
│   │   └── UserController.ts
│   ├── gateways
│   │   ├── StripePaymentGateway.ts
│   │   └── SendGridEmailGateway.ts
│   ├── messaging
│   │   ├── KafkaQueueService.ts
│   │   └── RabbitMQQueueService.ts
│   ├── cli
│   │   └── UserCLI.ts
│   ├── graphql
│   │   └── UserResolver.ts
│   ├── websockets
│   │   └── WebSocketServer.ts
├── core/
│   ├── domain/
│   │   ├── entities/
│   │   │   └── user.ts
│   │   ├── value-objects/
│   │   │   └── email.ts
│   │   ├── aggregates/
│   │   │   └── user.aggregate.ts
│   │   └── domain-events/
│   │       ├── domain-event.ts
│   │       ├── user-created.event.ts
│   │       └── user-email-changed.event.ts
│   └── use-cases/
│   │   ├── create-user.use-case.ts
│   │   ├── update-user.use-case.ts
│   └── ports/
│       └── repositories/
│       └── user-repository.port.ts
├── infrastructure/
│   ├── http/
│   ├── database/
│   └── config/
└── main.ts

This structure ensures that the core business logic is independent of external systems, making it easier to test and maintain. The adapters are responsible for connecting the core to the external systems, allowing for flexibility and scalability in the application.

Summary of Differences

✅ DDD → Defines how to model the domain with well-structured business rules. ✅ Clean Architecture → Defines the separation into layers to maintain low coupling. ✅ Hexagonal Architecture → Defines how the domain communicates with the external world through ports & adapters.

| Feature | DDD | Clean Architecture | Hexagonal Architecture | | -------------- | ------------------------------------------------- | ------------------------------------------- | ------------------------------------------------------------ | | Main Focus | Domain modeling and business rules | Separation of concerns and minimal coupling | Isolation of domain from external dependencies | | Organization | Based on entities, aggregates, services | Based on independent layers | Based on Ports & Adapters pattern | | Use Cases | Apply specific business rules | Are the central layer of the system | Encapsulated in the domain layer | | Repositories | Part of the domain (interface and implementation) | Are adapters (not part of the core) | Defined as ports (interfaces), implemented by adapters | | Infrastructure | Concrete implementations within the domain | Infrastructure is separated | Implementations reside in Adapters layer | | Dependencies | May have coupling to ORM | Does not depend on external frameworks | Domain is framework-agnostic, interfaces bridge dependencies |

MVC Architecture

MVC (Model-View-Controller) is a software architectural pattern that separates an application into three main logical components: the Model, the View, and the Controller. Each of these components is built to handle specific development aspects of an application.

  1. Model: Represents the data and the business logic of the application. It directly manages the data, logic, and rules of the application. The model responds to requests for information and updates from the view and instructions from the controller to update itself.

  2. View: Represents the UI (User Interface) of the application. It displays the data from the model to the user and sends user commands to the controller. The view is responsible for rendering the model's data in a format suitable for interaction.

  3. Controller: Acts as an intermediary between the model and the view. It listens to the input from the view, processes it (possibly altering the model's state), and returns the output display to the view. The controller handles the user input and updates the model and view accordingly.

Example Structure

src/
├── config/
│   ├── database.config.ts
│   └── app.config.ts
├── controllers/
│   ├── user.controller.ts
│   └── product.controller.ts
├── middlewares/
│   ├── auth.middleware.ts
│   └── error-handler.middleware.ts
├── models/
│   ├── user.model.ts
│   └── product.model.ts
├── views/
│   ├── user.view.ts
│   └── product.view.ts
├── routes/
│   ├── user.routes.ts
│   └── product.routes.ts
├── services/
│   ├── user.service.ts
│   └── product.service.ts
├── utils/
│   ├── date.util.ts
│   └── string.util.ts
└── main.ts

This structure ensures a clear separation of concerns, making the application easier to manage, test, and scale. The model handles the data and business logic, the view manages the presentation layer, and the controller processes user input and updates the model and view accordingly.

Serverless Architecture

Serverless Architecture is a cloud computing execution model where the cloud provider dynamically manages the allocation and provisioning of servers. In this architecture, developers can build and run applications without having to manage the underlying infrastructure. The term "serverless" is a bit of a misnomer, as servers are still involved, but the management of these servers is abstracted away from the developer.

In a serverless architecture, applications are typically composed of small, stateless functions that are triggered by events. These functions are often referred to as "Functions as a Service" (FaaS). The cloud provider automatically scales the functions in response to the number of incoming requests, ensuring that the application can handle varying levels of traffic without manual intervention.

Example Structure

src/
├── config/
│   ├── databaseConfig.ts
│   └── appConfig.ts
├── functions/
│   ├── createUser/
│   │   ├── handler.ts
│   │   ├── index.ts
│   │   └── schema.ts
│   ├── updateUser/
│   │   ├── handler.ts
│   │   ├── index.ts
│   │   └── schema.ts
│   └── deleteUser/
│       ├── handler.ts
│       ├── index.ts
│       └── schema.ts
├── models/
│   └── userModel.ts
├── services/
│   └── userService.ts
├── utils/
│   ├── dateUtil.ts
│   └── stringUtil.ts
└── serverless.yml

This structure ensures that the application is modular and each function is responsible for a specific task. The serverless.yml file is used to define the configuration for the serverless framework, specifying the functions, events that trigger them, and the resources they require.

Serverless architecture offers several benefits, including reduced operational complexity, automatic scaling, and a pay-as-you-go pricing model. It is particularly well-suited for applications with unpredictable or fluctuating workloads, as it can efficiently handle varying levels of demand without the need for manual scaling.

Conclusion

The ts-node-app CLI facilitates the creation and maintenance of project structures following well-defined architectural patterns. Use the commands above to efficiently manage your project's structure.