ecspresso 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,217 @@
1
+ # ECSpresso
2
+
3
+ *(pronounced "ex-presso")*
4
+
5
+ __Note: This is a VERY early work in progress.__
6
+
7
+ To install dependencies:
8
+
9
+ ```bash
10
+ bun install
11
+ ```
12
+
13
+ To run tests:
14
+
15
+ ```bash
16
+ bun test
17
+ ```
18
+
19
+
20
+ # ECSpresso
21
+
22
+ A lightweight, type-safe Entity Component System (ECS) library for TypeScript applications and games.
23
+
24
+ ## Overview
25
+
26
+ ECSpresso is a flexible and efficient Entity Component System implementation that provides:
27
+
28
+ - **Type-safe API**: Fully leverages TypeScript's type system for component, event, and resource definitions
29
+ - **Event System**: Built-in pub/sub event system for communication between systems
30
+ - **Resource Management**: Global state management through a dedicated resource manager
31
+ - **Bundle System**: Modular and reusable collections of components, resources, and systems
32
+ - **Query System**: Efficient entity filtering based on component presence/absence
33
+
34
+ ## Core Concepts
35
+
36
+ ### Entity Component System
37
+
38
+ The ECS pattern separates data (Components) from behavior (Systems) through Entities:
39
+
40
+ - **Entities**: Unique identifiers that components can be attached to
41
+ - **Components**: Plain data objects that hold state but no behavior
42
+ - **Systems**: Logic that processes entities with specific components
43
+ - **Resources**: Global state shared between systems
44
+ - **Events**: Messages passed between systems
45
+
46
+ ### Key Features
47
+
48
+ - Type-safe queries to filter entities based on component combinations
49
+ - Fluent builder API for creating systems and bundles
50
+ - Event handling with lifecycle hooks for systems
51
+ - Resource management for global state
52
+
53
+ ## Installation
54
+
55
+ ```bash
56
+ # Add the library to your project
57
+ npm install ecspresso
58
+ ```
59
+
60
+ ## Usage
61
+
62
+ ### Basic Setup
63
+
64
+ ```typescript
65
+ import ECSpresso, { Bundle } from 'ecspresso';
66
+
67
+ // Define your component types
68
+ interface Position {
69
+ x: number;
70
+ y: number;
71
+ }
72
+
73
+ interface Velocity {
74
+ dx: number;
75
+ dy: number;
76
+ }
77
+
78
+ // Define your event types
79
+ interface CollisionEvent {
80
+ entityA: number;
81
+ entityB: number;
82
+ }
83
+
84
+ // Define your resource types
85
+ interface GameState {
86
+ score: number;
87
+ level: number;
88
+ }
89
+
90
+ // Create an ECS instance with your types
91
+ const ecs = new ECSpresso<
92
+ { position: Position; velocity: Velocity },
93
+ { collision: CollisionEvent },
94
+ { gameState: GameState }
95
+ >();
96
+
97
+ // Add resources
98
+ ecs.addResource('gameState', { score: 0, level: 1 });
99
+
100
+ // Create an entity
101
+ const entityId = ecs.createEntity();
102
+
103
+ // Add components to the entity
104
+ ecs.addComponent(entityId, 'position', { x: 0, y: 0 });
105
+ ecs.addComponent(entityId, 'velocity', { dx: 1, dy: 2 });
106
+
107
+ // Run the simulation
108
+ ecs.update(16.67); // Pass delta time in ms
109
+ ```
110
+
111
+ ### Creating Systems
112
+
113
+ ```typescript
114
+ // Create a movement system
115
+ const movementSystem = ecs.entityManager
116
+ .createSystem('movement')
117
+ .addQuery('movable', {
118
+ with: ['position', 'velocity']
119
+ })
120
+ .setProcess((queries, deltaTime) => {
121
+ // Process entities with both position and velocity
122
+ for (const entity of queries.movable) {
123
+ const { position, velocity } = entity.components;
124
+ position.x += velocity.dx * (deltaTime / 1000);
125
+ position.y += velocity.dy * (deltaTime / 1000);
126
+ }
127
+ });
128
+
129
+ // Add the system to the ECS
130
+ ecs.addSystem(movementSystem);
131
+ ```
132
+
133
+ ### Using Bundles
134
+
135
+ ```typescript
136
+ // Create a physics bundle
137
+ const physicsBundle = new Bundle<
138
+ { position: Position; velocity: Velocity },
139
+ { collision: CollisionEvent },
140
+ {}
141
+ >('physics');
142
+
143
+ // Add a collision system to the bundle
144
+ physicsBundle
145
+ .addSystem('collision')
146
+ .addQuery('collidable', {
147
+ with: ['position']
148
+ })
149
+ .setProcess((queries, deltaTime, entityManager, resourceManager, eventBus) => {
150
+ // Check for collisions
151
+ // ...
152
+ // Emit collision events
153
+ eventBus.emit('collision', { entityA: 1, entityB: 2 });
154
+ });
155
+
156
+ // Install the bundle
157
+ ecs.install(physicsBundle);
158
+ ```
159
+
160
+ ### Event Handling
161
+
162
+ ```typescript
163
+ // Create a system that handles collision events
164
+ const scoreSystem = ecs.entityManager
165
+ .createSystem('score')
166
+ .setEventHandlers({
167
+ collision: {
168
+ handler: (event, entityManager, resourceManager) => {
169
+ // Handle collision event
170
+ const gameState = resourceManager.getResource('gameState');
171
+ if (gameState) {
172
+ gameState.score += 10;
173
+ }
174
+ }
175
+ }
176
+ });
177
+
178
+ // Add the system to the ECS
179
+ ecs.addSystem(scoreSystem);
180
+ ```
181
+
182
+ ## Advanced Features
183
+
184
+ ### Merging Bundles
185
+
186
+ ```typescript
187
+ import { mergeBundles } from 'ecspresso';
188
+
189
+ // Merge multiple bundles into one
190
+ const gameBundle = mergeBundles(
191
+ 'game',
192
+ physicsBundle,
193
+ renderBundle,
194
+ inputBundle
195
+ );
196
+
197
+ // Install the merged bundle
198
+ ecs.install(gameBundle);
199
+ ```
200
+
201
+ ### System Lifecycle Hooks
202
+
203
+ ```typescript
204
+ // Create a system with lifecycle hooks
205
+ const renderSystem = ecs.entityManager
206
+ .createSystem('render')
207
+ .setOnAttach((entityManager, resourceManager, eventBus) => {
208
+ // Initialize rendering resources
209
+ console.log('Render system attached');
210
+ })
211
+ .setOnDetach((entityManager, resourceManager, eventBus) => {
212
+ // Clean up rendering resources
213
+ console.log('Render system detached');
214
+ });
215
+ ```
216
+
217
+ This project was created using `bun init` in bun v1.2.4. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ class M{nextId=1;entities=new Map;componentIndices=new Map;createEntity(){let f=this.nextId++,g={id:f,components:{}};return this.entities.set(f,g),g}addComponent(f,g,E){let J=typeof f==="number"?this.entities.get(f):f;if(!J)throw new Error(`Entity ${f} does not exist`);if(J.components[g]=E,!this.componentIndices.has(g))this.componentIndices.set(g,new Set);return this.componentIndices.get(g)?.add(J.id),this}removeComponent(f,g){let E=this.entities.get(f);if(!E)throw new Error(`Entity ${f} does not exist`);delete E.components[g],this.componentIndices.get(g)?.delete(f)}getComponent(f,g){let E=this.entities.get(f);if(!E)throw new Error(`Entity ${f} does not exist`);return E.components[g]||null}getEntitiesWithComponents(f=[],g=[]){if(f.length===0){if(g.length===0)return Array.from(this.entities.values());return Array.from(this.entities.values()).filter((j)=>{return g.every((F)=>!(F in j.components))})}let E=f.reduce((j,F)=>{let K=this.componentIndices.get(F),U=K?K.size:0,X=this.componentIndices.get(j)?.size??1/0;return U<X?F:j},f[0]);return Array.from(this.componentIndices.get(E)||[]).filter((j)=>{let F=this.entities.get(j);return F&&f.every((K)=>(K in F.components))&&g.every((K)=>!(K in F.components))}).map((j)=>this.entities.get(j))}removeEntity(f){let g=this.entities.get(f);if(!g)return!1;for(let E of Object.keys(g.components))this.componentIndices.get(E)?.delete(f);return this.entities.delete(f)}getEntity(f){return this.entities.get(f)}}class P{handlers=new Map;subscribe(f,g){return this.addHandler(f,g,!1)}once(f,g){return this.addHandler(f,g,!0)}addHandler(f,g,E){if(!this.handlers.has(f))this.handlers.set(f,[]);let J={callback:g,once:E};return this.handlers.get(f).push(J),()=>{let j=this.handlers.get(f);if(j){let F=j.indexOf(J);if(F!==-1)j.splice(F,1)}}}publish(f,g=void 0){let E=this.handlers.get(f);if(!E)return;let J=[...E],j=[];for(let F of J)if(F.callback(g),F.once)j.push(F);if(j.length>0)for(let F of j){let K=E.indexOf(F);if(K!==-1)E.splice(K,1)}}clear(){this.handlers.clear()}clearEvent(f){this.handlers.delete(f)}}class Q{resources=new Map;add(f,g){return this.resources.set(f,g),g}get(f){let g=this.resources.get(f);if(g===void 0)throw new Error(`Resource ${String(f)} not found`);return g}getOptional(f){return this.resources.get(f)}has(f){return this.resources.has(f)}remove(f){return this.resources.delete(f)}getKeys(){return Array.from(this.resources.keys())}}var Y="0.0.0";class V{static VERSION=Y;_entityManager;_systems=[];_eventBus;_resourceManager;_installedBundles=new Set;constructor(){this._entityManager=new M,this._eventBus=new P,this._resourceManager=new Q}install(...f){for(let g of f){if(this._installedBundles.has(g.id)){console.warn(`Bundle ${g.id} is already installed`);continue}let E=g.getSystems();if(!E.length)console.warn(`Bundle ${g.id} has no systems`);for(let j of E){let F=j;if(this._systems.push(F),F.onAttach)F.onAttach(this._entityManager,this._resourceManager,this._eventBus);if(F.eventHandlers)for(let K in F.eventHandlers){let U=F.eventHandlers[K];if(U?.handler){let X=(Z)=>{U.handler(Z,this._entityManager,this._resourceManager,this._eventBus)};this._eventBus.subscribe(K,X)}}}let J=g.getResources();for(let[j,F]of J.entries())this._resourceManager.add(j,F);this._installedBundles.add(g.id)}return this}removeSystem(f){let g=this._systems.findIndex((J)=>J.label===f);if(g===-1)return!1;let E=this._systems[g];if(!E)return!1;return E.onDetach?.(this._entityManager,this._resourceManager,this._eventBus),this._systems.splice(g,1),!0}hasResource(f){return this._resourceManager.has(f)}getResource(f){return this._resourceManager.getOptional(f)}getResourceOrThrow(f){return this._resourceManager.get(f)}addResource(f,g){return this._resourceManager.add(f,g),this}hasComponent(f,g){return this._entityManager.getComponent(f,g)!==null}getEntitiesWithComponents(f,g=[]){return this._entityManager.getEntitiesWithComponents(f,g)}update(f){for(let g of this._systems){if(!g.process)continue;let E={};if(g.entityQueries){for(let J in g.entityQueries){let j=g.entityQueries[J];if(j)E[J]=this._entityManager.getEntitiesWithComponents(j.with,j.without||[])}g.process(E,f,this._entityManager,this._resourceManager,this._eventBus)}else g.process([],f,this._entityManager,this._resourceManager,this._eventBus)}}get entityManager(){return this._entityManager}get eventBus(){return this._eventBus}get resourceManager(){return this._resourceManager}get installedBundles(){return Array.from(this._installedBundles)}}function $(){return`bundle_${Date.now().toString(36)}_${Math.random().toString(36).substring(2,9)}`}class L{_systems=[];_resources=new Map;_id;constructor(f){this._id=f||$()}get id(){return this._id}set id(f){this._id=f}addSystem(f){let g=new W(f,this);return this._systems.push(g),g}addResource(f,g){return this._resources.set(f,g),this}getSystems(){return this._systems.map((f)=>f.build())}getResources(){return new Map(this._resources)}getResource(f){return this._resources.get(f)}getSystemBuilders(){return[...this._systems]}hasResource(f){return this._resources.has(f)}}function D(f,...g){if(g.length===0)return new L(f);let E=new L(f);for(let J of g){for(let j of J.getSystemBuilders())E.addSystem(j);for(let[j,F]of J.getResources().entries())E.addResource(j,F)}return E}class W{_label;_bundle;queries={};processFunction;attachFunction;detachFunction;eventHandlers;constructor(f,g=new L){this._label=f;this._bundle=g}get label(){return this._label}get bundle(){return this._bundle}addQuery(f,g){let E=this;return E.queries={...this.queries,[f]:g},E}setProcess(f){return this.processFunction=f,this}setOnAttach(f){return this.attachFunction=f,this}setOnDetach(f){return this.detachFunction=f,this}setEventHandlers(f){return this.eventHandlers=f,this}build(){let f={label:this._label,entityQueries:this.queries};if(this.processFunction)f.process=this.processFunction;if(this.attachFunction)f.onAttach=this.attachFunction;if(this.detachFunction)f.onDetach=this.detachFunction;if(this.eventHandlers)f.eventHandlers=this.eventHandlers;return f}}var c=V;export{D as mergeBundles,c as default,W as SystemBuilder,Q as ResourceManager,P as EventBus,M as EntityManager,L as Bundle};
2
+
3
+ //# debugId=7DD37829380BFEFA64756E2164756E21
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,16 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/entity-manager.ts", "../src/event-bus.ts", "../src/resource-manager.ts", "../src/ecspresso.ts", "../src/bundle.ts", "../src/system-builder.ts", "../src/index.ts"],
4
+ "sourcesContent": [
5
+ "import type { Entity, FilteredEntity } from \"./types\";\n\nexport default\nclass EntityManager<ComponentTypes> {\n\tprivate nextId: number = 1;\n\tprivate entities: Map<number, Entity<ComponentTypes>> = new Map();\n\tprivate componentIndices: Map<keyof ComponentTypes, Set<number>> = new Map();\n\t\n\tcreateEntity(): Entity<ComponentTypes> {\n\t\tconst id = this.nextId++;\n\t\tconst entity: Entity<ComponentTypes> = { id, components: {} };\n\t\tthis.entities.set(id, entity);\n\t\treturn entity;\n\t}\n\n\t// TODO: Component object pooling if(/when) garbage collection is an issue...?\n\taddComponent<ComponentName extends keyof ComponentTypes>(\n\t\tentityOrId: number | Entity<ComponentTypes>,\n\t\tcomponentName: ComponentName,\n\t\tdata: ComponentTypes[ComponentName]\n\t) {\n\t\tconst entity = typeof entityOrId === 'number' ?\n\t\t\tthis.entities.get(entityOrId) :\n\t\t\tentityOrId;\n\n\t\tif (!entity) throw new Error(`Entity ${entityOrId} does not exist`);\n\n\t\tentity.components[componentName] = data;\n\t\t\n\t\t// Update component index\n\t\tif (!this.componentIndices.has(componentName)) {\n\t\t\tthis.componentIndices.set(componentName, new Set());\n\t\t}\n\t\tthis.componentIndices.get(componentName)?.add(entity.id);\n\t\treturn this;\n\t}\n\n\tremoveComponent<ComponentName extends keyof ComponentTypes>(entityId: number, componentName: ComponentName) {\n\t\tconst entity = this.entities.get(entityId);\n\t\tif (!entity) throw new Error(`Entity ${entityId} does not exist`);\n\n\t\tdelete entity.components[componentName];\n\t\t\n\t\t// Update component index\n\t\tthis.componentIndices.get(componentName)?.delete(entityId);\n\t}\n\n\tgetComponent<ComponentName extends keyof ComponentTypes>(entityId: number, componentName: ComponentName): ComponentTypes[ComponentName] | null {\n\t\tconst entity = this.entities.get(entityId);\n\n\t\tif (!entity) throw new Error(`Entity ${entityId} does not exist`);\n\n\t\treturn entity.components[componentName] || null;\n\t}\n\n\tgetEntitiesWithComponents<\n\t\tWithComponents extends keyof ComponentTypes = never,\n\t\tWithoutComponents extends keyof ComponentTypes = never\n\t>(\n\t\trequired: ReadonlyArray<WithComponents> = [] as any, \n\t\texcluded: ReadonlyArray<WithoutComponents> = [] as any,\n\t): Array<FilteredEntity<ComponentTypes, WithComponents extends never ? never : WithComponents, WithoutComponents extends never ? never : WithoutComponents>> {\n\t\t// Use the smallest component set as base for better performance\n\t\tif (required.length === 0) {\n\t\t\tif (excluded.length === 0) {\n\t\t\t\treturn Array.from(this.entities.values()) as any;\n\t\t\t}\n\n\t\t\treturn Array\n\t\t\t\t.from(this.entities.values())\n\t\t\t\t.filter((entity) => {\n\t\t\t\t\treturn excluded.every(comp => !(comp in entity.components));\n\t\t\t\t}) as any;\n\t\t}\n\t\t\n\t\t// Find the component with the smallest entity set to start with\n\t\tconst smallestComponent = required.reduce((smallest, comp) => {\n\t\t\tconst set = this.componentIndices.get(comp);\n\t\t\tconst currentSize = set ? set.size : 0;\n\t\t\tconst smallestSize = this.componentIndices.get(smallest!)?.size ?? Infinity;\n\t\t\t\n\t\t\treturn currentSize < smallestSize ? comp : smallest;\n\t\t}, required[0])!;\n\n\t\t// Start with the entities from the smallest component set\n\t\tconst candidates = Array.from(this.componentIndices.get(smallestComponent) || []);\n\n\t\t// Return full entity objects, not just IDs\n\t\treturn candidates\n\t\t\t.filter(id => {\n\t\t\t\tconst entity = this.entities.get(id);\n\t\t\t\treturn (\n\t\t\t\t\tentity &&\n\t\t\t\t\trequired.every(comp => comp in entity.components) && \n\t\t\t\t\texcluded.every(comp => !(comp in entity.components))\n\t\t\t\t);\n\t\t\t})\n\t\t\t.map(id => this.entities.get(id)!) as Array<FilteredEntity<ComponentTypes, WithComponents extends never ? never : WithComponents, WithoutComponents extends never ? never : WithoutComponents>>;\n\t}\n\n\tremoveEntity(entityId: number): boolean {\n\t\tconst entity = this.entities.get(entityId);\n\t\tif (!entity) return false;\n\t\t\n\t\t// Remove entity from all component indices\n\t\tfor (const componentName of Object.keys(entity.components) as Array<keyof ComponentTypes>) {\n\t\t\tthis.componentIndices.get(componentName)?.delete(entityId);\n\t\t}\n\t\t\n\t\t// Remove the entity itself\n\t\treturn this.entities.delete(entityId);\n\t}\n\n\tgetEntity(entityId: number): Entity<ComponentTypes> | undefined {\n\t\treturn this.entities.get(entityId);\n\t}\n}\n",
6
+ "import type { EventHandler } from \"./types\";\n\nexport default\nclass EventBus<EventTypes> {\n\tprivate handlers: Map<keyof EventTypes, Array<EventHandler<any>>> = new Map();\n\n\t/**\n\t * Subscribe to an event\n\t */\n\tsubscribe<E extends keyof EventTypes>(\n\t\teventType: E,\n\t\tcallback: (data: EventTypes[E]) => void\n\t): () => void {\n\t\treturn this.addHandler(eventType, callback, false);\n\t}\n\n\t/**\n\t * Subscribe to an event once\n\t */\n\tonce<E extends keyof EventTypes>(\n\t\teventType: E,\n\t\tcallback: (data: EventTypes[E]) => void\n\t): () => void {\n\t\treturn this.addHandler(eventType, callback, true);\n\t}\n\n\t/**\n\t * Internal method to add an event handler\n\t */\n\tprivate addHandler<E extends keyof EventTypes>(\n\t\teventType: E,\n\t\tcallback: (data: EventTypes[E]) => void,\n\t\tonce: boolean\n\t): () => void {\n\t\tif (!this.handlers.has(eventType)) {\n\t\t\tthis.handlers.set(eventType, []);\n\t\t}\n\n\t\tconst handler: EventHandler<EventTypes[E]> = {\n\t\t\tcallback,\n\t\t\tonce\n\t\t};\n\n\t\tthis.handlers.get(eventType)!.push(handler);\n\n\t\t// Return unsubscribe function\n\t\treturn () => {\n\t\t\tconst handlers = this.handlers.get(eventType);\n\t\t\tif (handlers) {\n\t\t\t\tconst index = handlers.indexOf(handler);\n\t\t\t\tif (index !== -1) {\n\t\t\t\t\thandlers.splice(index, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\tpublish<E extends keyof EventTypes>(\n\t\teventType: E,\n\t\tdata: EventTypes[E] = undefined as EventTypes[E]\n\t): void {\n\t\tconst handlers = this.handlers.get(eventType);\n\t\tif (!handlers) return;\n\n\t\t// Create a copy of handlers to avoid issues with handlers that modify the array\n\t\tconst handlersToCall = [...handlers];\n\t\t\n\t\t// Call all handlers and collect handlers to remove\n\t\tconst handlersToRemove: EventHandler<any>[] = [];\n\t\t\n\t\tfor (const handler of handlersToCall) {\n\t\t\thandler.callback(data);\n\t\t\tif (handler.once) {\n\t\t\t\thandlersToRemove.push(handler);\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (handlersToRemove.length > 0) {\n\t\t\tfor (const handler of handlersToRemove) {\n\t\t\t\tconst index = handlers.indexOf(handler);\n\t\t\t\tif (index !== -1) {\n\t\t\t\t\thandlers.splice(index, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tclear(): void {\n\t\tthis.handlers.clear();\n\t}\n\n\tclearEvent<E extends keyof EventTypes>(eventType: E): void {\n\t\tthis.handlers.delete(eventType);\n\t}\n}\n",
7
+ "export default\nclass ResourceManager<ResourceTypes extends Record<string, any> = Record<string, any>> {\n\tprivate resources: Map<keyof ResourceTypes, ResourceTypes[keyof ResourceTypes]> = new Map();\n\n\t/**\n\t * Add a resource to the manager\n\t * @param label The resource key\n\t * @param resource The resource value\n\t * @returns The added resource\n\t */\n\tadd<K extends keyof ResourceTypes>(label: K, resource: ResourceTypes[K]): ResourceTypes[K] {\n\t\tthis.resources.set(label, resource);\n\t\treturn resource;\n\t}\n\n\t/**\n\t * Get a resource from the manager\n\t * @param label The resource key\n\t * @returns The resource value\n\t * @throws Error if resource not found\n\t */\n\tget<K extends keyof ResourceTypes>(label: K): ResourceTypes[K] {\n\t\tconst resource = this.resources.get(label);\n\t\tif (resource === undefined) {\n\t\t\tthrow new Error(`Resource ${String(label)} not found`);\n\t\t}\n\t\treturn resource as ResourceTypes[K];\n\t}\n\n\t/**\n\t * Get a resource from the manager, returning undefined if not found\n\t * @param label The resource key\n\t * @returns The resource value or undefined if not found\n\t */\n\tgetOptional<K extends keyof ResourceTypes>(label: K): ResourceTypes[K] | undefined {\n\t\tconst resource = this.resources.get(label);\n\t\treturn resource as ResourceTypes[K] | undefined;\n\t}\n\n\t/**\n\t * Check if a resource exists\n\t * @param label The resource key\n\t * @returns True if the resource exists\n\t */\n\thas<K extends keyof ResourceTypes>(label: K): boolean {\n\t\treturn this.resources.has(label);\n\t}\n\n\t/**\n\t * Remove a resource\n\t * @param label The resource key\n\t * @returns True if the resource was removed\n\t */\n\tremove<K extends keyof ResourceTypes>(label: K): boolean {\n\t\treturn this.resources.delete(label);\n\t}\n\n\t/**\n\t * Get all resource keys\n\t * @returns Array of resource keys\n\t */\n\tgetKeys(): Array<keyof ResourceTypes> {\n\t\treturn Array.from(this.resources.keys());\n\t}\n}\n",
8
+ "import EntityManager from \"./entity-manager\";\nimport EventBus from \"./event-bus\";\nimport ResourceManager from \"./resource-manager\";\nimport type { System } from \"./types\";\nimport type Bundle from \"./bundle\";\nimport { version } from \"../package.json\";\n\n\nexport default\nclass ECSpresso<\n\tComponentTypes extends Record<string, any> = Record<string, any>,\n\tEventTypes extends Record<string, any> = Record<string, any>,\n\tResourceTypes extends Record<string, any> = Record<string, any>,\n> {\n\tpublic static readonly VERSION = version;\n\tprivate _entityManager: EntityManager<ComponentTypes>;\n\tprivate _systems: System<ComponentTypes, any, any, EventTypes, ResourceTypes>[] = [];\n\tprivate _eventBus: EventBus<EventTypes>;\n\tprivate _resourceManager: ResourceManager<ResourceTypes>;\n\tprivate _installedBundles: Set<string> = new Set();\n\n\tconstructor() {\n\t\tthis._entityManager = new EntityManager<ComponentTypes>();\n\t\tthis._eventBus = new EventBus<EventTypes>();\n\t\tthis._resourceManager = new ResourceManager<ResourceTypes>();\n\t}\n\n\t/**\n\t * Install one or more bundles into this ECS instance\n\t */\n\tinstall<\n\t\tBundles extends Array<Bundle<any, any, any>>\n\t>(...bundles: Bundles): this {\n\t\tfor (const bundle of bundles) {\n\t\t\t// Check if this bundle is already installed\n\t\t\tif (this._installedBundles.has(bundle.id)) {\n\t\t\t\tconsole.warn(`Bundle ${bundle.id} is already installed`);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst systems = bundle.getSystems();\n\n\t\t\t// Check if bundle has systems\n\t\t\tif (!systems.length) {\n\t\t\t\tconsole.warn(`Bundle ${bundle.id} has no systems`);\n\t\t\t}\n\n\t\t\t// Register all systems from the bundle\n\t\t\tfor (const system of systems) {\n\t\t\t\t// Need to cast here because we can't fully type the system generics\n\t\t\t\tconst typedSystem = system as unknown as System<ComponentTypes, any, any, EventTypes, ResourceTypes>;\n\t\t\t\tthis._systems.push(typedSystem);\n\n\t\t\t\t// Call onAttach lifecycle hook if defined\n\t\t\t\tif (typedSystem.onAttach) {\n\t\t\t\t\ttypedSystem.onAttach(\n\t\t\t\t\t\tthis._entityManager,\n\t\t\t\t\t\tthis._resourceManager,\n\t\t\t\t\t\tthis._eventBus\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Auto-subscribe to events if eventHandlers are defined\n\t\t\t\tif (typedSystem.eventHandlers) {\n\t\t\t\t\tfor (const eventName in typedSystem.eventHandlers) {\n\t\t\t\t\t\tconst handler = typedSystem.eventHandlers[eventName];\n\t\t\t\t\t\tif (handler?.handler) {\n\t\t\t\t\t\t\t// Create a wrapper that passes the additional parameters to the handler\n\t\t\t\t\t\t\tconst wrappedHandler = (data: any) => {\n\t\t\t\t\t\t\t\thandler.handler(\n\t\t\t\t\t\t\t\t\tdata,\n\t\t\t\t\t\t\t\t\tthis._entityManager,\n\t\t\t\t\t\t\t\t\tthis._resourceManager,\n\t\t\t\t\t\t\t\t\tthis._eventBus\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tthis._eventBus.subscribe(eventName, wrappedHandler);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Register all resources from the bundle\n\t\t\tconst resources = bundle.getResources();\n\t\t\tfor (const [key, value] of resources.entries()) {\n\t\t\t\t// We need to cast here because TypeScript can't verify the type compatibility\n\t\t\t\t// between bundles, but we trust that the bundle's resource types are compatible\n\t\t\t\tthis._resourceManager.add(key as unknown as keyof ResourceTypes, value as any);\n\t\t\t}\n\n\t\t\t// Mark this bundle as installed\n\t\t\tthis._installedBundles.add(bundle.id);\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Remove a system by its label\n\t */\n\tremoveSystem(label: string): boolean {\n\t\tconst index = this._systems.findIndex(system => system.label === label);\n\t\tif (index === -1) return false;\n\n\t\tconst system = this._systems[index];\n\t\tif (!system) return false;\n\n\t\tsystem.onDetach?.(\n\t\t\tthis._entityManager,\n\t\t\tthis._resourceManager,\n\t\t\tthis._eventBus\n\t\t);\n\n\t\t// Remove system\n\t\tthis._systems.splice(index, 1);\n\t\treturn true;\n\t}\n\n\t/**\n\t * Check if a resource exists\n\t */\n\thasResource<K extends keyof ResourceTypes>(key: K): boolean {\n\t\treturn this._resourceManager.has(key);\n\t}\n\n\t/**\n\t * Get a resource if it exists, or undefined if not\n\t */\n\tgetResource<K extends keyof ResourceTypes>(key: K): ResourceTypes[K] | undefined {\n\t\treturn this._resourceManager.getOptional(key);\n\t}\n\n\t/**\n\t * Get a resource, throws error if not found\n\t */\n\tgetResourceOrThrow<K extends keyof ResourceTypes>(key: K): ResourceTypes[K] {\n\t\treturn this._resourceManager.get(key);\n\t}\n\n\t/**\n\t * Add a resource to the ECS instance\n\t */\n\taddResource<K extends keyof ResourceTypes>(key: K, resource: ResourceTypes[K]): this {\n\t\tthis._resourceManager.add(key, resource);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Check if an entity has a component\n\t */\n\thasComponent<K extends keyof ComponentTypes>(\n\t\tentityId: number,\n\t\tcomponentName: K\n\t): boolean {\n\t\tconst component = this._entityManager.getComponent(entityId, componentName);\n\t\treturn component !== null;\n\t}\n\n\t/**\n\t * Get all entities with specific components\n\t */\n\tgetEntitiesWithComponents(\n\t\twithComponents: (keyof ComponentTypes)[],\n\t\twithoutComponents: (keyof ComponentTypes)[] = []\n\t) {\n\t\treturn this._entityManager.getEntitiesWithComponents(\n\t\t\twithComponents,\n\t\t\twithoutComponents\n\t\t);\n\t}\n\n\t/**\n\t * Update all systems\n\t */\n\tupdate(deltaTime: number) {\n\t\tfor (const system of this._systems) {\n\t\t\tif (!system.process) continue;\n\n\t\t\t// Prepare query results\n\t\t\tconst queryResults: Record<string, any[]> = {};\n\n\t\t\t// Process entity queries if defined\n\t\t\tif (system.entityQueries) {\n\t\t\t\tfor (const queryName in system.entityQueries) {\n\t\t\t\t\tconst query = system.entityQueries[queryName];\n\t\t\t\t\tif (query) {\n\t\t\t\t\t\tqueryResults[queryName] = this._entityManager.getEntitiesWithComponents(\n\t\t\t\t\t\t\tquery.with,\n\t\t\t\t\t\t\tquery.without || []\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Call the system's process method\n\t\t\t\tsystem.process(\n\t\t\t\t\tqueryResults,\n\t\t\t\t\tdeltaTime,\n\t\t\t\t\tthis._entityManager,\n\t\t\t\t\tthis._resourceManager,\n\t\t\t\t\tthis._eventBus\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// No queries defined, pass an empty array\n\t\t\t\tsystem.process(\n\t\t\t\t\t[],\n\t\t\t\t\tdeltaTime,\n\t\t\t\t\tthis._entityManager,\n\t\t\t\t\tthis._resourceManager,\n\t\t\t\t\tthis._eventBus\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Getters for the internal managers\n\tget entityManager() {\n\t\treturn this._entityManager;\n\t}\n\n\tget eventBus() {\n\t\treturn this._eventBus;\n\t}\n\n\tget resourceManager() {\n\t\treturn this._resourceManager;\n\t}\n\n\t/**\n\t * Get all installed bundle IDs\n\t */\n\tget installedBundles(): string[] {\n\t\treturn Array.from(this._installedBundles);\n\t}\n}\n",
9
+ "import { SystemBuilder } from './system-builder';\n\n/**\n * Generates a unique ID for a bundle\n */\nfunction generateBundleId(): string {\n\treturn `bundle_${Date.now().toString(36)}_${Math.random().toString(36).substring(2, 9)}`;\n}\n\n/**\n * Bundle class that encapsulates a set of components, resources, events, and systems\n * that can be merged into a ECSpresso instance\n */\nexport default class Bundle<\n\tComponentTypes extends Record<string, any> = Record<string, any>,\n\tEventTypes extends Record<string, any> = Record<string, any>,\n\tResourceTypes extends Record<string, any> = Record<string, any>,\n> {\n\tprivate _systems: SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, any>[] = [];\n\tprivate _resources: Map<keyof ResourceTypes, ResourceTypes[keyof ResourceTypes]> = new Map();\n\tprivate _id: string;\n\n\tconstructor(id?: string) {\n\t\tthis._id = id || generateBundleId();\n\t}\n\n\t/**\n\t * Get the unique ID of this bundle\n\t */\n\tget id(): string {\n\t\treturn this._id;\n\t}\n\n\t/**\n\t * Set the ID of this bundle\n\t * @internal Used by combineBundles\n\t */\n\tset id(value: string) {\n\t\tthis._id = value;\n\t}\n\n\t/**\n\t * Add a system to this bundle\n\t */\n\taddSystem(label: string) {\n\t\tconst system = new SystemBuilder(label, this);\n\n\t\tthis._systems.push(system);\n\n\t\treturn system;\n\t}\n\n\t/**\n\t * Add a resource to this bundle\n\t * @param label The resource key\n\t * @param resource The resource value\n\t */\n\taddResource<K extends keyof ResourceTypes>(label: K, resource: ResourceTypes[K]) {\n\t\tthis._resources.set(label, resource);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Get all systems defined in this bundle\n\t * Returns built System objects instead of SystemBuilders\n\t */\n\tgetSystems() {\n\t\treturn this._systems.map(system => system.build());\n\t}\n\n\t/**\n\t * Get all resources defined in this bundle\n\t */\n\tgetResources(): Map<keyof ResourceTypes, ResourceTypes[keyof ResourceTypes]> {\n\t\treturn new Map(this._resources);\n\t}\n\n\t/**\n\t * Get a specific resource by key\n\t * @param key The resource key\n\t * @returns The resource value or undefined if not found\n\t */\n\tgetResource<K extends keyof ResourceTypes>(key: K): ResourceTypes[K] | undefined {\n\t\treturn this._resources.get(key) as ResourceTypes[K] | undefined;\n\t}\n\n\t/**\n\t * Get all system builders in this bundle\n\t */\n\tgetSystemBuilders(): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, any>[] {\n\t\treturn [...this._systems];\n\t}\n\n\t/**\n\t * Check if this bundle has a specific resource\n\t * @param key The resource key to check\n\t * @returns True if the resource exists\n\t */\n\thasResource<K extends keyof ResourceTypes>(key: K): boolean {\n\t\treturn this._resources.has(key);\n\t}\n}\n\n/**\n * Utility type for merging two types\n */\n// This sets props with the same name but different type to \"never\". Maybe we want this?\nexport type Merge<T1, T2> = T1 & T2;\n// This makes the later prop types override the earlier ones. Maybe we want this instead?\n// export type Merge<T1, T2> = Omit<T1, keyof T2> & T2;\n// Or maybe this, which sets props with the same name to a union of the two types\n// export type Merge<T1, T2> = {\n// \t[K in keyof T1 | keyof T2]: K extends keyof T1 & keyof T2\n// \t\t? T1[K] | T2[K]\n// \t\t: K extends keyof T1\n// \t\t\t? T1[K]\n// \t\t\t: K extends keyof T2\n// \t\t\t\t? T2[K]\n// \t\t\t\t: never;\n// };\n\nexport type MergeAll<T extends any[]> = T extends [infer First, ...infer Rest] ?\n\tRest extends [] ?\n\t\tFirst: Merge<First, MergeAll<Rest>>:\n\t{};\n\nexport function mergeBundles<\n\tBundles extends Array<Bundle<any, any, any>>\n>(\n\tid: string,\n\t...bundles: Bundles\n): Bundle<\n\tMergeAll<{ [K in keyof Bundles]: Bundles[K] extends Bundle<infer C, any, any> ? C : never }>,\n\tMergeAll<{ [K in keyof Bundles]: Bundles[K] extends Bundle<any, infer E, any> ? E : never }>,\n\tMergeAll<{ [K in keyof Bundles]: Bundles[K] extends Bundle<any, any, infer R> ? R : never }>\n> {\n\tif (bundles.length === 0) {\n\t\treturn new Bundle(id);\n\t}\n\n\tconst combined = new Bundle(id);\n\n\tfor (const bundle of bundles) {\n\t\tfor (const system of bundle.getSystemBuilders()) {\n\t\t\tcombined.addSystem(system as any);\n\t\t}\n\n\t\t// Add resources from this bundle\n\t\tfor (const [label, resource] of bundle.getResources().entries()) {\n\t\t\tcombined.addResource(label as any, resource);\n\t\t}\n\t}\n\n\treturn combined as any;\n}\n",
10
+ "import Bundle from \"./bundle\";\nimport type EntityManager from \"./entity-manager\";\nimport type EventBus from \"./event-bus\";\nimport type ResourceManager from \"./resource-manager\";\nimport type { FilteredEntity, System } from \"./types\";\n\n/**\n * Builder class for creating type-safe ECS Systems with proper query inference\n */\nexport class SystemBuilder<\n\tComponentTypes extends Record<string, any> = Record<string, any>,\n\tEventTypes extends Record<string, any> = Record<string, any>,\n\tResourceTypes extends Record<string, any> = Record<string, any>,\n\tQueries extends Record<string, QueryDefinition<ComponentTypes>> = {},\n> {\n\tprivate queries: Queries = {} as Queries;\n\tprivate processFunction?: ProcessFunction<ComponentTypes, EventTypes, ResourceTypes, Queries>;\n\tprivate attachFunction?: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>;\n\tprivate detachFunction?: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>;\n\tprivate eventHandlers?: {\n\t\t[EventName in keyof EventTypes]?: {\n\t\t\thandler(\n\t\t\t\tdata: EventTypes[EventName],\n\t\t\t\tentityManager: EntityManager<ComponentTypes>,\n\t\t\t\tresourceManager: ResourceManager<ResourceTypes>,\n\t\t\t\teventBus: EventBus<EventTypes>,\n\t\t\t): void;\n\t\t};\n\t};\n\n\tconstructor(\n\t\tprivate _label: string,\n\t\tprivate _bundle = new Bundle<ComponentTypes, EventTypes, ResourceTypes>()\n\t) {}\n\n\tget label() {\n\t\treturn this._label;\n\t}\n\n\tget bundle() {\n\t\treturn this._bundle;\n\t}\n\n\t/**\n\t * Add a query definition to the system\n\t */\n\taddQuery<\n\t\tQueryName extends string,\n\t\tWithComponents extends keyof ComponentTypes,\n\t\tWithoutComponents extends keyof ComponentTypes = never,\n\t>(\n\t\tname: QueryName,\n\t\tdefinition: {\n\t\t\twith: ReadonlyArray<WithComponents>;\n\t\t\twithout?: ReadonlyArray<WithoutComponents>;\n\t\t}\n\t): SystemBuilder<\n\t\tComponentTypes,\n\t\tEventTypes,\n\t\tResourceTypes,\n\t\tQueries & Record<QueryName, QueryDefinition<ComponentTypes, WithComponents, WithoutComponents>>\n\t> {\n\t\t// Cast is needed because TypeScript can't preserve the type information\n\t\t// when modifying an object property\n\t\tconst newBuilder = this as any;\n\t\tnewBuilder.queries = {\n\t\t\t...this.queries,\n\t\t\t[name]: definition,\n\t\t};\n\t\treturn newBuilder;\n\t}\n\n\t/**\n\t * Set the system's process function that runs each update\n\t */\n\tsetProcess(\n\t\tprocess: ProcessFunction<ComponentTypes, EventTypes, ResourceTypes, Queries>\n\t): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries> {\n\t\tthis.processFunction = process;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set the onAttach lifecycle hook\n\t */\n\tsetOnAttach(\n\t\tonAttach: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>\n\t): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries> {\n\t\tthis.attachFunction = onAttach;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set the onDetach lifecycle hook\n\t */\n\tsetOnDetach(\n\t\tonDetach: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>\n\t): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries> {\n\t\tthis.detachFunction = onDetach;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set event handlers for the system\n\t */\n\tsetEventHandlers(\n\t\thandlers: {\n\t\t\t[EventName in keyof EventTypes]?: {\n\t\t\t\thandler(\n\t\t\t\t\tdata: EventTypes[EventName],\n\t\t\t\t\tentityManager: EntityManager<ComponentTypes>,\n\t\t\t\t\tresourceManager: ResourceManager<ResourceTypes>,\n\t\t\t\t\teventBus: EventBus<EventTypes>,\n\t\t\t\t): void;\n\t\t\t};\n\t\t}\n\t): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries> {\n\t\tthis.eventHandlers = handlers;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Build the final system object\n\t */\n\tbuild(): System<ComponentTypes, any, any, EventTypes, ResourceTypes> {\n\t\tconst system: System<ComponentTypes, any, any, EventTypes, ResourceTypes> = {\n\t\t\tlabel: this._label,\n\t\t\tentityQueries: this.queries as any,\n\t\t};\n\n\t\tif (this.processFunction) {\n\t\t\tsystem.process = this.processFunction as any;\n\t\t}\n\n\t\tif (this.attachFunction) {\n\t\t\tsystem.onAttach = this.attachFunction;\n\t\t}\n\n\t\tif (this.detachFunction) {\n\t\t\tsystem.onDetach = this.detachFunction;\n\t\t}\n\n\t\tif (this.eventHandlers) {\n\t\t\tsystem.eventHandlers = this.eventHandlers;\n\t\t}\n\n\t\treturn system;\n\t}\n}\n\n// Helper type definitions\ntype QueryDefinition<\n\tComponentTypes,\n\tWithComponents extends keyof ComponentTypes = any,\n\tWithoutComponents extends keyof ComponentTypes = any,\n> = {\n\twith: ReadonlyArray<WithComponents>;\n\twithout?: ReadonlyArray<WithoutComponents>;\n};\n\ntype QueryResults<\n\tComponentTypes,\n\tQueries extends Record<string, QueryDefinition<ComponentTypes>>,\n> = {\n\t[QueryName in keyof Queries]: QueryName extends string\n\t\t? FilteredEntity<\n\t\t\tComponentTypes,\n\t\t\tQueries[QueryName] extends QueryDefinition<ComponentTypes, infer W, any> ? W : never,\n\t\t\tQueries[QueryName] extends QueryDefinition<ComponentTypes, any, infer WO> ? WO : never\n\t\t>[]\n\t\t: never;\n};\n\ntype ProcessFunction<\n\tComponentTypes,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>,\n\tQueries extends Record<string, QueryDefinition<ComponentTypes>>,\n> = (\n\tqueries: QueryResults<ComponentTypes, Queries>,\n\tdeltaTime: number,\n\tentityManager: EntityManager<ComponentTypes>,\n\tresourceManager: ResourceManager<ResourceTypes>,\n\teventBus: EventBus<EventTypes>,\n) => void;\n\ntype LifecycleFunction<\n\tComponentTypes,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>,\n> = (\n\tentityManager: EntityManager<ComponentTypes>,\n\tresourceManager: ResourceManager<ResourceTypes>,\n\teventBus: EventBus<EventTypes>,\n) => void;\n\n// // Factory function for easier creation\n// function createSystem<\n// \tComponentTypes,\n// \tEventTypes = any,\n// \tResourceTypes = any\n// >(\n// \tlabel: string\n// ): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes> {\n// \treturn new SystemBuilder<ComponentTypes, EventTypes, ResourceTypes>(label);\n// }\n",
11
+ "import ECSpresso from './ecspresso';\nimport { SystemBuilder } from './system-builder';\nimport Bundle, { mergeBundles } from './bundle';\n\nexport * from './types';\nexport { default as EntityManager } from './entity-manager';\nexport { default as EventBus } from './event-bus';\nexport { default as ResourceManager } from './resource-manager';\nexport { SystemBuilder };\nexport { Bundle, mergeBundles };\nexport default ECSpresso;\n"
12
+ ],
13
+ "mappings": "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",
14
+ "debugId": "7DD37829380BFEFA64756E2164756E21",
15
+ "names": []
16
+ }
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "ecspresso",
3
+ "version": "0.0.0",
4
+ "main": "src/index.ts",
5
+ "module": "src/index.ts",
6
+ "description": "A minimal Entity-Component-System library for typescript and javascript.",
7
+ "keywords": [
8
+ "game",
9
+ "gamedev",
10
+ "game development",
11
+ "game engine",
12
+ "game development",
13
+ "entity component system",
14
+ "web games",
15
+ "ecs"
16
+ ],
17
+ "devDependencies": {
18
+ "@types/bun": "latest"
19
+ },
20
+ "peerDependencies": {
21
+ "typescript": "^5"
22
+ },
23
+ "files": [
24
+ "dist"
25
+ ],
26
+ "scripts": {
27
+ "build:clean": "rm -rf dist",
28
+ "build:ts": "bun build --target=browser --sourcemap=linked --minify --outdir=dist src/index.ts",
29
+ "build": "bun build:clean && bun build:ts",
30
+ "prepublishOnly": "bun run build"
31
+ },
32
+ "type": "module"
33
+ }