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

entecs

v0.0.12

Published

A simple type script oriented ECS system

Downloads

139

Readme

EntECS

EntECS is a lightweight, TypeScript first Entity Component System designed for simplicity, speed, and flexibility. It lets you easily create games, simulations, or interactive applications by organizing logic into reusable components and systems. With EntECS, adding, updating, and managing entities becomes intuitive, letting you focus on building features instead of boilerplate.

Installation

To use in your project, run:

npm i entecs

Simple Example

import { ECS } from "entecs"

const ecs = new ECS()

class Position { x = 250; y = 250 }
class Velocity { dx = 0; dy = 0 }

const entity1 = ecs.createEntity()
ecs.addComponent(entity1, new Position())
ecs.addComponent(entity1, new Velocity())

function moveSystem(deltaTime: number, ecs: ECS) {
    const components = ecs.queryComponents([Position, Velocity])
    for (const [entityId, pos, vel] of components) {
        pos.x += vel.dx * deltaTime
        pos.y += vel.dy * deltaTime
    }
}
ecs.addSystem(moveSystem, 1)

ecs.update(1)
ecs.logDebugInfo()

Features

  • Typed component management
  • Singleton component support
  • Priority-based systems
  • Event-driven engine notifications
  • Efficient query caching
  • Deferred removal
  • Serialization for persistence

Entities

In EntECS, entities are represented by an ID of type number. You can either create one entity at a time or multiple, as seen below:

ecs.createEntity() // returns a single ID
ecs.createEntities(20) // returns 20 IDs

You can also delete entities with removeEntity optionally specifying whether you want deferred removal or instant removal.

ecs.removeEntity(entity1, false)

Note, entities and components are removed using a deferred removal system by default, meaning deletions are queued and processed safely after the current update cycle to prevent iteration conflicts.

Components

Components are represented as classes with only attributes and can be added with the addComponent function.

const ecs = new ECS()
const entity1 = ecs.createEntity()

class Position { x = 250; y = 250 }
class Velocity { dx = 0; dy = 0 }
class Acceleration { x = 0; y = 0 }

ecs.addComponent(entity1, new Position())
ecs.addComponent(entity1, new Velocity())

To get a specific component on a specific entity use getComponent

ecs.getComponent(entity1, Position)

To get all components of a specific type use getComponents

ecs.getComponents(Position)

For more advanced queries, you can use queryComponents, which lets you specify both the components that must and must not be present on entities. This method returns an array of tuples in the form [entityId, ...requiredComponents][]. The first parameter defines the components that must be present, while the second parameter lists those that must be absent.

ecs.queryComponents([Position, Velocity], [Acceleration])

In this example, the query returns all entities that have both Position and Velocity components but do not have an Acceleration component.

Singleton Components

EntECS also has support for singleton components, which are components that can only ever have one instance active and are not attached to an entity. These components can be used for global state, such as keeping track of “total collisions between two entities” or “game difficulty.”

class GameDifficulty { difficulty = 1.34 }

ecs.addSingletonComponent(new GameDifficulty())
ecs.getSingletonComponent(GameDifficulty)
ecs.removeSingletonComponent(GameDifficulty)

Systems

In EntECS, systems take the form of functions with two input parameters, deltaTime and the calling ECS instance.

function moveSystem(deltaTime: number, ecs: ECS) {
    const components = ecs.queryComponents([Position, Velocity])
    for (const [entityId, pos, vel] of components) {
        pos.x += vel.dx * deltaTime
        pos.y += vel.dy * deltaTime
    }
}

To create systems in a more declarative way, we can use the createSystem function.

const moveSystem = ecs.createSystem({
    include: [Position, Velocity],
    exclude: [Acceleration],
    forEach: (deltaTime, ecs, include) => {
        const [entityId, pos, vel] = include
        pos.x += vel.dx * deltaTime
        pos.y += vel.dy * deltaTime
    }
})

The complete list of parameters accepted by createSystem is shown below:

include: ComponentClass<any>[],
exclude?: ComponentClass<any>[],
singleton?: ComponentClass<any>[],
forEach: (deltaTime, ecs, includeTuple, singletonTuple?) => void

After creating a system we need to register it with the function addSystem which takes in two parameters, the system function and a priority number. The priority number determines the order systems are called in.

ecs.addSystem(moveSystem, 1)

To call our systems, we can use the update function, passing in deltaTime.

ecs.update(1)

Serialization

EntECS supports serialization of component states into a JSON string.

const jsonString = ecs.serialize()

To deserialize our JSON string we can call deserialize which takes in our JSON string and an array of all the components we wish to reconstruct. Note that EntECS assumes components have no methods and have constructors with no required arguments.

ecs.deserialize(jsonString, [Position, Velocity, Acceleration])

Events

User Events

To create custom events you first need to create a new class specifying the content of your event. You can then emit this event with emit and listen to it with on.

class CollisionEvent{
    constructor(public id1: number, public id2: number){}
}

ecs.emit(new CollisionEvent(1, 2))

ecs.on(CollisionEvent, (event) => {
    console.log(`${event.id1} collided with ${event.id2}`)
})

Events can also be assigned a priority. However, this is off by default so it needs to be enabled first.

ecs.enableEventPriority()
ecs.emit(new CollisionEvent(1, 2), 5)

Engine Events

You can listen to a variety of engine events using the onEngineEvent function and choose a specific event to listen to from the engineEvents object. Note that engine events are disabled by default and must be enabled first.

ecs.enableEngineEvents()
ecs.onEngineEvent(ecs.engineEvents.CreateEntityEvent, (event) => {
    console.log(event.ids)
})