add some common type and function and pass test
This commit is contained in:
		
							
								
								
									
										59
									
								
								server/common.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								server/common.test.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
import { type } from "./common"
 | 
			
		||||
import _ from "lodash"
 | 
			
		||||
import { expect, test } from "bun:test"
 | 
			
		||||
 | 
			
		||||
const CYCLES = 10000
 | 
			
		||||
test("Test Integer and Unsigned Integer", () => {
 | 
			
		||||
  for (let i = 0; i < CYCLES; i++) {
 | 
			
		||||
 | 
			
		||||
    // Unsigned Integer
 | 
			
		||||
    expect(type.UInteger.safeParse(_.random(0, Math.pow(2, 53), false)).success).toBeTrue()
 | 
			
		||||
    expect(type.UInt8.safeParse(_.random(0, Math.pow(2, 8) - 1, false)).success).toBeTrue()
 | 
			
		||||
    expect(type.UInt8.safeParse(_.random(Math.pow(2, 8), Math.pow(2, 53), false)).success).toBeFalse()
 | 
			
		||||
    expect(type.UInt16.safeParse(_.random(0, Math.pow(2, 16) - 1, false)).success).toBeTrue()
 | 
			
		||||
    expect(type.UInt16.safeParse(_.random(Math.pow(2, 16), Math.pow(2, 53), false)).success).toBeFalse()
 | 
			
		||||
    expect(type.UInt32.safeParse(_.random(0, Math.pow(2, 32) - 1, false)).success).toBeTrue()
 | 
			
		||||
    expect(type.UInt32.safeParse(_.random(Math.pow(2, 32), Math.pow(2, 53), false)).success).toBeFalse()
 | 
			
		||||
 | 
			
		||||
    // Integer
 | 
			
		||||
    expect(type.Integer.safeParse(_.random(-Math.pow(2, 52), Math.pow(2, 52) - 1, false)).success).toBeTrue()
 | 
			
		||||
    expect(type.Int8.safeParse(_.random(-Math.pow(2, 7), Math.pow(2, 7) - 1, false)).success).toBeTrue()
 | 
			
		||||
    expect(type.Int8.safeParse(_.random(Math.pow(2, 7), Math.pow(2, 52), false)).success).toBeFalse()
 | 
			
		||||
    expect(type.Int8.safeParse(_.random(-Math.pow(2, 52), -Math.pow(2, 7) - 1, false)).success).toBeFalse()
 | 
			
		||||
    expect(type.Int16.safeParse(_.random(-Math.pow(2, 15), Math.pow(2, 15) - 1, false)).success).toBeTrue()
 | 
			
		||||
    expect(type.Int16.safeParse(_.random(Math.pow(2, 15), Math.pow(2, 52), false)).success).toBeFalse()
 | 
			
		||||
    expect(type.Int16.safeParse(_.random(-Math.pow(2, 52), -Math.pow(2, 15) - 1, false)).success).toBeFalse()
 | 
			
		||||
    expect(type.Int32.safeParse(_.random(-Math.pow(2, 31), Math.pow(2, 31) - 1, false)).success).toBeTrue()
 | 
			
		||||
    expect(type.Int32.safeParse(_.random(Math.pow(2, 31), Math.pow(2, 52), false)).success).toBeFalse()
 | 
			
		||||
    expect(type.Int32.safeParse(_.random(-Math.pow(2, 52), -Math.pow(2, 31) - 1, false)).success).toBeFalse()
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test("Test Number Processor Function", () => {
 | 
			
		||||
  // Convert Number to Uint8Array
 | 
			
		||||
  expect(type.numberToBytes(0xFF, 1).unwrap()[0]).toBe(255)
 | 
			
		||||
  expect(type.numberToBytes(0xAAAA, 2).unwrap()).toEqual(new Uint8Array([0xAA, 0xAA]))
 | 
			
		||||
  expect(type.numberToBytes(0x12345678, 4).unwrap()).toEqual(new Uint8Array([0x78, 0x56, 0x34, 0x12]))
 | 
			
		||||
  expect(type.numberToBytes(0x12345678, 4, true).unwrap()).toEqual(new Uint8Array([0x12, 0x34, 0x56, 0x78]))
 | 
			
		||||
 | 
			
		||||
  // Number Match 
 | 
			
		||||
  for (let i = 0; i < CYCLES; i++) {
 | 
			
		||||
    const num1 = _.random(CYCLES / 2, false)
 | 
			
		||||
    const num2 = _.random(CYCLES / 2, false)
 | 
			
		||||
 | 
			
		||||
    expect(type.numberMatch(num1, num2)).toBe((num1 & num2) === num2 ? true : false)
 | 
			
		||||
    expect(type.numberMatch(num1, num2, "True", "False")).toBe((num1 & num2) === num2 ? "True" : "False")
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Number Set, Unset, Toggle and Get Bit
 | 
			
		||||
  expect(type.numberSetBit(0, 5)).toBe(0b10000)
 | 
			
		||||
  expect(type.numberUnsetBit(0b1111, 3)).toBe(0b1011)
 | 
			
		||||
  expect(type.numberToggleBit(0b1010, 3)).toBe(0b1110)
 | 
			
		||||
  expect(type.numberBit(0b1100, 2)).toBe(0)
 | 
			
		||||
 | 
			
		||||
  // Get High / Low Bits Num 
 | 
			
		||||
  expect(type.numberHighBitsNum(0xFF).unwrap()).toBe(8)
 | 
			
		||||
  expect(type.numberHighBitsNum(0xAA).unwrap()).toBe(4)
 | 
			
		||||
  expect(type.numberLowBitsNum(0xFF, 8).unwrap()).toBe(0)
 | 
			
		||||
  expect(type.numberLowBitsNum(0xAA, 8).unwrap()).toBe(4)
 | 
			
		||||
})
 | 
			
		||||
@@ -6,27 +6,47 @@ export function UNUSED(_: unknown): void { }
 | 
			
		||||
 | 
			
		||||
export namespace type {
 | 
			
		||||
 | 
			
		||||
  const NUMBER_MAX_LENGTH = 32
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  export const ErrorTypeSchema = z.union([
 | 
			
		||||
    z.literal("Not Integer"),
 | 
			
		||||
    z.literal("Not Unsigned Integer"),
 | 
			
		||||
    z.literal("Not 32Bits Integer")
 | 
			
		||||
  ])
 | 
			
		||||
 | 
			
		||||
  export type ErrorType = z.infer<typeof ErrorTypeSchema>
 | 
			
		||||
 | 
			
		||||
  export const Integer = z.number().int()
 | 
			
		||||
  export const UInteger = z.number().int().nonnegative()
 | 
			
		||||
 | 
			
		||||
  export const UInt8 = z.number().int().nonnegative().lt(Math.pow(2, 8))
 | 
			
		||||
  export const UInt16 = z.number().int().nonnegative().lt(Math.pow(2, 16))
 | 
			
		||||
  export const UInt32 = z.number().int().nonnegative().lt(Math.pow(2, 32))
 | 
			
		||||
  export const UInt8 = UInteger.lt(Math.pow(2, 8))
 | 
			
		||||
  export const UInt16 = UInteger.lt(Math.pow(2, 16))
 | 
			
		||||
  export const UInt32 = UInteger.lt(Math.pow(2, 32))
 | 
			
		||||
 | 
			
		||||
  export const Int8 = z.number().int().lt(Math.pow(2, 7)).gte(-Math.pow(2, 8))
 | 
			
		||||
  export const Int16 = z.number().int().lt(Math.pow(2, 15)).gte(-Math.pow(2, 16))
 | 
			
		||||
  export const Int32 = z.number().int().lt(Math.pow(2, 31)).gte(-Math.pow(2, 32))
 | 
			
		||||
  export const Int8 = Integer.lt(Math.pow(2, 7)).gte(-Math.pow(2, 8))
 | 
			
		||||
  export const Int16 = Integer.lt(Math.pow(2, 15)).gte(-Math.pow(2, 16))
 | 
			
		||||
  export const Int32 = Integer.lt(Math.pow(2, 31)).gte(-Math.pow(2, 32))
 | 
			
		||||
 | 
			
		||||
  export function numberToBytes(num: number, bytesLength: number): Result<Uint8Array, "Not Integer"> {
 | 
			
		||||
  export function numberToBytes(num: number, bytesLength: number, reverse: boolean = false)
 | 
			
		||||
    : Result<Uint8Array, ErrorType> {
 | 
			
		||||
    // Check Integer
 | 
			
		||||
    if (!(Integer.safeParse(num).success && Integer.safeParse(bytesLength).success)) {
 | 
			
		||||
      return new Err("Not Integer")
 | 
			
		||||
    if (!Int32.safeParse(num).success && !UInt32.lte(32).safeParse(bytesLength).success) {
 | 
			
		||||
      console.error(`Number : ${num}, 2 ^ 31 = ${2 ^ 31}`)
 | 
			
		||||
      console.error(Int32.safeParse(num).error?.message)
 | 
			
		||||
      return new Err("Not 32Bits Integer")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var array = new Uint8Array(bytesLength)
 | 
			
		||||
 | 
			
		||||
    for (let i = 0; i < bytesLength; i++) {
 | 
			
		||||
      array[i] = num & (0xFF << (i << 3))
 | 
			
		||||
    if (reverse) {
 | 
			
		||||
      for (let i = 0; i < bytesLength; i++) {
 | 
			
		||||
        array[bytesLength - 1 - i] = ((num >> (i << 3)) & 0xFF)
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      for (let i = 0; i < bytesLength; i++) {
 | 
			
		||||
        array[i] = ((num >> (i << 3)) & 0xFF)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return new Ok(array)
 | 
			
		||||
@@ -60,14 +80,47 @@ export namespace type {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  export function numberSetBit(num: number, loc: number): number {
 | 
			
		||||
    return num | (1 << loc)
 | 
			
		||||
    return num | (1 << (loc - 1))
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  export function numberUnsetBit(num: number, loc: number): number {
 | 
			
		||||
    return num | (~1 << loc)
 | 
			
		||||
    return num & ~(1 << (loc - 1))
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  export function numberHighBits(num: number) {
 | 
			
		||||
  export function numberToggleBit(num: number, loc: number): number {
 | 
			
		||||
    return num ^ (1 << (loc - 1))
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  export function numberBit(num: number, loc: number): number {
 | 
			
		||||
    return (num >> (loc - 1)) & 1
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  export function numberHighBitsNum(num: number, maxLen: number = NUMBER_MAX_LENGTH): Result<number, ErrorType> {
 | 
			
		||||
    if (!Int32.safeParse(num).success && maxLen > 32) {
 | 
			
		||||
      return new Err("Not 32Bits Integer")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let cnt = 0
 | 
			
		||||
    for (let i = 0; i < maxLen; i++) {
 | 
			
		||||
      if (num & (1 << i)) {
 | 
			
		||||
        cnt++
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return new Ok(cnt)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  export function numberLowBitsNum(num: number, maxLen: number): Result<number, ErrorType> {
 | 
			
		||||
    if (!Int32.safeParse(num).success && maxLen > 32) {
 | 
			
		||||
      return new Err("Not 32Bits Integer")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let cnt = 0
 | 
			
		||||
    for (let i = 0; i < maxLen; i++) {
 | 
			
		||||
      if (!(num & (1 << i))) {
 | 
			
		||||
        cnt++
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return new Ok(cnt)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  export function isStringArray(obj: any): obj is Array<string> {
 | 
			
		||||
 
 | 
			
		||||
@@ -2,23 +2,20 @@ import { Database, type Changes } from "bun:sqlite";
 | 
			
		||||
import _ from "lodash";
 | 
			
		||||
import { Ok, Err, Result, None, Some, Option } from "ts-results-es";
 | 
			
		||||
import { z } from "zod";
 | 
			
		||||
import { fun } from "./common";
 | 
			
		||||
import { fun, type } from "./common";
 | 
			
		||||
 | 
			
		||||
const db = new Database("lab.sqlite", { strict: true })
 | 
			
		||||
initDB(db);
 | 
			
		||||
 | 
			
		||||
// Error Type
 | 
			
		||||
export const BOARD_ERR_WRONG_TYPE = "Wrong type"
 | 
			
		||||
export const BOARD_ERR_NO_BOARDS = "No such Boards"
 | 
			
		||||
export const BOARD_ERR_ID_CONFLICT = "ID conflict"
 | 
			
		||||
export const BOARD_ERR_NAME_CONFLICT = "Name conflict in one room"
 | 
			
		||||
const BoardErrorTypeSchema = z.union([
 | 
			
		||||
  z.literal("Wrong Type"),
 | 
			
		||||
  z.literal("No Such Board(s)"),
 | 
			
		||||
  z.literal("ID Conflict"),
 | 
			
		||||
  z.literal("Name Conflict")
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
export type BoardErrorType = (
 | 
			
		||||
  typeof BOARD_ERR_WRONG_TYPE |
 | 
			
		||||
  typeof BOARD_ERR_NO_BOARDS |
 | 
			
		||||
  typeof BOARD_ERR_ID_CONFLICT |
 | 
			
		||||
  typeof BOARD_ERR_NAME_CONFLICT
 | 
			
		||||
)
 | 
			
		||||
export type BoardErrorType = z.infer<typeof BoardErrorTypeSchema>
 | 
			
		||||
 | 
			
		||||
const boardSchema = z.object({
 | 
			
		||||
  id: z.number().nonnegative(),
 | 
			
		||||
@@ -125,7 +122,7 @@ export namespace BoardTable {
 | 
			
		||||
 | 
			
		||||
  export function add(board: Board): Result<Changes, BoardErrorType> {
 | 
			
		||||
    if (!isBoard(board)) {
 | 
			
		||||
      return new Err(BOARD_ERR_WRONG_TYPE)
 | 
			
		||||
      return new Err("Wrong Type")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Ensure no id conflict
 | 
			
		||||
@@ -135,9 +132,9 @@ export namespace BoardTable {
 | 
			
		||||
    } else {
 | 
			
		||||
      const retID = includes(board.id)
 | 
			
		||||
      if (retID.isOk()) {
 | 
			
		||||
        if (retID.value) return new Err(BOARD_ERR_ID_CONFLICT)
 | 
			
		||||
        if (retID.value) return new Err("ID Conflict")
 | 
			
		||||
      } else {
 | 
			
		||||
        return new Err(BOARD_ERR_WRONG_TYPE)
 | 
			
		||||
        return new Err("Wrong Type")
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -146,10 +143,10 @@ export namespace BoardTable {
 | 
			
		||||
      const retName = includes(board.name, board.room)
 | 
			
		||||
      if (retName.isOk()) {
 | 
			
		||||
        if (retName.value) {
 | 
			
		||||
          return new Err(BOARD_ERR_NAME_CONFLICT)
 | 
			
		||||
          return new Err("Name Conflict")
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        return new Err("Wrong type")
 | 
			
		||||
        return new Err("Wrong Type")
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -225,7 +222,7 @@ export namespace BoardTable {
 | 
			
		||||
        retBoard = _.cloneDeep(retBoard.value.value)
 | 
			
		||||
        condition = `id=${arg1}`
 | 
			
		||||
      } else {
 | 
			
		||||
        return new Err(BOARD_ERR_WRONG_TYPE)
 | 
			
		||||
        return new Err("Wrong Type")
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    } else if (_.isString(arg1) && _.isString(arg2)) {
 | 
			
		||||
@@ -234,11 +231,11 @@ export namespace BoardTable {
 | 
			
		||||
        retBoard = _.cloneDeep(retBoard.value.value)
 | 
			
		||||
        condition = `name=${arg1}`
 | 
			
		||||
      } else {
 | 
			
		||||
        return new Err(BOARD_ERR_NO_BOARDS)
 | 
			
		||||
        return new Err("No Such Board(s)")
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
      return new Err(BOARD_ERR_WRONG_TYPE)
 | 
			
		||||
      return new Err("Wrong Type")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const query = db.query(`DELETE FROM Boards WHERE ${condition}`)
 | 
			
		||||
@@ -263,7 +260,7 @@ export namespace BoardTable {
 | 
			
		||||
  export function removeByCondition(condition: string): Result<Array<Board>, BoardErrorType> {
 | 
			
		||||
    const rsArr = findByCondition(condition)
 | 
			
		||||
    if (rsArr.isNone()) {
 | 
			
		||||
      return new Err(BOARD_ERR_NO_BOARDS)
 | 
			
		||||
      return new Err("No Such Board(s)")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const query = db.query(`DELETE FROM Boards WHERE ${condition}`)
 | 
			
		||||
@@ -276,7 +273,7 @@ export namespace BoardTable {
 | 
			
		||||
    : Result<Array<Board>, BoardErrorType> {
 | 
			
		||||
 | 
			
		||||
    if (!isBoardColumn(columnName)) {
 | 
			
		||||
      return new Err(BOARD_ERR_WRONG_TYPE)
 | 
			
		||||
      return new Err("Wrong Type")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let condition: string
 | 
			
		||||
@@ -285,17 +282,17 @@ export namespace BoardTable {
 | 
			
		||||
      if (retCond.isSome()) {
 | 
			
		||||
        condition = retCond.value
 | 
			
		||||
      } else {
 | 
			
		||||
        return new Err(BOARD_ERR_WRONG_TYPE)
 | 
			
		||||
        return new Err("Wrong Type")
 | 
			
		||||
      }
 | 
			
		||||
    } else if (fun.isStringArray(val)) {
 | 
			
		||||
    } else if (type.isStringArray(val)) {
 | 
			
		||||
      const retCond = fun.sqlConditionFromArray(columnName, val, "OR")
 | 
			
		||||
      if (retCond.isSome()) {
 | 
			
		||||
        condition = retCond.value
 | 
			
		||||
      } else {
 | 
			
		||||
        return new Err(BOARD_ERR_WRONG_TYPE)
 | 
			
		||||
        return new Err("Wrong Type")
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      return new Err(BOARD_ERR_WRONG_TYPE)
 | 
			
		||||
      return new Err("Wrong Type")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return removeByCondition(condition)
 | 
			
		||||
@@ -339,7 +336,7 @@ export namespace BoardTable {
 | 
			
		||||
      condition = `name='${arg1}' AND room='${arg2}'`
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
      return new Err(BOARD_ERR_WRONG_TYPE)
 | 
			
		||||
      return new Err("Wrong Type")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const query = db.query(`SELECT * FROM Boards WHERE ${condition}`)
 | 
			
		||||
@@ -360,17 +357,17 @@ export namespace BoardTable {
 | 
			
		||||
      if (retCond.isSome()) {
 | 
			
		||||
        condition = retCond.value
 | 
			
		||||
      } else {
 | 
			
		||||
        return new Err(BOARD_ERR_WRONG_TYPE)
 | 
			
		||||
        return new Err("Wrong Type")
 | 
			
		||||
      }
 | 
			
		||||
    } else if (fun.isStringArray(name)) {
 | 
			
		||||
    } else if (type.isStringArray(name)) {
 | 
			
		||||
      const retCond = fun.sqlConditionFromArray("name", name, "OR")
 | 
			
		||||
      if (retCond.isSome()) {
 | 
			
		||||
        condition = retCond.value
 | 
			
		||||
      } else {
 | 
			
		||||
        return new Err(BOARD_ERR_WRONG_TYPE)
 | 
			
		||||
        return new Err("Wrong Type")
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      return new Err(BOARD_ERR_WRONG_TYPE)
 | 
			
		||||
      return new Err("Wrong Type")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return new Ok(findByCondition(condition))
 | 
			
		||||
@@ -390,7 +387,7 @@ export namespace BoardTable {
 | 
			
		||||
    : Result<Option<Array<Board>>, BoardErrorType> {
 | 
			
		||||
 | 
			
		||||
    if (!isBoardColumn(columnName)) {
 | 
			
		||||
      return new Err(BOARD_ERR_WRONG_TYPE)
 | 
			
		||||
      return new Err("Wrong Type")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let condition: string
 | 
			
		||||
@@ -399,17 +396,17 @@ export namespace BoardTable {
 | 
			
		||||
      if (retCond.isSome()) {
 | 
			
		||||
        condition = retCond.value
 | 
			
		||||
      } else {
 | 
			
		||||
        return new Err(BOARD_ERR_WRONG_TYPE)
 | 
			
		||||
        return new Err("Wrong Type")
 | 
			
		||||
      }
 | 
			
		||||
    } else if (fun.isStringArray(val)) {
 | 
			
		||||
    } else if (type.isStringArray(val)) {
 | 
			
		||||
      const retCond = fun.sqlConditionFromArray(columnName, val, "OR")
 | 
			
		||||
      if (retCond.isSome()) {
 | 
			
		||||
        condition = retCond.value
 | 
			
		||||
      } else {
 | 
			
		||||
        return new Err(BOARD_ERR_WRONG_TYPE)
 | 
			
		||||
        return new Err("Wrong Type")
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      return new Err(BOARD_ERR_WRONG_TYPE)
 | 
			
		||||
      return new Err("Wrong Type")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return new Ok(findByCondition(condition))
 | 
			
		||||
@@ -427,13 +424,13 @@ export namespace BoardTable {
 | 
			
		||||
        condition = `name='${arg1}'`
 | 
			
		||||
 | 
			
		||||
      } else {
 | 
			
		||||
        return new Err(BOARD_ERR_WRONG_TYPE)
 | 
			
		||||
        return new Err("Wrong Type")
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      if (_.isString(arg1) && _.isString(arg2)) {
 | 
			
		||||
        condition = `name='${arg1} AND room=${arg2}'`
 | 
			
		||||
      } else {
 | 
			
		||||
        return new Err(BOARD_ERR_WRONG_TYPE)
 | 
			
		||||
        return new Err("Wrong Type")
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user