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

@colyseus/schema

Package Overview
Dependencies
Maintainers
1
Versions
313
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@colyseus/schema - npm Package Compare versions

Comparing version 0.1.8 to 0.3.0

lib/types/ArraySchema.d.ts

42

lib/annotations.d.ts
import * as decode from "./msgpack/decode";
export declare type PrimitiveType = "string" | "number" | "int8" | "uint8" | "int16" | "uint16" | "int32" | "uint32" | "int64" | "uint64" | typeof Schema;
import { ArraySchema } from './types/ArraySchema';
/**
* Data types
*/
export declare type PrimitiveType = "string" | "number" | "boolean" | "int8" | "uint8" | "int16" | "uint16" | "int32" | "uint32" | "int64" | "uint64" | "float32" | "float64" | typeof Schema;
export declare type DefinitionType = (PrimitiveType | PrimitiveType[] | {

@@ -9,7 +13,10 @@ map: PrimitiveType;

};
export interface DataChange {
export interface DataChange<T = any> {
field: string;
value: any;
previousValue: any;
value: T;
previousValue: T;
}
/**
* Schema encoder / decoder
*/
export declare abstract class Schema {

@@ -20,2 +27,5 @@ static _schema: Definition;

};
protected $allChanges: {
[key: string]: any;
};
protected $changes: {

@@ -37,4 +47,26 @@ [key: string]: any;

decode(bytes: any, it?: decode.Iterator): this;
encode(root?: boolean, encodedBytes?: any[]): any[];
encode(root?: boolean, encodeAll?: boolean): any[];
encodeAll(): any[];
toJSON(): {};
}
/**
* Reflection
*/
export declare class ReflectionField extends Schema {
name: string;
type: PrimitiveType;
referencedType: number;
}
export declare class ReflectionType extends Schema {
id: number;
fields: ArraySchema<ReflectionField>;
}
export declare class Reflection extends Schema {
types: ArraySchema<ReflectionType>;
static encode(instance: Schema): any[];
static decode(bytes: number[]): any;
}
/**
* Decorators / Proxies
*/
export declare function type(type: DefinitionType): (target: any, field: string) => void;
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -6,2 +25,4 @@ var spec_1 = require("./spec");

var decode = require("./msgpack/decode");
var ArraySchema_1 = require("./types/ArraySchema");
var MapSchema_1 = require("./types/MapSchema");
function encodePrimitiveType(type, bytes, value) {

@@ -26,2 +47,5 @@ var encodeFunc = encode[type];

}
/**
* Schema encoder / decoder
*/
var Schema = /** @class */ (function () {

@@ -34,2 +58,3 @@ // allow inherited classes to have a constructor

}
this.$allChanges = {};
this.$changes = {};

@@ -41,3 +66,3 @@ this.$changed = false;

this.$changed = true;
if (value) {
if (value !== undefined) {
if (Array.isArray(value.$parentField) ||

@@ -56,7 +81,14 @@ fieldSchema && (Array.isArray(fieldSchema) || fieldSchema.map)) {

}
if (fieldKey !== undefined &&
this.$changes[fieldName].indexOf(fieldKey) === -1 // do not store duplicates of changed fields
) {
this.$changes[fieldName].push(fieldKey);
if (!this.$allChanges[fieldName]) {
this.$allChanges[fieldName] = [];
}
if (fieldKey !== undefined) {
// do not store duplicates of changed fields
if (this.$changes[fieldName].indexOf(fieldKey) === -1) {
this.$changes[fieldName].push(fieldKey);
}
if (this.$allChanges[fieldName].indexOf(fieldKey) === -1) {
this.$allChanges[fieldName].push(fieldKey);
}
}
}

@@ -66,2 +98,3 @@ else if (value.$parentField) {

this.$changes[value.$parentField] = value;
this.$allChanges[value.$parentField] = value;
}

@@ -71,2 +104,3 @@ else {

this.$changes[field] = this["_" + field];
this.$allChanges[field] = this["_" + field];
}

@@ -103,8 +137,7 @@ }

var totalBytes = bytes.length;
while (it.offset < totalBytes) {
var _loop_1 = function () {
var index = bytes[it.offset++];
var field = fieldsByIndex[index];
if (index === spec_1.END_OF_STRUCTURE) {
// reached end of strucutre. skip.
break;
return "break";
}

@@ -116,4 +149,4 @@ var type_1 = schema[field];

if (type_1._schema) {
value = this["_" + field] || new type_1();
value.$parent = this;
value = this_1["_" + field] || new type_1();
value.$parent = this_1;
value.decode(bytes, it);

@@ -125,5 +158,5 @@ hasChange = true;

change = [];
var valueRef = this["_" + field] || [];
value = valueRef.slice(0);
var newLength = decode.number(bytes, it);
var valueRef_1 = this_1["_" + field] || new ArraySchema_1.ArraySchema();
value = valueRef_1.clone();
var newLength_1 = decode.number(bytes, it);
var numChanges = decode.number(bytes, it);

@@ -135,7 +168,10 @@ hasChange = (numChanges > 0);

// ensure current array has the same length as encoded one
if (value.length > newLength) {
value.splice(newLength).forEach(function (itemRemoved) {
if (value.length > newLength_1) {
value.splice(newLength_1).forEach(function (itemRemoved, i) {
if (itemRemoved.onRemove) {
itemRemoved.onRemove();
}
if (valueRef_1.onRemove) {
valueRef_1.onRemove(itemRemoved, newLength_1 + i);
}
});

@@ -145,8 +181,2 @@ }

var newIndex = decode.number(bytes, it);
if (decode.nilCheck(bytes, it)) {
// const item = this[`_${field}`][newIndex];
// TODO: trigger `onRemove` on Schema object being removed.
it.offset++;
continue;
}
// index change check

@@ -161,16 +191,28 @@ var indexChangedFrom = void 0;

var item = void 0;
if (hasIndexChange && indexChangedFrom === undefined && newIndex !== undefined) {
var isNew = (hasIndexChange && indexChangedFrom === undefined && newIndex !== undefined);
if (isNew) {
item = new type_1();
}
else if (indexChangedFrom !== undefined) {
item = valueRef[indexChangedFrom];
item = valueRef_1[indexChangedFrom];
}
else if (newIndex !== undefined) {
item = valueRef[newIndex];
item = valueRef_1[newIndex];
}
if (!item) {
item = new type_1();
isNew = true;
}
item.$parent = this;
if (decode.nilCheck(bytes, it)) {
it.offset++;
if (valueRef_1.onRemove) {
valueRef_1.onRemove(item, newIndex);
}
continue;
}
item.$parent = this_1;
item.decode(bytes, it);
if (isNew && valueRef_1.onAdd) {
valueRef_1.onAdd(item, newIndex);
}
value[newIndex] = item;

@@ -186,4 +228,4 @@ }

type_1 = type_1.map;
var valueRef = this["_" + field] || {};
value = Object.assign({}, valueRef);
var valueRef = this_1["_" + field] || new MapSchema_1.MapSchema();
value = valueRef.clone();
var length = decode.number(bytes, it);

@@ -194,3 +236,10 @@ hasChange = (length > 0);

var hasIndexChange = false;
var mapKeys = Object.keys(valueRef);
for (var i = 0; i < length; i++) {
// `encodeAll` may indicate a higher number of indexes it actually encodes
// TODO: do not encode a higher number than actual encoded entries
if (bytes[it.offset] === undefined ||
bytes[it.offset] === spec_1.END_OF_STRUCTURE) {
break;
}
// index change check

@@ -200,3 +249,3 @@ var previousKey = void 0;

decode.uint8(bytes, it);
previousKey = Object.keys(valueRef)[decode.number(bytes, it)];
previousKey = mapKeys[decode.number(bytes, it)];
hasIndexChange = true;

@@ -206,5 +255,6 @@ }

var newKey = (hasMapIndex)
? Object.keys(valueRef)[decode.number(bytes, it)]
? mapKeys[decode.number(bytes, it)]
: decode.string(bytes, it);
var item = void 0;
var isNew = (hasIndexChange && previousKey === undefined && hasMapIndex);
if (hasIndexChange && previousKey === undefined && hasMapIndex) {

@@ -221,2 +271,3 @@ item = new type_1();

item = new type_1();
isNew = true;
}

@@ -228,2 +279,5 @@ if (decode.nilCheck(bytes, it)) {

}
if (valueRef.onRemove) {
valueRef.onRemove(item, newKey);
}
delete value[newKey];

@@ -236,5 +290,11 @@ continue;

else {
item.$parent = this;
item.$parent = this_1;
item.decode(bytes, it);
value[newKey] = item;
if (isNew && valueRef.onAdd) {
valueRef.onAdd(item, newKey);
}
else if (valueRef.onChange) {
valueRef.onChange(item, newKey);
}
}

@@ -247,11 +307,16 @@ }

}
if (this.onChange && hasChange) {
if (hasChange && this_1.onChange) {
changes.push({
field: field,
value: change || value,
// value: value,
previousValue: this["_" + field]
previousValue: this_1["_" + field]
});
}
this["_" + field] = value;
this_1["_" + field] = value;
};
var this_1 = this;
while (it.offset < totalBytes) {
var state_1 = _loop_1();
if (state_1 === "break")
break;
}

@@ -263,5 +328,6 @@ if (this.onChange && changes.length > 0) {

};
Schema.prototype.encode = function (root, encodedBytes) {
Schema.prototype.encode = function (root, encodeAll) {
if (root === void 0) { root = true; }
if (encodedBytes === void 0) { encodedBytes = []; }
if (encodeAll === void 0) { encodeAll = false; }
var encodedBytes = [];
var endStructure = function () {

@@ -273,3 +339,3 @@ if (!root) {

// skip if nothing has changed
if (!this.$changed) {
if (!this.$changed && !encodeAll) {
endStructure();

@@ -280,6 +346,9 @@ return encodedBytes;

var indexes = this._indexes;
for (var field in this.$changes) {
var changes = (encodeAll)
? this.$allChanges
: this.$changes;
for (var field in changes) {
var bytes = [];
var type_2 = schema[field];
var value = this.$changes[field];
var value = changes[field];
var fieldIndex = indexes[field];

@@ -293,3 +362,3 @@ // skip unchagned fields

// encode child object
bytes = bytes.concat(value.encode(false));
bytes = bytes.concat(value.encode(false, encodeAll));
// ensure parent is set

@@ -327,3 +396,3 @@ // in case it was manually instantiated

}
bytes = bytes.concat(item.encode(false));
bytes = bytes.concat(item.encode(false, encodeAll));
}

@@ -340,10 +409,20 @@ else {

else if (type_2.map) {
// encode Map of type
encode.number(bytes, fieldIndex);
// encode Map of type
var keys = value;
var keys = value; // TODO: during `encodeAll`, removed entries are not going to be encoded
encode.number(bytes, keys.length);
var mapKeys = Object.keys(this["_" + field]);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var key = mapKeys[keys[i]] || keys[i];
var item = this["_" + field][key];
var mapItemIndex = this["_" + field + "MapIndex"][key];
var mapItemIndex = this["_" + field]._indexes[key];
if (encodeAll) {
if (item) {
mapItemIndex = undefined;
}
else {
// previously deleted items are skipped during `encodeAll`
continue;
}
}
// encode index change

@@ -356,13 +435,16 @@ if (item && item.$parentIndexChange >= 0) {

if (mapItemIndex !== undefined) {
key = mapItemIndex;
encode.number(bytes, key);
encode.number(bytes, mapItemIndex);
}
else {
// TODO: remove item
encode.string(bytes, key);
this["_" + field + "MapIndex"][key] = Object.keys(this["_" + field]).indexOf(key);
var mapKey = mapKeys.indexOf(key);
if (mapKey >= 0) {
this["_" + field]._indexes[key] = mapKey;
}
}
if (item instanceof Schema) {
item.$parent = this;
item.$parentField = [field, key];
bytes = bytes.concat(item.encode(false));
item.$parentField = [field, keys[i]];
bytes = bytes.concat(item.encode(false, encodeAll));
}

@@ -376,2 +458,3 @@ else if (item !== undefined) {

}
this["_" + field]._updateIndexes();
}

@@ -393,5 +476,168 @@ else {

};
Schema.prototype.encodeAll = function () {
return this.encode(true, true);
};
Schema.prototype.toJSON = function () {
var schema = this._schema;
var obj = {};
for (var field in schema) {
obj[field] = this["_" + field];
}
return obj;
};
return Schema;
}());
exports.Schema = Schema;
/**
* Reflection
*/
var ReflectionField = /** @class */ (function (_super) {
__extends(ReflectionField, _super);
function ReflectionField() {
return _super !== null && _super.apply(this, arguments) || this;
}
__decorate([
type("string")
], ReflectionField.prototype, "name", void 0);
__decorate([
type("string")
], ReflectionField.prototype, "type", void 0);
__decorate([
type("number")
], ReflectionField.prototype, "referencedType", void 0);
return ReflectionField;
}(Schema));
exports.ReflectionField = ReflectionField;
var ReflectionType = /** @class */ (function (_super) {
__extends(ReflectionType, _super);
function ReflectionType() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.fields = new ArraySchema_1.ArraySchema();
return _this;
}
__decorate([
type("uint8")
], ReflectionType.prototype, "id", void 0);
__decorate([
type([ReflectionField])
], ReflectionType.prototype, "fields", void 0);
return ReflectionType;
}(Schema));
exports.ReflectionType = ReflectionType;
var Reflection = /** @class */ (function (_super) {
__extends(Reflection, _super);
function Reflection() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.types = new ArraySchema_1.ArraySchema();
return _this;
}
Reflection.encode = function (instance) {
var reflection = new Reflection();
var schema = instance._schema;
var lastTypeId = 0;
var rootType = new ReflectionType();
rootType.id = lastTypeId++;
var typeIds = {};
var buildType = function (currentType, schema) {
for (var fieldName in schema) {
var field = new ReflectionField();
field.name = fieldName;
var fieldType = void 0;
if (typeof (schema[fieldName]) === "string") {
fieldType = schema[fieldName];
}
else {
var isSchema = typeof (schema[fieldName]) === "function";
var isArray = Array.isArray(schema[fieldName]);
// const isMap = !isArray && (schema[fieldName] as any).map;
fieldType = (isArray)
? "array"
: (isSchema)
? "ref"
: "map";
var childSchema = (isArray)
? schema[fieldName][0]
: (isSchema)
? schema[fieldName]
: schema[fieldName].map;
var childSchemaName = childSchema.name;
if (typeIds[childSchemaName] === undefined) {
var childType = new ReflectionType();
childType.id = lastTypeId++;
typeIds[childSchemaName] = childType.id;
buildType(childType, (new childSchema())._schema);
}
field.referencedType = typeIds[childSchemaName];
}
field.type = fieldType;
currentType.fields.push(field);
}
reflection.types.push(currentType);
};
buildType(rootType, schema);
return reflection.encodeAll();
};
Reflection.decode = function (bytes) {
var reflection = new Reflection();
reflection.decode(bytes);
var schemaTypes = reflection.types.reverse().map(function (_) {
return /** @class */ (function (_super) {
__extends(_, _super);
function _() {
return _super !== null && _super.apply(this, arguments) || this;
}
return _;
}(Schema));
});
reflection.types.forEach(function (reflectionType, i) {
reflectionType.fields.forEach(function (field) {
var schemaType = schemaTypes[i];
if (field.referencedType !== undefined) {
var refType = schemaTypes[field.referencedType];
if (field.type === "array") {
type([refType])(schemaType.prototype, field.name);
}
else if (field.type === "map") {
type({ map: refType })(schemaType.prototype, field.name);
}
else if (field.type === "ref") {
type(refType)(schemaType.prototype, field.name);
}
}
else {
type(field.type)(schemaType.prototype, field.name);
}
});
});
var rootType = new schemaTypes[0];
/**
* auto-initialize referenced types on root type
* to allow registering listeners immediatelly on client-side
*/
for (var fieldName in rootType._schema) {
var fieldType = rootType._schema[fieldName];
if (typeof (fieldType) !== "string") {
var isSchema = typeof (fieldType) === "function";
var isArray = Array.isArray(fieldType);
var isMap = !isArray && fieldType.map;
rootType[fieldName] = (isArray)
? new ArraySchema_1.ArraySchema()
: (isMap)
? new MapSchema_1.MapSchema()
: (isSchema)
? new fieldType()
: undefined;
}
}
return rootType;
};
__decorate([
type([ReflectionType])
], Reflection.prototype, "types", void 0);
return Reflection;
}(Schema));
exports.Reflection = Reflection;
/**
* Decorators / Proxies
*/
function type(type) {

@@ -409,2 +655,6 @@ return function (target, field) {

constructor._schema[field] = type;
/**
* TODO: `isSchema` / `isArray` / `isMap` is repeated on many places!
* need to refactor all of them.
*/
var isArray = Array.isArray(type);

@@ -428,5 +678,2 @@ var isMap = !isArray && type.map;

if (isArray || isMap) {
if (isMap) {
this[fieldCached + "MapIndex"] = {};
}
value = new Proxy(value, {

@@ -437,6 +684,6 @@ get: function (obj, prop) { return obj[prop]; },

// ensure new value has a parent
var key = (isArray) ? Number(prop) : prop;
var key = (isArray) ? Number(prop) : String(prop);
if (setValue.$parentField && setValue.$parentField[1] !== key) {
if (isMap) {
var indexChange = _this[fieldCached + "MapIndex"][setValue.$parentField[1]];
var indexChange = _this["" + fieldCached]._indexes[setValue.$parentField[1]];
setValue.$parentIndexChange = indexChange;

@@ -455,3 +702,2 @@ }

obj[prop] = setValue;
// console.log("setValue:", obj, setValue)
_this.markAsChanged(field, obj);

@@ -471,3 +717,3 @@ }

// ensure new value has a parent
if (previousValue.$parent) {
if (previousValue && previousValue.$parent) {
previousValue.$parent.markAsChanged(field, previousValue);

@@ -474,0 +720,0 @@ }

4

lib/index.d.ts

@@ -1,1 +0,3 @@

export { Schema, type, DataChange, PrimitiveType, Definition, DefinitionType, } from "./annotations";
export { MapSchema } from "./types/MapSchema";
export { ArraySchema } from "./types/ArraySchema";
export { Schema, type, DataChange, PrimitiveType, Definition, DefinitionType, Reflection, ReflectionType, ReflectionField, } from "./annotations";
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var MapSchema_1 = require("./types/MapSchema");
exports.MapSchema = MapSchema_1.MapSchema;
var ArraySchema_1 = require("./types/ArraySchema");
exports.ArraySchema = ArraySchema_1.ArraySchema;
var annotations_1 = require("./annotations");
// Public API
exports.Schema = annotations_1.Schema;
exports.type = annotations_1.type;
// Reflection
exports.Reflection = annotations_1.Reflection;
exports.ReflectionType = annotations_1.ReflectionType;
exports.ReflectionField = annotations_1.ReflectionField;

@@ -36,5 +36,7 @@ /**

export declare function uint32(bytes: number[], it: Iterator): number;
export declare function float32(bytes: number[], it: Iterator): number;
export declare function float64(bytes: number[], it: Iterator): number;
export declare function readFloat32(bytes: number[], it: Iterator): number;
export declare function readFloat64(bytes: number[], it: Iterator): number;
/****/
export declare function boolean(bytes: number[], it: Iterator): boolean;
export declare function string(bytes: any, it: Iterator): string;

@@ -47,5 +49,1 @@ export declare function stringCheck(bytes: any, it: Iterator): boolean;

export declare function indexChangeCheck(bytes: any, it: Iterator): boolean;
/**
* UNUSED. LEFT HERE JUST FOR REFERENCE.
*/
export declare function decode(bytes: any, it: Iterator): any;

@@ -77,2 +77,10 @@ "use strict";

;
function float32(bytes, it) {
return readFloat32(bytes, it);
}
exports.float32 = float32;
function float64(bytes, it) {
return readFloat64(bytes, it);
}
exports.float64 = float64;
// export function int64 (bytes: number[], it: Iterator) {

@@ -101,3 +109,7 @@ // return new flatbuffers.Long(int32(bytes, it), int32(bytes, it));

;
/****/
function boolean(bytes, it) {
return uint8(bytes, it) > 0;
}
exports.boolean = boolean;
;
function string(bytes, it) {

@@ -225,177 +237,1 @@ var prefix = bytes[it.offset++];

exports.indexChangeCheck = indexChangeCheck;
/**
* UNUSED. LEFT HERE JUST FOR REFERENCE.
*/
function decode(bytes, it) {
var prefix = bytes[it.offset++];
var value, length = 0, type = 0, hi = 0, lo = 0;
if (prefix < 0xc0) {
// positive fixint
if (prefix < 0x80) {
return prefix;
}
// fixmap
if (prefix < 0x90) {
return this._map(prefix & 0x0f);
}
// fixarray
if (prefix < 0xa0) {
return this._array(prefix & 0x0f);
}
// fixstr
return _str(bytes, it, prefix & 0x1f);
}
// negative fixint
if (prefix > 0xdf) {
return (0xff - prefix + 1) * -1;
}
switch (prefix) {
// nil
case 0xc0:
return null;
// false
case 0xc2:
return false;
// true
case 0xc3:
return true;
// bin
case 0xc4:
length = bytes[it.offset];
it.offset += 1;
return this._bin(length);
case 0xc5:
length = bytes[it.offset];
it.offset += 2;
return this._bin(length);
case 0xc6:
length = bytes[it.offset];
it.offset += 4;
return this._bin(length);
// ext
case 0xc7:
length = bytes[it.offset];
type = bytes[it.offset + 1];
it.offset += 2;
return [type, this._bin(length)];
case 0xc8:
length = bytes[it.offset];
type = bytes[it.offset + 2];
it.offset += 3;
return [type, this._bin(length)];
case 0xc9:
length = bytes[it.offset];
type = bytes[it.offset + 4];
it.offset += 5;
return [type, this._bin(length)];
// float
case 0xca:
value = bytes[it.offset];
it.offset += 4;
return value;
case 0xcb:
value = bytes[it.offset];
it.offset += 8;
return value;
// uint
case 0xcc:
value = bytes[it.offset];
it.offset += 1;
return value;
case 0xcd:
value = bytes[it.offset];
it.offset += 2;
return value;
case 0xce:
value = bytes[it.offset];
it.offset += 4;
return value;
case 0xcf:
hi = bytes[it.offset] * Math.pow(2, 32);
lo = bytes[it.offset + 4];
it.offset += 8;
return hi + lo;
// int
case 0xd0:
value = bytes[it.offset];
it.offset += 1;
return value;
case 0xd1:
value = bytes[it.offset];
it.offset += 2;
return value;
case 0xd2:
value = bytes[it.offset];
it.offset += 4;
return value;
case 0xd3:
hi = bytes[it.offset] * Math.pow(2, 32);
lo = bytes[it.offset + 4];
it.offset += 8;
return hi + lo;
// fixext
case 0xd4:
type = bytes[it.offset];
it.offset += 1;
if (type === 0x00) {
it.offset += 1;
return void 0;
}
return [type, this._bin(1)];
case 0xd5:
type = bytes[it.offset];
it.offset += 1;
return [type, this._bin(2)];
case 0xd6:
type = bytes[it.offset];
it.offset += 1;
return [type, this._bin(4)];
case 0xd7:
type = bytes[it.offset];
it.offset += 1;
if (type === 0x00) {
hi = bytes[it.offset] * Math.pow(2, 32);
lo = bytes[it.offset + 4];
it.offset += 8;
return new Date(hi + lo);
}
return [type, this._bin(8)];
case 0xd8:
type = bytes[it.offset];
it.offset += 1;
return [type, this._bin(16)];
// str
case 0xd9:
length = bytes[it.offset];
it.offset += 1;
return this._str(length);
case 0xda:
length = bytes[it.offset];
it.offset += 2;
return this._str(length);
case 0xdb:
length = bytes[it.offset];
it.offset += 4;
return this._str(length);
// array
case 0xdc:
length = bytes[it.offset];
it.offset += 2;
return this._array(length);
case 0xdd:
length = bytes[it.offset];
it.offset += 4;
return this._array(length);
// map
case 0xde:
length = bytes[it.offset];
it.offset += 2;
return this._map(length);
case 0xdf:
length = bytes[it.offset];
it.offset += 4;
return this._map(length);
}
throw new Error('Could not parse');
}
exports.decode = decode;

@@ -32,9 +32,8 @@ /**

export declare function uint64(bytes: any, value: any): void;
export declare function float32(bytes: any, value: any): void;
export declare function float64(bytes: any, value: any): void;
export declare function writeFloat32(bytes: any, value: any): void;
export declare function writeFloat64(bytes: any, value: any): void;
export declare function boolean(bytes: any, value: any): void;
export declare function string(bytes: any, value: any): number;
export declare function number(bytes: any, value: any): 1 | 2 | 3 | 5 | 9;
/**
* UNUSED. LEFT HERE JUST FOR REFERENCE.
*/
export declare function encode(bytes: any, defers: any, value: any): any;

@@ -126,2 +126,10 @@ "use strict";

;
function float32(bytes, value) {
writeFloat32(bytes, value);
}
exports.float32 = float32;
function float64(bytes, value) {
writeFloat64(bytes, value);
}
exports.float64 = float64;
var _isLittleEndian = new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1;

@@ -133,3 +141,3 @@ var _int32 = new Int32Array(2);

_float32[0] = value;
int32(bytes, int32[0]);
int32(bytes, _int32[0]);
}

@@ -145,2 +153,7 @@ exports.writeFloat32 = writeFloat32;

;
function boolean(bytes, value) {
return uint8(bytes, value ? 1 : 0);
}
exports.boolean = boolean;
;
function string(bytes, value) {

@@ -180,4 +193,8 @@ var length = utf8Length(value);

if (Math.floor(value) !== value || !isFinite(value)) {
/**
* TODO:
* is it possible to differentiate between float32 / float64 here?
*/
bytes.push(0xcb);
// defers.push({ _float: value, _length: 8, _offset: bytes.length });
writeFloat64(bytes, value);
return 9;

@@ -245,211 +262,1 @@ }

exports.number = number;
/**
* UNUSED. LEFT HERE JUST FOR REFERENCE.
*/
function encode(bytes, defers, value) {
var type = typeof value, i = 0, l = 0, hi = 0, lo = 0, length = 0, size = 0;
if (type === 'string') {
length = utf8Length(value);
// fixstr
if (length < 0x20) {
bytes.push(length | 0xa0);
size = 1;
}
// str 8
else if (length < 0x100) {
bytes.push(0xd9, length);
size = 2;
}
// str 16
else if (length < 0x10000) {
bytes.push(0xda, length >> 8, length);
size = 3;
}
// str 32
else if (length < 0x100000000) {
bytes.push(0xdb, length >> 24, length >> 16, length >> 8, length);
size = 5;
}
else {
throw new Error('String too long');
}
defers.push({ _str: value, _length: length, _offset: bytes.length });
return size + length;
}
if (type === 'number') {
// TODO: encode to float 32?
// float 64
if (Math.floor(value) !== value || !isFinite(value)) {
bytes.push(0xcb);
defers.push({ _float: value, _length: 8, _offset: bytes.length });
return 9;
}
if (value >= 0) {
// positive fixnum
if (value < 0x80) {
bytes.push(value);
return 1;
}
// uint 8
if (value < 0x100) {
bytes.push(0xcc, value);
return 2;
}
// uint 16
if (value < 0x10000) {
bytes.push(0xcd, value >> 8, value);
return 3;
}
// uint 32
if (value < 0x100000000) {
bytes.push(0xce, value >> 24, value >> 16, value >> 8, value);
return 5;
}
// uint 64
hi = (value / Math.pow(2, 32)) >> 0;
lo = value >>> 0;
bytes.push(0xcf, hi >> 24, hi >> 16, hi >> 8, hi, lo >> 24, lo >> 16, lo >> 8, lo);
return 9;
}
else {
// negative fixnum
if (value >= -0x20) {
bytes.push(value);
return 1;
}
// int 8
if (value >= -0x80) {
bytes.push(0xd0, value);
return 2;
}
// int 16
if (value >= -0x8000) {
bytes.push(0xd1, value >> 8, value);
return 3;
}
// int 32
if (value >= -0x80000000) {
bytes.push(0xd2, value >> 24, value >> 16, value >> 8, value);
return 5;
}
// int 64
hi = Math.floor(value / Math.pow(2, 32));
lo = value >>> 0;
bytes.push(0xd3, hi >> 24, hi >> 16, hi >> 8, hi, lo >> 24, lo >> 16, lo >> 8, lo);
return 9;
}
}
if (type === 'object') {
// nil
if (value === null) {
bytes.push(0xc0);
return 1;
}
if (Array.isArray(value)) {
length = value.length;
// fixarray
if (length < 0x10) {
bytes.push(length | 0x90);
size = 1;
}
// array 16
else if (length < 0x10000) {
bytes.push(0xdc, length >> 8, length);
size = 3;
}
// array 32
else if (length < 0x100000000) {
bytes.push(0xdd, length >> 24, length >> 16, length >> 8, length);
size = 5;
}
else {
throw new Error('Array too large');
}
for (i = 0; i < length; i++) {
size += encode(bytes, defers, value[i]);
}
return size;
}
// fixext 8 / Date
if (value instanceof Date) {
var time = value.getTime();
hi = Math.floor(time / Math.pow(2, 32));
lo = time >>> 0;
bytes.push(0xd7, 0, hi >> 24, hi >> 16, hi >> 8, hi, lo >> 24, lo >> 16, lo >> 8, lo);
return 10;
}
if (value instanceof ArrayBuffer) {
length = value.byteLength;
// bin 8
if (length < 0x100) {
bytes.push(0xc4, length);
size = 2;
}
else
// bin 16
if (length < 0x10000) {
bytes.push(0xc5, length >> 8, length);
size = 3;
}
else
// bin 32
if (length < 0x100000000) {
bytes.push(0xc6, length >> 24, length >> 16, length >> 8, length);
size = 5;
}
else {
throw new Error('Buffer too large');
}
defers.push({ _bin: value, _length: length, _offset: bytes.length });
return size + length;
}
if (typeof value.toJSON === 'function') {
return encode(bytes, defers, value.toJSON());
}
var keys = [], key = '';
var allKeys = Object.keys(value);
for (i = 0, l = allKeys.length; i < l; i++) {
key = allKeys[i];
if (typeof value[key] !== 'function') {
keys.push(key);
}
}
length = keys.length;
// fixmap
if (length < 0x10) {
bytes.push(length | 0x80);
size = 1;
}
// map 16
else if (length < 0x10000) {
bytes.push(0xde, length >> 8, length);
size = 3;
}
// map 32
else if (length < 0x100000000) {
bytes.push(0xdf, length >> 24, length >> 16, length >> 8, length);
size = 5;
}
else {
throw new Error('Object too large');
}
for (i = 0; i < length; i++) {
key = keys[i];
size += encode(bytes, defers, key);
size += encode(bytes, defers, value[key]);
}
return size;
}
// false/true
if (type === 'boolean') {
bytes.push(value ? 0xc3 : 0xc2);
return 1;
}
// fixext 1 / undefined
if (type === 'undefined') {
bytes.push(0xd4, 0, 0);
return 3;
}
throw new Error('Could not encode');
}
exports.encode = encode;
{
"name": "@colyseus/schema",
"version": "0.1.8",
"version": "0.3.0",
"description": "",

@@ -35,3 +35,3 @@ "main": "lib/index.js",

"mocha": "^5.2.0",
"nanoid": "^2.0.0",
"nanoid": "^2.0.1",
"notepack.io": "^2.2.0",

@@ -38,0 +38,0 @@ "sinon": "^7.2.2",

@@ -8,3 +8,3 @@ <div align="center">

A binary schema-based serialization algorithm. <br>
Although it was born to solve a <a href="https://github.com/colyseus/colyseus">Colyseus</a> issue, this library can be used standalone.
Although it was born to be used on <a href="https://github.com/colyseus/colyseus">Colyseus</a>, this library can be used as standalone.
</p>

@@ -38,3 +38,3 @@

```typescript
import { DataChange, Schema, type } from '@colyseus/schema';
import { Schema, type, ArraySchema, MapSchema } from '@colyseus/schema';

@@ -63,10 +63,10 @@ export class Player extends Schema {

@type([ Player ])
arrayOfPlayers: Player[];
arrayOfPlayers: ArraySchema<Player>;
@type({ map: Player })
mapOfPlayers: { [id: string]: Player };
mapOfPlayers: MapSchema<Player>;
}
```
See [example/State.ts](example/State.ts).
See [example](test/Schema.ts).

@@ -81,2 +81,3 @@ ## Supported types

| number | auto-detects `int` or `float` type. (extra byte on output) | `0` to `18446744073709551615` |
| boolean | `true` or `false` | `0` or `1` |
| int8 | signed 8-bit integer | `-128` to `127` |

@@ -90,13 +91,62 @@ | uint8 | unsigned 8-bit integer | `0` to `255` |

| uint64 | unsigned 64-bit integer | `0` to `18446744073709551615` |
| float32 | single-precision floating-point number | `-3.40282347e+38` to `3.40282347e+38`|
| float64 | double-precision floating-point number | `-1.7976931348623157e+308` to `1.7976931348623157e+308` |
**Declaration:**
### Declaration:
- `@type("string") name: string;`
- `@type("number") level: number;`
- `@type(Player) player: Player;`
- `@type([ Player ]) arrayOfPlayers: Player[];`
- `@type([ "number" ]) arrayOfNumbers: number[];`
- `@type([ "string" ]) arrayOfStrings: string[];`
- `@type({ map: Player }) mapOfPlayers: {[id: string]: Player};`
#### Primitive types (`string`, `number`, `boolean`, etc)
```typescript
@type("string")
name: string;
@type("int32")
name: number;
```
#### Custom `Schema` type
```typescript
@type(Player)
player: Player;
```
#### Array of a primitive type
You can't mix types inside arrays.
```typescript
@type([ "number" ])
arrayOfNumbers: ArraySchema<number>;
@type([ "string" ])
arrayOfStrings: ArraySchema<string>;
```
#### Array of custom `Schema` type
```typescript
@type([ Player ])
arrayOfPlayers: ArraySchema<Player>;
```
#### Map of a primitive type
You can't mix types inside maps.
```typescript
@type({ map: "number" })
mapOfNumbers: MapSchema<number>;
@type({ map: "string" })
mapOfStrings: MapSchema<string>;
```
#### Map of custom `Schema` type
```typescript
@type({ map: Player })
mapOfPlayers: MapSchema<Player>;
```
## Limitations and best practices

@@ -103,0 +153,0 @@

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