npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

macoolka-io

v0.3.4

Published

`macoolka-io` is Runtime type system for IO decoding/encoding.

Downloads

67

Readme

macoolka-io

macoolka-io is Runtime type system for IO decoding/encoding.

It extend on io-ts.

It suport i18n.

It provide some common type

Table of contents

Inspired by

Installation

To install the stable version:

npm install macoolka-io

Consuming

Format a i18n message (english)

import * as t from 'macoolka-io'
import * as E from 'fp-ts/lib/Either'
import { pipe } from 'fp-ts/lib/pipeable'
const R = t.intersection([
    t.type({
        name: t.intersection([t.stringMaxLength(8), t.stringMinLength(2)]),
        int: t.int,
        match: t.stringMatch(/^A/),
        maxLength: t.stringMaxLength(1),
        minLenght: t.stringMinLength(1),
        minValue: t.numberMinValue(1),
        maxValue: t.numberMaxValue(1),
        url: t.url,
        uuid: t.uuid,
        email: t.email,
        ipv4: t.ipv4,
        ipv6: t.ipv6,
        number: t.number,
        date: t.dateFromISOString,
        literal: t.literal('1'),
        keyof: t.keyof({ 'a': '', "b": '' }),
        union: t.union([t.literal('a'), t.literal('b')]),
        string: t.string,
        boolean: t.boolean,
        array: t.array(t.string),
        nonEmptyArray:t.nonEmptyArray(t.string),
        nonEmptyString:t.nonEmptyString,
    }, 'required'),
    t.partial({
        city: t.union([t.literal('beijing'), t.literal('london')])
    })
], 'User'
)
const result=
`Invalid value undefined supplied to : User/0: required/name: (stringMaxLength=8 & stringMinLength=2)/0: string max length=8
Invalid value undefined supplied to : User/0: required/name: (stringMaxLength=8 & stringMinLength=2)/1: string min length=2
Invalid value undefined supplied to : User/0: required/int: integer
Invalid value undefined supplied to : User/0: required/match: string match
Invalid value undefined supplied to : User/0: required/maxLength: string max length=1
Invalid value undefined supplied to : User/0: required/minLenght: string min length=1
Invalid value undefined supplied to : User/0: required/minValue: number min value=1
Invalid value undefined supplied to : User/0: required/maxValue: number max value=1
Invalid value undefined supplied to : User/0: required/url: Url
Invalid value undefined supplied to : User/0: required/uuid: UUID
Invalid value undefined supplied to : User/0: required/email: EMail
Invalid value undefined supplied to : User/0: required/ipv4: IPV4
Invalid value undefined supplied to : User/0: required/ipv6: IPV6
Invalid value undefined supplied to : User/0: required/number: number
Invalid value undefined supplied to : User/0: required/date: ISO Date
Invalid value undefined supplied to : User/0: required/literal: literal
Invalid value undefined supplied to : User/0: required/keyof: "a" | "b"
Invalid value undefined supplied to : User/0: required/union: ("a" | "b")/0: literal
Invalid value undefined supplied to : User/0: required/union: ("a" | "b")/1: literal
Invalid value undefined supplied to : User/0: required/string: string
Invalid value undefined supplied to : User/0: required/boolean: boolean
Invalid value undefined supplied to : User/0: required/array: Array<string>
Invalid value undefined supplied to : User/0: required/nonEmptyArray: NonEmptyArray<string>
Invalid value undefined supplied to : User/0: required/nonEmptyString: NonEmptyString`
describe('i18n io', () => {
    it('with locale en', () => {
        const value = {}
        pipe(
            R.decode(value),
            E.mapLeft(a => {
                expect(t.show(a)({})).toEqual(result)
            })
        )
    })
})

Format a i18n message (chinese)


import * as t from 'macoolka-io'
import * as E from 'fp-ts/lib/Either'
import { pipe } from 'fp-ts/lib/pipeable'
const R = t.intersection([
    t.type({
        name: t.intersection([t.stringMaxLength(8), t.stringMinLength(2)]),
        int: t.int,
        match: t.stringMatch(/^A/),
        maxLength: t.stringMaxLength(1),
        minLenght: t.stringMinLength(1),
        minValue: t.numberMinValue(1),
        maxValue: t.numberMaxValue(1),
        url: t.url,
        uuid: t.uuid,
        email: t.email,
        ipv4: t.ipv4,
        ipv6: t.ipv6,
        number: t.number,
        date: t.dateFromISOString,
        literal: t.literal('1'),
        keyof: t.keyof({ 'a': '', "b": '' }),
        union: t.union([t.literal('a'), t.literal('b')]),
        string: t.string,
        boolean: t.boolean,
        array: t.array(t.string),
        nonEmptyArray:t.nonEmptyArray(t.string),
        nonEmptyString:t.nonEmptyString,
    },'必填'),
    t.partial({
        city: t.union([t.literal('beijing'), t.literal('london')])
    })
], '用户'
)
const result=
`无效的值undefined : 用户/0: 必填/name: (stringMaxLength=8 & stringMinLength=2)/0: 最大长度=8
无效的值undefined : 用户/0: 必填/name: (stringMaxLength=8 & stringMinLength=2)/1: 最小长度=2
无效的值undefined : 用户/0: 必填/int: 整型
无效的值undefined : 用户/0: 必填/match: 正则表达式
无效的值undefined : 用户/0: 必填/maxLength: 最大长度=1
无效的值undefined : 用户/0: 必填/minLenght: 最小长度=1
无效的值undefined : 用户/0: 必填/minValue: 最小值=1
无效的值undefined : 用户/0: 必填/maxValue: 最大值=1
无效的值undefined : 用户/0: 必填/url: 网址
无效的值undefined : 用户/0: 必填/uuid: UUID
无效的值undefined : 用户/0: 必填/email: 邮箱
无效的值undefined : 用户/0: 必填/ipv4: IPV4
无效的值undefined : 用户/0: 必填/ipv6: IPV6
无效的值undefined : 用户/0: 必填/number: 浮点型
无效的值undefined : 用户/0: 必填/date: ISO日期
无效的值undefined : 用户/0: 必填/literal: 标量
无效的值undefined : 用户/0: 必填/keyof: "a" | "b"
无效的值undefined : 用户/0: 必填/union: ("a" | "b")/0: 标量
无效的值undefined : 用户/0: 必填/union: ("a" | "b")/1: 标量
无效的值undefined : 用户/0: 必填/string: 字符型
无效的值undefined : 用户/0: 必填/boolean: 布尔型
无效的值undefined : 用户/0: 必填/array: 数组<字符型>
无效的值undefined : 用户/0: 必填/nonEmptyArray: 非空数组<字符型>
无效的值undefined : 用户/0: 必填/nonEmptyString: 非空字符串`
describe('i18n io', () => {
    it('with locale zh', () => {
        const value = {}
        pipe(
            R.decode(value),
            E.mapLeft(a => {
                expect(t.show(a)({i18n:{locale:'zh'}})).toEqual(result)
            })
        )
    })
})

customer a i18n type

import * as t from 'macoolka-io'
import * as E from 'fp-ts/lib/Either'
import { pipe } from 'fp-ts/lib/pipeable'
export const defaultOption = {
    defaultLanguage: 'en',
    locale: 'en',
    languages: ['en', 'zh'],
    data: {
        en: {
            'macoolka.customer.error': 'error value:{value}'
        },
        zh: {
            'macoolka.customer.error': '错误的值 :{value}'
        },
    }
}
/**
 * Customer a i18n codec
 */
const customer = new t.Type<string>(
    'customer',
    t.string.is,
    (u, c) => {
        return pipe(
            t.string.validate(u, c),
            E.chain(_ => {
                return u === 'abc' ?
                    t.failMessage<string>([{
                        id: 'macoolka.customer.error',
                        value: {
                            value: u
                        }
                    }], c)
                    : t.success<any>(u)
            })
        )

    },
    t.string.encode,
)

describe('customer i18n io', () => {
    it('ok', () => {
        const value = 'ok'
        pipe(
            customer.decode(value),
            as => expect(E.isRight(as)).toBeTruthy()
        )
    })
    it('error default', () => {
        const value = 'abc'
        pipe(
            customer.decode(value),
            as => {
                expect(E.isLeft(as)).toBeTruthy()
                return as
            },
            E.mapLeft(a => {
                expect(t.show(a)({ i18n: defaultOption })).toEqual(`error value:abc : customer`)
            })
        )
    })
    it('error zh', () => {
        const value = 'abc'
        pipe(
            customer.decode(value),
            as => {
                expect(E.isLeft(as)).toBeTruthy()
                return as
            },
            E.mapLeft(a => {
                expect(t.show(a)({ i18n: { ...defaultOption, locale: 'zh' } })).toEqual(`错误的值 :abc : customer`)
            })
        )
    })
    it('error macoolka-io', () => {
        const value = 1
        pipe(
            customer.decode(value),
            as => {
                expect(E.isLeft(as)).toBeTruthy()
                return as
            },
            E.mapLeft(a => {
                expect(t.show(a)({ i18n: { ...defaultOption, locale: 'zh' } })).toEqual(`无效的值1 : customer`)
            })
        )
    })

})

common type

import * as t from 'macoolka-io';
import { right,isLeft } from 'fp-ts/lib/Either';
describe('io', () => {
    it('withDefault', () => {
        const M = t.withDefault(t.string, '123');
        expect(M.decode(null)).toEqual(right('123'));
        expect(M.decode(null)).toEqual(right('123'));
        expect(M.decode('4')).toEqual(right('4'));

        const MA=t.type({
            name:t.string,
            names:t.array(t.string)
        })
   
        const MB=t.type({
            name:t.withDefault(t.string,'1'),
            names:t.withDefault(t.array(t.string),[])
        })
        expect(MB.decode({})).toEqual(right({name:'1',names:[]}));
        expect(MB.decode({name:'2'})).toEqual(right({name:'2',names:[]}));
        expect(MB.decode({names:['1']})).toEqual(right({name:'1',names:['1']}));
        expect(MB.decode({names:['3'],name:'3'})).toEqual(right({name:'3',names:['3']}));
        expect(isLeft(MA.decode({}))).toEqual(true);
     });
 
    it('dateFromNumber', () => {
        const d = new Date(2000, 1, 1);
        const millis = d.getTime();
        expect(t.dateFromNumber.decode(millis)).toEqual(right(d));
    });
    it('dateFromISOString', () => {
        const d = new Date(2000, 1, 1);
        const s = d.toISOString();
        expect(t.dateFromISOString.decode(s)).toEqual(right(d));
    });
    it('StringMaxLength',()=>{
        expect(t.stringMaxLength(3).decode('123')).toEqual(right('123'))
        expect(isLeft(t.stringMaxLength(3).decode('1234'))).toEqual(true)
    })
    it('stringMinLength',()=>{
        expect(t.stringMinLength(3).decode('123')).toEqual(right('123'))
        expect(isLeft(t.stringMinLength(3).decode('12'))).toEqual(true)
    })
    it('StringMatch',()=>{
        expect(t.stringMatch(/^A/).decode('ABC')).toEqual(right('ABC'))
        expect(isLeft(t.stringMatch(/^A/).decode('12'))).toEqual(true)
    })
    it('email',()=>{
        expect(t.email.decode('[email protected]')).toEqual(right('[email protected]'))
        expect(isLeft(t.email.decode('12'))).toEqual(true)
    }) 
    it('ipv4',()=>{
        expect(t.ipv4.decode('8.8.8.8')).toEqual(right('8.8.8.8'))
        expect(isLeft(t.ipv4.decode('12'))).toEqual(true)
    })  
    it('ipv6',()=>{
        expect(t.ipv6.decode('2409:8a15:244a:a780:b0f5:8e9a:2c2e:5ce2')).toEqual(right('2409:8a15:244a:a780:b0f5:8e9a:2c2e:5ce2'))
        expect(isLeft(t.ipv6.decode('8.8.8.8'))).toEqual(true)
    })  
    it('url',()=>{
        expect(t.url.decode('http://bing.com')).toEqual(right('http://bing.com'))
        expect(isLeft(t.url.decode('8.8.8.8'))).toEqual(true)
    }) 
     it('UUID',()=>{
        expect(t.uuid.decode('00000000-0000-0000-0000-000000000000')).toEqual(right('00000000-0000-0000-0000-000000000000'))
        expect(isLeft(t.uuid.decode('12'))).toEqual(true)
    })
    it('NumberMaxValue',()=>{
        expect(t.numberMaxValue(3).decode(3)).toEqual(right(3))
        expect(isLeft(t.numberMaxValue(3).decode(4))).toEqual(true)
    })
    it('NumberMinValue',()=>{
        expect(t.numberMinValue(3).decode(3)).toEqual(right(3))
        expect(isLeft(t.numberMinValue(3).decode(2))).toEqual(true)
    })
});

Documentation

License

The MIT License (MIT)