From b3da27e73b53f61c21638c8b6e1cf190d9979596 Mon Sep 17 00:00:00 2001 From: schmelczerandras Date: Wed, 7 Oct 2020 10:04:05 +0200 Subject: [PATCH] Refactor serialization --- backend/src/objects/character-physical.ts | 4 +- backend/src/objects/circle-physical.ts | 4 +- backend/src/objects/lamp-physical.ts | 4 +- backend/src/objects/tunnel-physical.ts | 4 +- frontend/src/index.ts | 8 +++ frontend/src/scripts/game.ts | 6 +- .../src/scripts/objects/character-view.ts | 3 +- frontend/src/scripts/objects/lamp-view.ts | 3 +- frontend/src/scripts/objects/tunnel-view.ts | 3 +- shared/src/commands/types/create-objects.ts | 4 +- shared/src/commands/types/create-player.ts | 4 +- shared/src/commands/types/delete-objects.ts | 4 +- shared/src/commands/types/move-action.ts | 4 +- shared/src/commands/types/primary-action.ts | 4 +- shared/src/commands/types/secondary-action.ts | 4 +- .../commands/types/set-view-area-action.ts | 4 +- shared/src/commands/types/ternary-action.ts | 4 +- shared/src/commands/types/update-objects.ts | 4 +- shared/src/helper/circle.ts | 4 +- shared/src/helper/rectangle.ts | 4 +- shared/src/main.ts | 8 ++- shared/src/objects/types/character-base.ts | 6 +- shared/src/objects/types/lamp-base.ts | 4 +- shared/src/objects/types/tunnel-base.ts | 6 +- .../src/transport/serializable/deserialize.ts | 13 ----- .../transport/serializable/serializable.ts | 58 ------------------- .../src/transport/serializable/serialize.ts | 10 ---- .../serialization/deserializable-class.ts | 1 + .../transport/serialization/deserialize.ts | 13 +++++ .../serialization/override-deserialization.ts | 13 +++++ .../serialization/serializable-class.ts | 4 ++ .../serialization/serializable-mapping.ts | 12 ++++ .../transport/serialization/serializable.ts | 16 +++++ .../src/transport/serialization/serialize.ts | 8 +++ .../transport/serialization/serializes-to.ts | 20 +++++++ 35 files changed, 142 insertions(+), 133 deletions(-) delete mode 100644 shared/src/transport/serializable/deserialize.ts delete mode 100644 shared/src/transport/serializable/serializable.ts delete mode 100644 shared/src/transport/serializable/serialize.ts create mode 100644 shared/src/transport/serialization/deserializable-class.ts create mode 100644 shared/src/transport/serialization/deserialize.ts create mode 100644 shared/src/transport/serialization/override-deserialization.ts create mode 100644 shared/src/transport/serialization/serializable-class.ts create mode 100644 shared/src/transport/serialization/serializable-mapping.ts create mode 100644 shared/src/transport/serialization/serializable.ts create mode 100644 shared/src/transport/serialization/serialize.ts create mode 100644 shared/src/transport/serialization/serializes-to.ts diff --git a/backend/src/objects/character-physical.ts b/backend/src/objects/character-physical.ts index 5d093e2..66e4274 100644 --- a/backend/src/objects/character-physical.ts +++ b/backend/src/objects/character-physical.ts @@ -6,7 +6,7 @@ import { settings, CommandExecutors, MoveActionCommand, - serializable, + serializesTo, } from 'shared'; import { ImmutableBoundingBox } from '../physics/bounding-boxes/immutable-bounding-box'; @@ -15,7 +15,7 @@ import { CirclePhysical } from './circle-physical'; import { Physical } from '../physics/physical'; import { PhysicalContainer } from '../physics/containers/physical-container'; -@serializable(CharacterBase) +@serializesTo(CharacterBase) export class CharacterPhysical extends CharacterBase implements Physical { public readonly canCollide = true; public readonly isInverted = false; diff --git a/backend/src/objects/circle-physical.ts b/backend/src/objects/circle-physical.ts index b14ac85..492e248 100644 --- a/backend/src/objects/circle-physical.ts +++ b/backend/src/objects/circle-physical.ts @@ -4,7 +4,7 @@ import { clamp, CommandExecutors, GameObject, - serializable, + serializesTo, settings, StepCommand, } from 'shared'; @@ -15,7 +15,7 @@ import { BoundingBoxBase } from '../physics/bounding-boxes/bounding-box-base'; import { moveCircle } from '../physics/move-circle'; import { PhysicalContainer } from '../physics/containers/physical-container'; -@serializable(Circle) +@serializesTo(Circle) export class CirclePhysical implements Circle, Physical { readonly isInverted = false; readonly canCollide = true; diff --git a/backend/src/objects/lamp-physical.ts b/backend/src/objects/lamp-physical.ts index b397347..6b71cab 100644 --- a/backend/src/objects/lamp-physical.ts +++ b/backend/src/objects/lamp-physical.ts @@ -1,11 +1,11 @@ import { vec2, vec3 } from 'gl-matrix'; -import { LampBase, settings, id, serializable } from 'shared'; +import { LampBase, settings, id, serializesTo } from 'shared'; import { ImmutableBoundingBox } from '../physics/bounding-boxes/immutable-bounding-box'; import { Physical } from '../physics/physical'; -@serializable(LampBase) +@serializesTo(LampBase) export class LampPhysical extends LampBase implements Physical { public readonly canCollide = false; public readonly isInverted = false; diff --git a/backend/src/objects/tunnel-physical.ts b/backend/src/objects/tunnel-physical.ts index eadfc70..73a046f 100644 --- a/backend/src/objects/tunnel-physical.ts +++ b/backend/src/objects/tunnel-physical.ts @@ -1,10 +1,10 @@ import { vec2 } from 'gl-matrix'; -import { clamp01, mix, TunnelBase, id, serializable } from 'shared'; +import { clamp01, mix, TunnelBase, id, serializesTo } from 'shared'; import { ImmutableBoundingBox } from '../physics/bounding-boxes/immutable-bounding-box'; import { StaticPhysical } from '../physics/containers/static-physical-object'; -@serializable(TunnelBase) +@serializesTo(TunnelBase) export class TunnelPhysical extends TunnelBase implements StaticPhysical { public readonly canCollide = true; public readonly isInverted = true; diff --git a/frontend/src/index.ts b/frontend/src/index.ts index b5e368a..27e9fd5 100644 --- a/frontend/src/index.ts +++ b/frontend/src/index.ts @@ -1,9 +1,17 @@ import { glMatrix } from 'gl-matrix'; +import { CharacterBase, LampBase, overrideDeserialization, TunnelBase } from 'shared'; import { Game } from './scripts/game'; +import { CharacterView } from './scripts/objects/character-view'; +import { LampView } from './scripts/objects/lamp-view'; +import { TunnelView } from './scripts/objects/tunnel-view'; import './styles/main.scss'; glMatrix.setMatrixArrayType(Array); +overrideDeserialization(CharacterBase, CharacterView); +overrideDeserialization(TunnelBase, TunnelView); +overrideDeserialization(LampBase, LampView); + const main = async () => { try { await new Game().start(); diff --git a/frontend/src/scripts/game.ts b/frontend/src/scripts/game.ts index aa8a5f0..b55c94d 100644 --- a/frontend/src/scripts/game.ts +++ b/frontend/src/scripts/game.ts @@ -29,14 +29,10 @@ import { RenderCommand } from './commands/types/render'; import { Configuration } from './config/configuration'; import { DeltaTimeCalculator } from './helper/delta-time-calculator'; import { rgb } from './helper/rgb'; -import { CharacterView } from './objects/character-view'; -import { TunnelView } from './objects/tunnel-view'; -import { LampView } from './objects/lamp-view'; + import { GameObjectContainer } from './objects/game-object-container'; import { BlobShape } from './shapes/blob-shape'; -const a = [CharacterView, TunnelView, LampView]; - export class Game { public readonly gameObjects = new GameObjectContainer(); private readonly canvas: HTMLCanvasElement = document.querySelector('canvas#main'); diff --git a/frontend/src/scripts/objects/character-view.ts b/frontend/src/scripts/objects/character-view.ts index 7de66bc..8cb63b6 100644 --- a/frontend/src/scripts/objects/character-view.ts +++ b/frontend/src/scripts/objects/character-view.ts @@ -1,9 +1,8 @@ import { vec2 } from 'gl-matrix'; -import { CharacterBase, CommandExecutors, deserializable } from 'shared'; +import { CharacterBase, CommandExecutors } from 'shared'; import { RenderCommand } from '../commands/types/render'; import { BlobShape } from '../shapes/blob-shape'; -@deserializable(CharacterBase) export class CharacterView extends CharacterBase { private shape = new BlobShape(); diff --git a/frontend/src/scripts/objects/lamp-view.ts b/frontend/src/scripts/objects/lamp-view.ts index 1c04fb6..a2b1045 100644 --- a/frontend/src/scripts/objects/lamp-view.ts +++ b/frontend/src/scripts/objects/lamp-view.ts @@ -1,9 +1,8 @@ import { vec2, vec3 } from 'gl-matrix'; import { CircleLight } from 'sdf-2d'; -import { CommandExecutors, deserializable, Id, LampBase } from 'shared'; +import { CommandExecutors, Id, LampBase } from 'shared'; import { RenderCommand } from '../commands/types/render'; -@deserializable(LampBase) export class LampView extends LampBase { private light: CircleLight; diff --git a/frontend/src/scripts/objects/tunnel-view.ts b/frontend/src/scripts/objects/tunnel-view.ts index bd34bf8..ecd6638 100644 --- a/frontend/src/scripts/objects/tunnel-view.ts +++ b/frontend/src/scripts/objects/tunnel-view.ts @@ -1,9 +1,8 @@ import { vec2 } from 'gl-matrix'; import { InvertedTunnel } from 'sdf-2d'; -import { CommandExecutors, deserializable, Id, TunnelBase } from 'shared'; +import { CommandExecutors, Id, TunnelBase } from 'shared'; import { RenderCommand } from '../commands/types/render'; -@deserializable(TunnelBase) export class TunnelView extends TunnelBase { private shape: InvertedTunnel; diff --git a/shared/src/commands/types/create-objects.ts b/shared/src/commands/types/create-objects.ts index b69cbc2..2579d8c 100644 --- a/shared/src/commands/types/create-objects.ts +++ b/shared/src/commands/types/create-objects.ts @@ -1,8 +1,8 @@ import { GameObject } from '../../objects/game-object'; -import { serializable } from '../../transport/serializable/serializable'; +import { serializable } from '../../transport/serialization/serializable'; import { Command } from '../command'; -@serializable() +@serializable export class CreateObjectsCommand extends Command { public constructor(public readonly objects: Array) { super(); diff --git a/shared/src/commands/types/create-player.ts b/shared/src/commands/types/create-player.ts index 4944d8b..f811412 100644 --- a/shared/src/commands/types/create-player.ts +++ b/shared/src/commands/types/create-player.ts @@ -1,8 +1,8 @@ import { CharacterBase } from '../../objects/types/character-base'; -import { serializable } from '../../transport/serializable/serializable'; +import { serializable } from '../../transport/serialization/serializable'; import { Command } from '../command'; -@serializable() +@serializable export class CreatePlayerCommand extends Command { public constructor(public readonly character: CharacterBase) { super(); diff --git a/shared/src/commands/types/delete-objects.ts b/shared/src/commands/types/delete-objects.ts index bec92ac..8a672e3 100644 --- a/shared/src/commands/types/delete-objects.ts +++ b/shared/src/commands/types/delete-objects.ts @@ -1,8 +1,8 @@ import { Id } from '../../transport/identity'; -import { serializable } from '../../transport/serializable/serializable'; +import { serializable } from '../../transport/serialization/serializable'; import { Command } from '../command'; -@serializable() +@serializable export class DeleteObjectsCommand extends Command { public constructor(public readonly ids: Array) { super(); diff --git a/shared/src/commands/types/move-action.ts b/shared/src/commands/types/move-action.ts index 902fc16..d3596ae 100644 --- a/shared/src/commands/types/move-action.ts +++ b/shared/src/commands/types/move-action.ts @@ -1,8 +1,8 @@ import { vec2 } from 'gl-matrix'; -import { serializable } from '../../transport/serializable/serializable'; +import { serializable } from '../../transport/serialization/serializable'; import { Command } from '../command'; -@serializable() +@serializable export class MoveActionCommand extends Command { public constructor(public readonly delta: vec2) { super(); diff --git a/shared/src/commands/types/primary-action.ts b/shared/src/commands/types/primary-action.ts index 6960bb3..fdc49f4 100644 --- a/shared/src/commands/types/primary-action.ts +++ b/shared/src/commands/types/primary-action.ts @@ -1,8 +1,8 @@ import { vec2 } from 'gl-matrix'; -import { serializable } from '../../transport/serializable/serializable'; +import { serializable } from '../../transport/serialization/serializable'; import { Command } from '../command'; -@serializable() +@serializable export class PrimaryActionCommand extends Command { public constructor(public readonly position: vec2) { super(); diff --git a/shared/src/commands/types/secondary-action.ts b/shared/src/commands/types/secondary-action.ts index 1241ad3..0edb39e 100644 --- a/shared/src/commands/types/secondary-action.ts +++ b/shared/src/commands/types/secondary-action.ts @@ -1,8 +1,8 @@ import { vec2 } from 'gl-matrix'; -import { serializable } from '../../transport/serializable/serializable'; +import { serializable } from '../../transport/serialization/serializable'; import { Command } from '../command'; -@serializable() +@serializable export class SecondaryActionCommand extends Command { public constructor(public readonly position: vec2) { super(); diff --git a/shared/src/commands/types/set-view-area-action.ts b/shared/src/commands/types/set-view-area-action.ts index f9f86ef..f2baa88 100644 --- a/shared/src/commands/types/set-view-area-action.ts +++ b/shared/src/commands/types/set-view-area-action.ts @@ -1,8 +1,8 @@ import { Rectangle } from '../../helper/rectangle'; -import { serializable } from '../../transport/serializable/serializable'; +import { serializable } from '../../transport/serialization/serializable'; import { Command } from '../command'; -@serializable() +@serializable export class SetViewAreaActionCommand extends Command { public constructor(public readonly viewArea: Rectangle) { super(); diff --git a/shared/src/commands/types/ternary-action.ts b/shared/src/commands/types/ternary-action.ts index 404fc70..547396f 100644 --- a/shared/src/commands/types/ternary-action.ts +++ b/shared/src/commands/types/ternary-action.ts @@ -1,8 +1,8 @@ import { vec2 } from 'gl-matrix'; -import { serializable } from '../../transport/serializable/serializable'; +import { serializable } from '../../transport/serialization/serializable'; import { Command } from '../command'; -@serializable() +@serializable export class TernaryActionCommand extends Command { public constructor(public readonly position: vec2) { super(); diff --git a/shared/src/commands/types/update-objects.ts b/shared/src/commands/types/update-objects.ts index 3741f8c..8469483 100644 --- a/shared/src/commands/types/update-objects.ts +++ b/shared/src/commands/types/update-objects.ts @@ -1,8 +1,8 @@ import { GameObject } from '../../objects/game-object'; -import { serializable } from '../../transport/serializable/serializable'; +import { serializable } from '../../transport/serialization/serializable'; import { Command } from '../command'; -@serializable() +@serializable export class UpdateObjectsCommand extends Command { public constructor(public readonly objects: Array) { super(); diff --git a/shared/src/helper/circle.ts b/shared/src/helper/circle.ts index 879221e..0418921 100644 --- a/shared/src/helper/circle.ts +++ b/shared/src/helper/circle.ts @@ -1,7 +1,7 @@ import { vec2 } from 'gl-matrix'; -import { serializable } from '../transport/serializable/serializable'; +import { serializable } from '../transport/serialization/serializable'; -@serializable() +@serializable export class Circle { constructor(public center: vec2, public radius: number) { } diff --git a/shared/src/helper/rectangle.ts b/shared/src/helper/rectangle.ts index af1f3cc..9758cce 100644 --- a/shared/src/helper/rectangle.ts +++ b/shared/src/helper/rectangle.ts @@ -1,7 +1,7 @@ import { vec2 } from 'gl-matrix'; -import { serializable } from '../transport/serializable/serializable'; +import { serializable } from '../transport/serialization/serializable'; -@serializable() +@serializable export class Rectangle { constructor(public topLeft = vec2.create(), public size = vec2.create()) { } diff --git a/shared/src/main.ts b/shared/src/main.ts index 8dbea13..abef016 100644 --- a/shared/src/main.ts +++ b/shared/src/main.ts @@ -22,9 +22,11 @@ export * from './helper/random'; export * from './helper/unique'; export * from './helper/rotate-90-deg'; export * from './objects/game-object'; -export * from './transport/serializable/deserialize'; -export * from './transport/serializable/serialize'; -export * from './transport/serializable/serializable'; +export * from './transport/serialization/deserialize'; +export * from './transport/serialization/serialize'; +export * from './transport/serialization/serializes-to'; +export * from './transport/serialization/serializable'; +export * from './transport/serialization/override-deserialization'; export * from './objects/types/character-base'; export * from './objects/types/lamp-base'; export * from './objects/types/tunnel-base'; diff --git a/shared/src/objects/types/character-base.ts b/shared/src/objects/types/character-base.ts index d7310ad..799d273 100644 --- a/shared/src/objects/types/character-base.ts +++ b/shared/src/objects/types/character-base.ts @@ -1,10 +1,10 @@ import { Circle } from '../../helper/circle'; import { Id } from '../../transport/identity'; -import { serializable } from '../../transport/serializable/serializable'; +import { serializable } from '../../transport/serialization/serializable'; import { GameObject } from '../game-object'; -@serializable() -export abstract class CharacterBase extends GameObject { +@serializable +export class CharacterBase extends GameObject { constructor( id: Id, public head: Circle, diff --git a/shared/src/objects/types/lamp-base.ts b/shared/src/objects/types/lamp-base.ts index 8090ae6..cf594a2 100644 --- a/shared/src/objects/types/lamp-base.ts +++ b/shared/src/objects/types/lamp-base.ts @@ -2,8 +2,8 @@ import { vec2, vec3 } from 'gl-matrix'; import { Id, serializable } from '../../main'; import { GameObject } from '../game-object'; -@serializable() -export abstract class LampBase extends GameObject { +@serializable +export class LampBase extends GameObject { constructor(id: Id, public center: vec2, public color: vec3, public lightness: number) { super(id); } diff --git a/shared/src/objects/types/tunnel-base.ts b/shared/src/objects/types/tunnel-base.ts index 6818c55..79ac7da 100644 --- a/shared/src/objects/types/tunnel-base.ts +++ b/shared/src/objects/types/tunnel-base.ts @@ -1,10 +1,10 @@ import { vec2 } from 'gl-matrix'; import { Id } from '../../transport/identity'; -import { serializable } from '../../transport/serializable/serializable'; +import { serializable } from '../../transport/serialization/serializable'; import { GameObject } from '../game-object'; -@serializable() -export abstract class TunnelBase extends GameObject { +@serializable +export class TunnelBase extends GameObject { constructor( id: Id, public readonly from: vec2, diff --git a/shared/src/transport/serializable/deserialize.ts b/shared/src/transport/serializable/deserialize.ts deleted file mode 100644 index 0d9009a..0000000 --- a/shared/src/transport/serializable/deserialize.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { serializableClasses } from './serializable'; - -export const deserialize = (json: string): any => { - return JSON.parse(json, (k, v) => { - const possibleType = v[0]; - const overridableConstructor = serializableClasses.get(possibleType); - if (overridableConstructor) { - const [_, ...values] = v; - return new overridableConstructor.constructor(...values); - } - return v; - }); -}; diff --git a/shared/src/transport/serializable/serializable.ts b/shared/src/transport/serializable/serializable.ts deleted file mode 100644 index 85cfc63..0000000 --- a/shared/src/transport/serializable/serializable.ts +++ /dev/null @@ -1,58 +0,0 @@ -export const serializableClasses = new Map< - string, - { - constructor: any; - overriden: boolean; - } ->(); - -export const serializable = (serializableType?) => { - return (type): any => { - const actualType = serializableType - ? Object.getPrototypeOf((serializableType as any).prototype).constructor - : type; - - const typeName = actualType.name; - - const overridableConstructor = serializableClasses.get(typeName); - if (!overridableConstructor) { - serializableClasses.set(typeName, { - constructor: actualType, - overriden: false, - }); - } - - if (!Object.prototype.hasOwnProperty.call(actualType.prototype, 'toArray')) { - throw new Error( - `Class ${typeName} must define a toArray returning an array containing the arguments for its constructor.` - ); - } - - return class extends type { - public get type(): string { - return typeName; - } - - public static get type(): string { - return typeName; - } - }; - }; -}; - -export const deserializable = (fromType) => { - return (type): any => { - const overridableConstructor = serializableClasses.get(fromType.name); - if (!overridableConstructor || !overridableConstructor.overriden) { - serializableClasses.set(fromType.name, { - constructor: type, - overriden: true, - }); - } else { - throw new Error( - `Constructor ${fromType} already overriden, cannot override again with ${type}` - ); - } - return type; - }; -}; diff --git a/shared/src/transport/serializable/serialize.ts b/shared/src/transport/serializable/serialize.ts deleted file mode 100644 index 521c0f7..0000000 --- a/shared/src/transport/serializable/serialize.ts +++ /dev/null @@ -1,10 +0,0 @@ -export const serialize = (object): string => { - const result = JSON.stringify(object, (key, value) => { - if (value?.type) { - return [value.type, ...value.toArray()]; - } - return value?.toFixed ? Number(value.toFixed(3)) : value; - }); - - return result; -}; diff --git a/shared/src/transport/serialization/deserializable-class.ts b/shared/src/transport/serialization/deserializable-class.ts new file mode 100644 index 0000000..9913aa1 --- /dev/null +++ b/shared/src/transport/serialization/deserializable-class.ts @@ -0,0 +1 @@ +export type DeserializableClass = { new(...args: Array): {}; name: string }; diff --git a/shared/src/transport/serialization/deserialize.ts b/shared/src/transport/serialization/deserialize.ts new file mode 100644 index 0000000..3d9dcfb --- /dev/null +++ b/shared/src/transport/serialization/deserialize.ts @@ -0,0 +1,13 @@ +import { serializableMapping } from './serializable-mapping'; + +export const deserialize = (json: string): any => { + return JSON.parse(json, (k, v) => { + const possibleType = v[0]; + const overridableConstructor = serializableMapping.get(possibleType); + if (overridableConstructor) { + v.shift(); + return new overridableConstructor.constructor(...v); + } + return v; + }); +}; diff --git a/shared/src/transport/serialization/override-deserialization.ts b/shared/src/transport/serialization/override-deserialization.ts new file mode 100644 index 0000000..d80d202 --- /dev/null +++ b/shared/src/transport/serialization/override-deserialization.ts @@ -0,0 +1,13 @@ +import { DeserializableClass } from './deserializable-class'; +import { SerializableClass } from './serializable-class'; +import { serializableMapping } from './serializable-mapping'; + +export const overrideDeserialization = ( + source: SerializableClass, + target: DeserializableClass +) => { + serializableMapping.set(source.name, { + constructor: target, + overriden: true, + }); +}; diff --git a/shared/src/transport/serialization/serializable-class.ts b/shared/src/transport/serialization/serializable-class.ts new file mode 100644 index 0000000..41438ca --- /dev/null +++ b/shared/src/transport/serialization/serializable-class.ts @@ -0,0 +1,4 @@ +export type SerializableClass = { + new(...args: Array): { toArray(): Array }; + name: string; +}; diff --git a/shared/src/transport/serialization/serializable-mapping.ts b/shared/src/transport/serialization/serializable-mapping.ts new file mode 100644 index 0000000..bb9b731 --- /dev/null +++ b/shared/src/transport/serialization/serializable-mapping.ts @@ -0,0 +1,12 @@ +import { DeserializableClass } from './deserializable-class'; + +/** + * @internal + */ +export const serializableMapping = new Map< + string, + { + constructor: DeserializableClass; + overriden: boolean; + } +>(); diff --git a/shared/src/transport/serialization/serializable.ts b/shared/src/transport/serialization/serializable.ts new file mode 100644 index 0000000..967e6cc --- /dev/null +++ b/shared/src/transport/serialization/serializable.ts @@ -0,0 +1,16 @@ +import { SerializableClass } from './serializable-class'; +import { serializableMapping } from './serializable-mapping'; + +export const serializable = (type: SerializableClass): any => { + if (!serializableMapping.get(type.name)) { + serializableMapping.set(type.name, { + constructor: type, + overriden: false, + }); + } + + Object.defineProperty(type, '__serializable_type', { value: type.name }); + Object.defineProperty(type.prototype, '__serializable_type', { value: type.name }); + + return type; +}; diff --git a/shared/src/transport/serialization/serialize.ts b/shared/src/transport/serialization/serialize.ts new file mode 100644 index 0000000..eb4d97f --- /dev/null +++ b/shared/src/transport/serialization/serialize.ts @@ -0,0 +1,8 @@ +export const serialize = (object): string => { + return JSON.stringify(object, (_, value) => { + if (value?.__serializable_type) { + return [value.__serializable_type, ...value.toArray()]; + } + return value?.toFixed ? Number(value.toFixed(3)) : value; + }); +}; diff --git a/shared/src/transport/serialization/serializes-to.ts b/shared/src/transport/serialization/serializes-to.ts new file mode 100644 index 0000000..1346164 --- /dev/null +++ b/shared/src/transport/serialization/serializes-to.ts @@ -0,0 +1,20 @@ +import { SerializableClass } from './serializable-class'; +import { serializableMapping } from './serializable-mapping'; + +export const serializesTo = (target: SerializableClass) => { + return (actual: SerializableClass): any => { + if (!serializableMapping.get(target.name)) { + serializableMapping.set(target.name, { + constructor: target, + overriden: false, + }); + } + + Object.defineProperty(actual, '__serializable_type', { value: target.name }); + Object.defineProperty(actual.prototype, '__serializable_type', { + value: target.name, + }); + + return actual; + }; +};