Skip to content

varletjs/ruler-factory

Repository files navigation

ruler-factory

A flexible, chainable validation rule factory for TypeScript/JavaScript.

Features

  • Chainable API for building complex validation rules
  • Supports string, number, array, boolean, object, symbol, bigint, null, undefined
  • Customizable error messages
  • Easy to extend and integrate
  • TypeScript support

Installation

pnpm add ruler-factory
# or
npm install ruler-factory
# or
yarn add ruler-factory

Integration with UI frameworks

Varlet UI

<script setup lang="ts">
import { ref } from 'vue'
import { rulerFactory } from 'ruler-factory'

const ruler = rulerFactory((validator) => {
  return (value) => {
    const e = validator(value)
    return e ? e.message : true
  }
})

const model = ref({
  name: '',
  email: '',
})
</script>

<template>
  <var-form>
    <var-input
      v-model="model.name"
      placeholder="Name"
      :rules="ruler().required('Required').min(2, 'Wrong length').done()"
    />
    <var-input v-model="model.age" placeholder="Email" :rules="ruler().email('Must be email format').done()" />
  </var-form>
</template>

Vant

<script setup lang="ts">
import { ref } from 'vue'
import { rulerFactory } from 'ruler-factory'
import type { FieldRule } from 'vant'

const ruler = rulerFactory<FieldRule>((validator, params) => ({
  validator(value) {
    const e = validator(value)

    return e ? e.message : true
  },
  trigger: ['onChange', 'onBlur', 'onSubmit'],
  ...params,
}))

const model = ref({
  name: '',
  email: '',
})
</script>

<template>
  <van-form>
    <van-cell-group inset>
      <van-field v-model="model.name" label="Name" placeholder="Name" :rules="ruler().required('Required').done()" />
      <van-field
        v-model="model.email"
        label="Email"
        placeholder="Email"
        :rules="ruler().email('Must be email format').done()"
      />
    </van-cell-group>
  </van-form>
</template>

Naive UI

<script setup lang="ts">
import { ref } from 'vue'
import type { FormItemRule } from 'naive-ui'
import { rulerFactory } from 'ruler-factory'

const ruler = rulerFactory<FormItemRule>((validator, params = {}) => ({
  trigger: ['blur', 'change', 'input'],
  validator: (_, value) => validator(value),
  ...params,
}))

const model = ref({
  name: '',
  age: 20,
})
</script>

<template>
  <n-form :model>
    <n-form-item path="name" label="Name" :rule="ruler().required('Required').min(2, 'Wrong length').done()">
      <n-input v-model:value="model.name" />
    </n-form-item>
    <n-form-item
      path="age"
      label="Age"
      :rule="ruler().number().required('Required').negative('Must be negative').done()"
    >
      <n-input-number v-model:value="model.age" />
    </n-form-item>
  </n-form>
</template>

Element Plus

<script setup lang="ts">
import { ref } from 'vue'
import type { FormItemRule } from 'element-plus'
import { rulerFactory } from 'ruler-factory'

const ruler = rulerFactory<FormItemRule>((validator, params) => ({
  validator(_, value, callback) {
    const e = validator(value)

    e ? callback(e) : callback()
  },
  trigger: ['blur', 'change', 'input'],
  ...params,
}))

const model = ref({
  name: '',
  email: '',
})
</script>

<template>
  <el-form :model>
    <el-form-item prop="name" label="Name" :rules="ruler().required('Required').done()">
      <el-input v-model="model.name" />
    </el-form-item>
    <el-form-item prop="email" label="Email" :rules="ruler().email('Must be email format').done()">
      <el-input v-model="model.email" />
    </el-form-item>
  </el-form>
</template>

Extend API

Take Naive UI as an example

import { FormItemRule } from 'naive-ui'
import { RulerContext, rulerFactory, RulerFactoryMessage } from 'ruler-factory'

interface RulerExtendedContext {
  ip(message: RulerFactoryMessage, params?: FormItemRule): RulerContext<FormItemRule, FormItemRule, this>
}

customRuler().ip('ip format error').done()

const ruler = rulerFactory<FormItemRule, FormItemRule, RulerExtendedContext>(
  (validator, params = {}) => ({
    trigger: ['blur', 'change', 'input'],
    validator: (_, value) => validator(value),
    ...params,
  }),
  (ctx) => {
    function ip(message: RulerFactoryMessage, params?: FormItemRule) {
      ctx.addRule((value) => {
        // Implement isString and isIP by yourself
        if (!isString(value) || !isIP(value)) {
          return new Error(ctx.getMessage(message))
        }
      }, params)

      return ctx
    }

    return { ip }
  },
)

API

Types Validation

  • .string(message?, params?)
  • .number(message?, params?)
  • .array(message?, params?)
  • .boolean(message?, params?)
  • .object(message?, params?)
  • .symbol(message?, params?)
  • .bigint(message?, params?)
  • .null(message?, params?)
  • .undefined(message?, params?)
  • .true(message?, params?)
  • .false(message?, params?)

Non Empty Validation

  • .required(message)

String Validation

  • .min(value, message, params?)
  • .max(value, message, params?)
  • .length(value, message, params?)
  • .regex(regexp, message, params?)
  • .startsWith(value, message, params?)
  • .endsWith(value, message, params?)
  • .includes(value, message, params?)
  • .uppercase(message, params?)
  • .lowercase(message, params?)
  • .email(message, params?)

Number Validation

  • .number().min(value, message, params?)
  • .number().max(value, message, params?)
  • .number().gt(value, message, params?)
  • .number().gte(value, message, params?) alias .min
  • .number().lt(value, message, params?)
  • .number().lte(value, message, params?) alias .max
  • .number().positive(value, message, params?)
  • .number().negative(value, message, params?)

Bigint Validation

  • .bigint().min(value, message, params?)
  • .bigint().max(value, message, params?)
  • .bigint().gt(value, message, params?)
  • .bigint().gte(value, message, params?) alias .min
  • .bigint().lt(value, message, params?)
  • .bigint().lte(value, message, params?) alias .max
  • .bigint().positive(value, message, params?)
  • .bigint().negative(value, message, params?)

Array Validation

  • .array().min(value, message, params?)
  • .array().max(value, message, params?)
  • .array().length(value, message, params?)
  • .array().includes(value, message, params?)

Predicate Validation

  • .is(fn, message, params?)
  • .not(fn, message, params?)

Complete rule building

  • .done()

Custom Rule

  • .addRule(validator)

Value Transformer

  • .trim()
  • .toLowerCase()
  • .toUpperCase()
  • .transform(fn)

License

MIT

Links

Inspired By

zod yup

About

A flexible, chainable validation rule factory for typeScript/javaScript.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published