Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

colyseus-events

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

colyseus-events - npm Package Compare versions

Comparing version 2.0.0 to 2.1.0

dist/core-visitors.d.ts

36

dist/index.d.ts

@@ -1,34 +0,4 @@

import { ArraySchema, CollectionSchema, MapSchema, Schema, SetSchema } from '@colyseus/schema';
export declare type Primitive = number | string | boolean | null | undefined;
export declare type Container = Schema | ArraySchema | MapSchema | CollectionSchema | SetSchema;
export declare type Colyseus = Primitive | Container;
export interface Events<E = string> {
emit(eventName: E, value: Event): unknown;
}
export declare type Add = {
op: 'add';
path: string;
value: Colyseus;
};
export declare type Replace = {
op: 'replace';
path: string;
value: Colyseus;
};
export declare type Remove = {
op: 'remove';
path: string;
};
export declare type Event = Add | Remove | Replace;
export declare function add(path: string, value: Colyseus): Add;
export declare function replace(path: string, value: Colyseus): Replace;
export declare function remove(path: string): Remove;
/**
* make every change in Colyseus state trigger an event in the EventEmitter using the provided namespace.
* @param state Colyseus state to track
* @param events EventsEmitter of you choice. has to at least have the method `emit(eventName, value)`.
* @param namespace (optional) Prefix of json pointer
* @returns the provided events emitter (2nd argument)
*/
export declare function wireEvents<T extends Events>(state: Colyseus, events: T, namespace?: string): T;
export * from './types';
export * from './wire-events';
export * from './core-visitors';
//# sourceMappingURL=index.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.wireEvents = exports.remove = exports.replace = exports.add = void 0;
const schema_1 = require("@colyseus/schema");
const schemaKeys = Object.keys(new (class extends schema_1.Schema {
})()).concat(['onChange']); // keys that exist on any schema object - are not data fields
function isPrimitive(val) {
return typeof val !== 'object' || !val;
}
function add(path, value) {
return { op: 'add', path, value };
}
exports.add = add;
function replace(path, value) {
return { op: 'replace', path, value };
}
exports.replace = replace;
function remove(path) {
return { op: 'remove', path };
}
exports.remove = remove;
/**
* make every change in Colyseus state trigger an event in the EventEmitter using the provided namespace.
* @param state Colyseus state to track
* @param events EventsEmitter of you choice. has to at least have the method `emit(eventName, value)`.
* @param namespace (optional) Prefix of json pointer
* @returns the provided events emitter (2nd argument)
*/
function wireEvents(state, events, namespace = '') {
if (isPrimitive(state)) {
return events;
}
if (state instanceof schema_1.Schema) {
state.onChange = (changes) => {
for (const { field, value } of changes) {
const fieldNamespace = `${namespace}/${field}`;
events.emit(fieldNamespace, replace(fieldNamespace, value));
wireEvents(value, events, fieldNamespace);
}
};
for (const field in state) {
if (!schemaKeys.includes(field) && Object.prototype.hasOwnProperty.call(state, field)) {
const fieldNamespace = `${namespace}/${field}`;
const value = state[field];
wireEvents(value, events, fieldNamespace);
}
}
}
else if (state instanceof schema_1.ArraySchema) {
state.onAdd = (value, field) => {
const fieldNamespace = `${namespace}/${field}`;
events.emit(namespace, add(fieldNamespace, value));
wireEvents(value, events, fieldNamespace);
};
state.onChange = (value, field) => {
const fieldNamespace = `${namespace}/${field}`;
events.emit(fieldNamespace, replace(fieldNamespace, value));
wireEvents(value, events, fieldNamespace);
};
state.onRemove = (_, field) => {
const fieldNamespace = `${namespace}/${field}`;
events.emit(namespace, remove(fieldNamespace));
};
for (const [field, value] of state.entries()) {
const fieldNamespace = `${namespace}/${field}`;
wireEvents(value, events, fieldNamespace);
}
}
else if (state instanceof schema_1.MapSchema) {
state.onAdd = (value, field) => {
const fieldNamespace = `${namespace}/${field}`;
events.emit(namespace, add(fieldNamespace, value));
wireEvents(value, events, fieldNamespace);
};
state.onChange = (value, field) => {
const fieldNamespace = `${namespace}/${field}`;
events.emit(fieldNamespace, replace(fieldNamespace, value));
wireEvents(value, events, fieldNamespace);
};
state.onRemove = (_, field) => {
const fieldNamespace = `${namespace}/${field}`;
events.emit(namespace, remove(fieldNamespace));
};
for (const [field, value] of state.entries()) {
const fieldNamespace = `${namespace}/${field}`;
wireEvents(value, events, fieldNamespace);
}
}
// TODO handle CollectionSchema and andSetSchema
return events;
}
exports.wireEvents = wireEvents;
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./types"), exports);
tslib_1.__exportStar(require("./wire-events"), exports);
tslib_1.__exportStar(require("./core-visitors"), exports);
//# sourceMappingURL=index.js.map
{
"name": "colyseus-events",
"version": "2.0.0",
"version": "2.1.0",
"description": "generate notification events from colyseus state",

@@ -5,0 +5,0 @@ "repository": "git@github.com:starwards/colyseus-events.git",

# colyseus-events
Generate json-patch events from colyseus state.
Generate json-patch events from [colyseus](https://www.colyseus.io/) state.
```typescript

@@ -23,3 +23,4 @@ import { wireEvents } from 'colyseus-events';

## How to use
Import `wireEvents` and call it once when connecting to a room on the client side,
### wireEvents
Import `wireEvents` and call it once when connecting to a room on the client side:
```typescript

@@ -31,4 +32,54 @@ import { wireEvents } from 'colyseus-events';

```
then you can wire listeners to `events` using their [JSON-pointer](https://github.com/janl/node-jsonpointer) as event name.
then you can wire listeners to `events` using the [JSON-pointer](https://github.com/janl/node-jsonpointer) of target field as event name.
### customWireEvents
To change the behavior for parts or all of your state, use `customWireEvents` to produce your own version of `wireEvents`:
```typescript
import { customWireEvents, coreVisitors} from 'colyseus-events';
const special = {
visit: (traverse: Traverse, state: Container, events: Events, jsonPath: string): boolean => { /* see Visitor implementation below*/},
};
const wireEvents = customWireEvents([ special, ...coreVisitors]);
const room: Room<GameState> = await client.joinOrCreate("game");
const events = wireEvents(room.state, new EventEmitter());
// `events` will emit json-patch events whenever the room state changes
```
`customWireEvents` accepts a single argument, a collection of `Visitor` objects, and returns afunctyion compatible with the default `wireEvents`. In fact, the default `wireEvents` function is itself the result `customWireEvents` when using `coreVisitors` as the argument. it is defined in [wire-events.ts](src/wire-events.ts#L42) by the following line:
```typescript
export const wireEvents = customWireEvents(coreVisitors);
```
The order of the visitors is crucial: they are executed as a fallback chain: the first visitor to return `true` will stop the chain and prevent later visitors from wiring the same state. So be sure to order them by specificity: the more specific handlers should first check for their use case before the generic visitors, and `coreVisitors` should be the last visitors.
#### Visitor implementation
A visitor must implement a single method, `visit`. This method should:
1. Check if it is going to handle the state object, and return `false` if not.
2. Call the traverse function for each child member of the state.
3. Hook on the state's [`.onChange`](https://docs.colyseus.io/colyseus/state/schema/#onchange-changes-datachange) and possibly [`.onAdd`](https://docs.colyseus.io/colyseus/state/schema/#onadd-instance-key) and [`.onRemove`](https://docs.colyseus.io/colyseus/state/schema/#onremove-instance-key), or perhaspse the [`.listen`](https://docs.colyseus.io/colyseus/state/schema/#listenprop-callback) mechanism.
4. For every new value in each child member of the state, call the traverse function and emit the events using the event emitter.
Examples can be found in [core-visitors.ts](src/core-visitors.ts). Here is the visitor that handles `MapSchema`:
```typescript
{
visit: (traverse: Traverse, state: Container, events: Events, namespace: string) => {
// Check if it is going to handle the state object, and return `false` if not.
if (!(state instanceof MapSchema)) {
return false;
}
// Hook on new elements
state.onAdd = (value: Colyseus, field) => {
const fieldNamespace = `${namespace}/${field}`; // path to the new element
events.emit(namespace, Add(fieldNamespace, value)); // emit the add event
traverse(value, events, fieldNamespace); // call the traverse function on the new value
};
...
// Call the traverse function for each child member of the state.
for (const [field, value] of state.entries()) {
const fieldNamespace = `${namespace}/${field}`;
traverse(value as Colyseus, events, fieldNamespace);
}
// finally return true. this will break the visitors fallback chain and complete the wiring for this object.
return true;
}
}
```
## Examples

@@ -39,3 +90,4 @@

export class Inner extends Schema {
@type('uint8') public baz = 0;
@type('uint8') public x = 0;
@type('uint8') public y = 0;
}

@@ -55,3 +107,3 @@ export class GameState extends Schema {

- when the server executes: `room.mapNumbers.set('F00', 1)` (assuming mapNumbers had a previous value at key `F00`) an event named `'/mapNumbers/F00'` will be emitted with value `{ op: 'replace', path: '/mapNumbers/F00', value: 1 }`
- when the server executes: `room.state.bar.baz = 1` an event named `'/bar/baz'` will be emitted with value `{ op: 'replace', path: '/bar/baz', value: 1 }`
- when the server executes: `room.state.bar.x = 1` an event named `'/bar/x'` will be emitted with value `{ op: 'replace', path: '/bar/x', value: 1 }`
- when the server executes: `room.state.bar = new Inner()` an event named `'/bar'` will be emitted with value `{ op: 'replace', path: '/bar', value: {{the actual object in state.bar }} }`

@@ -58,0 +110,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc