@kol1993/proto
TypeScript icon, indicating that this package has built-in type declarations

0.1.3 • Public • Published

TypeRegistry

Creating type registry

import { TypeRegistries } from '@temabit/proto';

abstract class ABase {
  abstract todo(): void;
}

const registry = TypeRegistries.create(ABase, '@@type');

Persisting type registry

import { TypeRegistries } from '@temabit/proto';

abstract class ABase {
  abstract todo(): void;
}

const registry = TypeRegistries.for(ABase, '@@type');

Adding implementations to registry

import { TypeRegistries } from '.';

abstract class ABase {
  abstract todo(): void;
}
const Implementations = TypeRegistries.for(ABase, '@@type');


@Implementations.Define() // defines implementation with `
class ImplementationA extends ABase {
  todo() {
    console.log(this.constructor.name);
  }
}

@Implementations.Define({
  name: 'B' // defines class with specific name
})
class ImplementationB extends ABase {
  todo() {
    console.log(this.constructor.name);
  }
}

Adding serializable properties to classes

import { TypeRegistries } from '.';

const Objects = TypeRegistries.for(Object, '@@type');

abstract class AConnection {
  @Expose()
  @Objects.Integer()
  public timeout!: number; // Common property

  public abstract connect(): Promise<any>;
}
const Connections = TypeRegistries.for(AConnection, '@@type');


@Connections.Define({ name: 'postgres' })
class PostgresConnection extends AConnection {
  @Expose()
  @Connections.String()
  public host!: string;

  @Expose()
  @Connections.String()
  public user!: string;

  @Expose()
  @Connections.String()
  public database!: string;

  @Expose()
  @Connections.Integer()
  public port!: number;

  public connect() {
    return Promise.resolve(this);
  }
}

@Connections.Define({ name: 'sqlite' })
class SQLiteConnection extends AConnection {
  @Expose()
  @Connections.String()
  public filename!: string;

  public connect() {
    return Promise.resolve(this);
  }
}

Adding property validators

import { TypeRegistries, Validate } from '.';

const Objects = TypeRegistries.for(Object, '@@type');

abstract class AConnection {
  @Expose()
  @Objects.Integer([
    Validate.Number.Positive(),
    Validate.Number.Max(Math.pow(2, 31) - 1)
  ])
  public timeout!: number; // Common property

  public abstract connect(): Promise<any>;
}
const Connections = TypeRegistries.for(AConnection, '@@type');


@Connections.Define({ name: 'postgres' })
class PostgresConnection extends AConnection {
  @Expose()
  @Connections.String([
    Validate.String.IsNotEmpty()
  ])
  public host!: string;

  @Expose()
  @Connections.String([
    Validate.String.IsNotEmpty()
  ])
  public user!: string;

  @Expose()
  @Connections.String([
    Validate.String.IsNotEmpty()
  ])
  public database!: string;

  @Expose()
  @Connections.Integer([
    Validate.Number.Min(1),
    Validate.Number.Max(65536),
  ])
  public port!: number;

  public connect() {
    return Promise.resolve(this);
  }
}

@Connections.Define({ name: 'sqlite' })
class SQLiteConnection extends AConnection {
  @Connections.String([
    Validate.String.IsNotEmpty()
  ])
  public filename!: string;

  public connect() {
    return Promise.resolve(this);
  }
}

Parsing plain instance

import { TypeRegistries, Validate } from '.';

const Objects = TypeRegistries.for(Object, '@@type');

abstract class AConnection {
  @Objects.Integer([
    Validate.Number.Positive(),
    Validate.Number.Max(Math.pow(2, 31) - 1)
  ])
  public timeout!: number; // Common property

  public abstract connect(): Promise<any>;
}
const Connections = TypeRegistries.for(AConnection, '@@type');


@Connections.Define({ name: 'postgres' })
class PostgresConnection extends AConnection {
  @Connections.String([
    Validate.String.IsNotEmpty()
  ])
  public host!: string;

  @Connections.String([
    Validate.String.IsNotEmpty()
  ])
  public user!: string;

  @Connections.String([
    Validate.String.IsNotEmpty()
  ])
  public database!: string;

  @Connections.Integer([
    Validate.Number.Min(1),
    Validate.Number.Max(65536),
  ])
  public port!: number;

  public connect() {
    return Promise.resolve(this);
  }
}

@Connections.Define({ name: 'sqlite' })
class SQLiteConnection extends AConnection {
  @Connections.String([
    Validate.String.IsNotEmpty()
  ])
  public filename!: string;

  public connect() {
    return Promise.resolve(this);
  }
}

try {
  console.log(Connections.parseInstance({
    '@@type': "postgres",
    timeout: 1000,
    host: 'localhost',
    port: 5432,
    user: 'postgres',
    database: 'postgres',
  }));
  /*
   PostgresConnection {
    timeout: 1000,
    host: 'localhost',
    user: 'postgres',
    database: 'postgres',
    port: 5432
   }
   */
} catch (e) {
  console.error(String(e));
}

try {
  console.log(Connections.parseInstance({
    '@@type': "sqlite",
    timeout: 1000,
    filename: 'test.sqlite3'
  }));
  /*
   SQLiteConnection { timeout: 1000, filename: 'test.sqlite3' }
   */
} catch (e) {
  console.error(String(e));
}

try {
  console.log(Connections.parseInstance({
    '@@type': "unknown",
    timeout: 1000,
    filename: 'test.sqlite3'
  }));
} catch (e) {
  console.error(String(e));
  /*
   ValidationFailure: : data must be an instance of AConnection
   */
}

Parsing plain array

import { TypeRegistries, Validate } from '.';

const Objects = TypeRegistries.for(Object, '@@type');

abstract class AConnection {
  @Objects.Integer([
    Validate.Number.Positive(),
    Validate.Number.Max(Math.pow(2, 31) - 1)
  ])
  public timeout!: number; // Common property

  public abstract connect(): Promise<any>;
}
const Connections = TypeRegistries.for(AConnection, '@@type');


@Connections.Define({ name: 'postgres' })
class PostgresConnection extends AConnection {
  @Connections.String([
    Validate.String.IsNotEmpty()
  ])
  public host!: string;

  @Connections.String([
    Validate.String.IsNotEmpty()
  ])
  public user!: string;

  @Connections.String([
    Validate.String.IsNotEmpty()
  ])
  public database!: string;

  @Connections.Integer([
    Validate.Number.Min(1),
    Validate.Number.Max(65536),
  ])
  public port!: number;

  public connect() {
    return Promise.resolve(this);
  }
}

@Connections.Define({ name: 'sqlite' })
class SQLiteConnection extends AConnection {
  @Connections.String([
    Validate.String.IsNotEmpty()
  ])
  public filename!: string;

  public connect() {
    return Promise.resolve(this);
  }
}

try {
  console.log(Connections.parseArray([
    {
      '@@type': "postgres",
      timeout: 1000,
      host: 'localhost',
      port: 5432,
      user: 'postgres',
      database: 'postgres',
    },
    {
      '@@type': "sqlite",
      timeout: 1000,
      filename: 'test.sqlite3'
    }
  ]));
  /*
   [
       PostgresConnection {
           timeout: 1000,
           host: 'localhost',
           user: 'postgres',
           database: 'postgres',
           port: 5432
       },
       SQLiteConnection { timeout: 1000, filename: 'test.sqlite3' }
   ]
   */
} catch (e) {
  console.error(String(e));
}

Validating parsed instances or arrays

import { TypeRegistries, Validate } from '.';


const Objects = TypeRegistries.for(Object, '@@type');


abstract class AConnection {
  @Objects.Integer([
    Validate.Number.Positive(),
    Validate.Number.Max(Math.pow(2, 31) - 1),
  ])
  public timeout!: number; // Common property

  public abstract connect(): Promise<any>;
}


const Connections = TypeRegistries.for(AConnection, '@@type');


@Connections.Define({name: 'sqlite'})
class SQLiteConnection extends AConnection {
  @Connections.String([
    Validate.String.IsNotEmpty(),
  ])
  public filename!: string;

  public connect() {
    return Promise.resolve(this);
  }
}


try {
  const instance = Connections.parseInstance({
    '@@type': 'sqlite',
    timeout: 1000,
    filename: '',
  });
  Connections.assert(Connections.validate(instance));
} catch (e) {
  console.error(String(e));
  /*
   ValidationFailure: .filename: filename should not be empty
   */
}

Serialization

import { TypeRegistries, Validate } from '.';


const Objects = TypeRegistries.for(Object, '@@type');


abstract class AConnection {
  @Objects.Integer([
    Validate.Number.Positive(),
    Validate.Number.Max(Math.pow(2, 31) - 1),
  ])
  public timeout!: number; // Common property

  public abstract connect(): Promise<any>;
}


const Connections = TypeRegistries.for(AConnection, '@@type');


@Connections.Define({name: 'sqlite'})
class SQLiteConnection extends AConnection {
  @Connections.String([
    Validate.String.IsNotEmpty(),
  ])
  public filename!: string;

  public connect() {
    return Promise.resolve(this);
  }
}


try {
  const instance = new SQLiteConnection();
  instance.filename = '123';
  instance.timeout = 1000;
  console.log(Connections.serialize(instance));
  /*
   { filename: '123', timeout: 1000, '@@type': 'sqlite' }
   */
} catch (e) {
  console.error(String(e));
}

Cloning

import { TypeRegistries, Validate } from '.';


const Objects = TypeRegistries.for(Object, '@@type');


abstract class AConnection {
  @Objects.Integer([
    Validate.Number.Positive(),
    Validate.Number.Max(Math.pow(2, 31) - 1),
  ])
  public timeout!: number; // Common property

  public abstract connect(): Promise<any>;
}


const Connections = TypeRegistries.for(AConnection, '@@type');


@Connections.Define({name: 'sqlite'})
class SQLiteConnection extends AConnection {
  @Connections.String([
    Validate.String.IsNotEmpty(),
  ])
  public filename!: string;

  public connect() {
    return Promise.resolve(this);
  }
}


try {
  const instance = new SQLiteConnection();
  instance.filename = '123';
  instance.timeout = 1000;
  console.log(Connections.clone(instance));
  /*
   SQLiteConnection { filename: '123', timeout: 1000 }
   */
} catch (e) {
  console.error(String(e));
}

Complex sample

import { TypeRegistries, Validate } from '.';

const Objects = TypeRegistries.for(Object, 'type');

class Point {
  @Objects.Number()
  public x!: number;

  @Objects.Number()
  public y!: number;
}

abstract class ASceneObject {
  public abstract draw(context: CanvasRenderingContext2D): void;
}

const SceneObjects = TypeRegistries.for(ASceneObject, '@@type');

@SceneObjects.Define()
class Scene extends ASceneObject {
  @SceneObjects.Array(
    SceneObjects.AbstractInstance()
  )
  public children!: ASceneObject[];

  public draw(context: CanvasRenderingContext2D): void {
    for (const child of this.children) {
      try {
        context.save();
        child.draw(context);
      } finally {
        context.restore();
      }
    }
  }
}

@SceneObjects.Define()
class Circle extends ASceneObject {
  @SceneObjects.Instance({
    type: Point
  })
  public point!: Point;

  @SceneObjects.Number([
    Validate.Number.Positive()
  ])
  public radius!: number;

  public draw(context: CanvasRenderingContext2D): void {
    context.arc(this.point.x, this.point.y, this.radius, 0, 2*Math.PI);
  }
}

@SceneObjects.Define()
class Line extends ASceneObject {
  @SceneObjects.Array(
    SceneObjects.Instance({
      type: Point
    })
  )
  public points!: Point[];

  public draw(context: CanvasRenderingContext2D): void {
    if (this.points.length > 1) {
      const [start, ...points] = this.points;
      context.moveTo(start.x, start.y);
      for (const p of points) {
        context.lineTo(p.x, p.y);
      }
    }
  }
}

console.dir(SceneObjects.parseInstance(
  {
    '@@type': Scene.name,
    children: [
      {
        '@@type': Line.name,
        points: [
          {
            x: 0, y: 0,
          },
          {
            x: 0, y: 1,
          },
          {
            x: 1, y: 1,
          },
          {
            x: 1, y: 0,
          },
        ]
      },
      {
        '@@type': Circle.name,
        point: {
          x: 5,
          y: 5,
        },
        radius: 3
      }
    ]
  }
), { depth: null });
/*
 Scene {
  children: [
    Line {
      points: [
        Point { x: 0, y: 0 },
        Point { x: 0, y: 1 },
        Point { x: 1, y: 1 },
        Point { x: 1, y: 0 }
      ]
    },
    Circle { point: Point { x: 5, y: 5 }, radius: 3 }
  ]
 }
 */

Readme

Keywords

none

Package Sidebar

Install

npm i @kol1993/proto

Weekly Downloads

0

Version

0.1.3

License

ISC

Unpacked Size

1.02 MB

Total Files

339

Last publish

Collaborators

  • kol-93