0.1.2 • Published 1 year ago

@flagtail/type-flow v0.1.2

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

type-flow

A validation library that makes your code safe and readable

# Installation

npm i @flagtail/type-flow

# Usage

- Client-side(ES)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">   
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Type Flow Example</title>
</head>
<body>
    <script src="./node_modules/@flagtail/type-flow/dist/type-flow.js"></script>
    <script>
        const { Typing, safeCall } = TypeFlow;
        const validateResult = safeCall(()=>{
            Typing.check([
                Typing.the('hello').isNotNull().isPrimitiveOf(String),
                Typing.the({role:"admin"}).isArray().isNotNull().isSatisfy(v => v.role === "admin"),
                Typing.the(100).isPrimitiveOf(Number).isSatisfy(v => v % 2 === 0),
            ])

            return 'validation is success';
        },
        (err)=> {
            console.log(JSON.stringify(
                JSON.parse(err.message),
                null,
                2
            ))
        })
    </script>
</body>
</html>

- Node.js(CommonJS)

const { Typing, safeCall } = require('@flagtail/type-flow');

safeCall(()=>{
    Typing.check([
        Typing.the('hello').isNotNull().isPrimitiveOf(String),
        Typing.the({role:"user"}).isArray().isNotNull().isSatisfy(v => v.role === "admin"),
        Typing.the(100).isPrimitiveOf(Number).isSatisfy(v => v % 2 === 0),
    ])
},
(err)=> {
    console.log(err);
})

# Why type-flow

- Before use type-flow

class Member {

    constructor(name, age) {
       
        if(typeof name === "string") {
            if(name.length > 30) {
                throw new RangeError(`the name length (${name.length}) is too long (over 30)`)
            }
            this.name = name;
        } else {
            throw new TypeError(`the name type must be string type`);
        }

        if(typeof age === "number") {
            if(age < 0) {
                throw new RangeError(`the age ${age} cannot be minus number`);
            }
            this.age = age;
        } else {
            throw new TypeError(`the age type must be number type`);
        }

    }

    isAdult() {
        return this.age > 18;
    }
}

function main() {
    try {
        const alice = new Member("Alice", 30)
        console.log(alice.isAdult())
    } catch (err) {
        console.log(err);
    }
}

main()

- With type-flow

const {
    Typing,
    safeCall
} = require('@flagtail/type-flow');

class Member {

    constructor(name, age) {
        
        Typing.check([
            Typing.the(name).isPrimitiveOf(String).isSatisfy(v => v.length <= 30),
            Typing.the(age).isPrimitiveOf(Number).isSatisfy(v => v >= 0)
        ]) 

        this.name = name;
        this.age = age;
    }

    isAdult() {
        return this.age > 18;
    }
}

function main() {

    safeCall(()=>{
        const alice = new Member("Alice", 30)
        console.log(alice.isAdult())
    },
    (err=>{
        console.log(err);
    })) 
}

main()

# API Reference

- isNotNull(value)

  • value: any

* example

Typing.isNotNull(false)  // true
Typing.isNotNull(10)     // true
Typing.isNotNull('word') // true

Typing.isNotNull(null)      // false
Typing.isNotNull(undefined) // false
Typing.isNotNull('')        // false

- isNull(value)

  • value: any

* example

Typing.isNotNull(false)  // false
Typing.isNotNull(10)     // false
Typing.isNotNull('word') // false

Typing.isNotNull(null)      // true
Typing.isNotNull(undefined) // true
Typing.isNotNull('')        // true

- ifNullThrow(value)

  • value: any

* example

Typing.ifNullThrow(null)      // ERROR: the value is null or undefined or empty
Typing.ifNullThrow(undefined) // ERROR: the value is null or undefined or empty
Typing.ifNullThrow('')        // ERROR: the value is null or undefined or empty

- isWrapper(value)

  • value: any

* example

Typing.isWrapper(new String('text')) // true
Typing.isWrapper(new Number(10))     // true
Typing.isWrapper(new Boolean(false)) // true

Typing.isWrapper('text') // false
Typing.isWrapper(10)     // false
Typing.isWrapper(false)  // false

- isPrimitive(value)

  • value: any

* example

Typing.isPrimitive(new String('text'))) // false
Typing.isPrimitive(new Number(10)))     // false
Typing.isPrimitive(new Boolean(false))) // false
Typing.isPrimitive(function() {}))      // false
Typing.isPrimitive(class {}))           // false
Typing.isPrimitive({}))                 // false

Typin.isPrimitive(100))                 // true
Typin.isPrimitive('text'))              // true
Typin.isPrimitive(false))               // true
Typin.isPrimitive(BiInt(123456789)))    // true
Typin.isPrimitive(Symbol('sym')))       // true

- isFunction(value)

  • value: any

* example

Typing.isFunction(function myFunc() {}))  // true
Typing.isFunction(function () {}))        // true
Typing.isFunction(()=>{}))                // true

Typing.isFunction(class {}))          // false
Typing.isFunction({}))                // false
Typing.isFunction('function() {}'))   // false

- isClass(value)

  • value: any

* example

Typing.isClass(class myClass {})) // true
Typing.isClass(class {}))         // true
  
Typing.isClass(function myFunc() {})) // false
Typing.isClass(function () {}))       // false
Typing.isClass(()=>{}))               // false
Typing.isClass({}))                   // false
Typing.isClass('class {}'))           // false

- isObject(value)

  • value: any

* example

Typing.isObject([]) // true

class Clazz {}

Typing.isObject(class MyClass {}))  // false
Typing.isObject(class {}))          // false
Typing.isObject(new Clazz()))       // true

Typing.isObject(function myFunc() {})) // false
Typing.isObject(function () {}))       // false
Typing.isObject(()=>{}))               // false

Typing.isObject(new String('test'))) // true
Typing.isObject('test'))             // false

- isArray(value)

  • value: any

* example

Typing.isArray([1, 2, 3, 4])    // true
Typing.isArray({a: 10, b: 20})  // false

- is(value).instanceOf(type)

  • value: any
  • type : data type || Array[data type]

* example

class Clazz {}

Typing.is(new Clazz()).instanceOf(Clazz))   // true
Typing.is(new Clazz()).instanceOf(Object))  // true
Typing.is([1, 2, 3, 4]).instanceOf(Array))  // true
Typing.is([1, 2, 3, 4]).instanceOf(Object)) // true

Typing.is('test').instanceOf(String)) // false
Typing.is(Clazz).instanceOf(Clazz))   // false

class Member{}

Typing.is(new Member()).instanceOf([Member,Array]) // true
Typing.is(new Member()).instanceOf([Error,Array])  // false

- is(value).primitiveOf(type)

  • value: any
  • type : data type || Array[data type]

* example

Typing.is(10).primitiveOf(Number))        // true
Typing.is('text').primitiveOf(String))    // true 
Typing.is(false).primitiveOf('boolean'))  // true

Typing.is([1, 2, 3]).primitiveOf('array')) // false
Typing.is(10).primitiveOf('string'))       // false
Typing.is('text').primitiveOf(Number))     // false

const age = "30";
const name = "Alice"

Typing.is(age).primitiveOf(["number", String]) // true
Typing.is(name).primitiveOf([Number,Boolean])  // false

- is(value).satisfy(action)

  • value : any
  • action: function

* example

class Member {
    constructor(name, age) {
    this.name = name;
    this.age = age;
    }

    isAdult() {
    return this.age >= 18
    }
}

Typing.is(100).satisfy(v => v % 2 === 0)) // true

Typing.is(new Member('rhie', 17)).satisfy(v => v.isAdult())) // false

- the(value) ~~~ isValid()

  • value: any

chainning method(return TypingChain)

* example

class Member {
    constructor(name, age) {
    this.name = name;
    this.age = age;
    }

    isAdult() {
    return this.age >= 18
    }
}

Typing.the(111)
      .isPrimitiveOf(Number)
      .isNotNull()
      .isSatisfy(v => v >= 100)
      .isValid() // true

Typing.the(new Member('rhie-coder', 17))
      .isInstanceOf(Member)
      .isSatisfy(v => v.isAdult())
      .isValid() // false

- check(typeCHeck)

  • typeCheck: Array[TypingChain]

It will throw errors if TypingChian is not valid.

* example

class Member {
    constructor(name, age) {
    this.name = name;
    this.age = age;
    }

    isAdult() {
    return this.age >= 18
    }
}

Typing.check([
    Typing.the('hello').isNotNull().isPrimitiveOf(String),
    Typing.the({role:"user"}).isArray().isNotNull().isSatisfy(v => v.role === "admin"),
    Typing.the(100).isPrimitiveOf(Number).isSatisfy(v => v % 2 === 0),
    Typing.the(new Member('rhie', 17)).isInstanceOf(Member).isSatisfy(v => v.isAdult())
])
/* Throw Errors
[
  [
    {
      "target": {
        "role": "user"
      }
    },
    {
      "isArray": false
    },
    {
      "isNotNull": true
    },
    {
      "isSatisfy": false
    }
  ],
  [
    {
      "target": {
        "name": "rhie",
        "age": 17
      }
    },
    {
      "isInstanceOf": true
    },
    {
      "isSatisfy": false
    }
  ]
]
*/

- safeCall(callback, errorHandler)

  • callback : function()
  • errorHandler: function(err)

* example

try {
    Typing.check([
        Typing.the('hello').isNotNull().isPrimitiveOf(String),
        Typing.the({role:"user"}).isArray().isNotNull().isSatisfy(v => v.role === "admin"),
        Typing.the(100).isPrimitiveOf(Number).isSatisfy(v => v % 2 === 0),
        Typing.the(new Member('rhie', 17)).isInstanceOf(Member).isSatisfy(v => v.isAdult())
    ])
} catch(err) {
    console.log(JSON.stringify(
        JSON.parse(err.message),
        null,
        2
    ))
}

is same with below:

safeCall(()=>{
    Typing.check([
        Typing.the('hello').isNotNull().isPrimitiveOf(String),
        Typing.the({role:"user"}).isArray().isNotNull().isSatisfy(v => v.role === "admin"),
        Typing.the(100).isPrimitiveOf(Number).isSatisfy(v => v % 2 === 0),
        Typing.the(new Member('rhie', 17)).isInstanceOf(Member).isSatisfy(v => v.isAdult())
    ])
},
(err)=> {
    console.log(JSON.stringify(
        JSON.parse(err.message),
        null,
        2
    ))
})

# License

MIT

0.1.2

1 year ago

0.1.1

1 year ago

0.1.0

1 year ago

0.0.2

1 year ago

0.0.1

1 year ago