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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@aeunius/peru-rules

v1.0.0

Published

Validación de documentos y datos peruanos en JavaScript: RUC, DNI, carné de extranjería, pasaporte, celular, placa vehicular y CCI, con reglas para formularios de Vue.

Readme

Peru Rules para JavaScript

Validación de documentos y datos peruanos en el navegador y en Node: RUC, DNI, carné de extranjería, pasaporte, celular, placa vehicular y CCI. Valida el formato y los dígitos de control sin conectarse a ningún servicio externo.

Es el gemelo en TypeScript de aeunius/laravel-peru-rules: usa los mismos algoritmos y se prueba con los mismos casos, así que el formulario da exactamente el mismo resultado que el backend en Laravel. Incluye reglas listas para formularios de Vue (Vuetify, Quasar y VeeValidate).

ci Versión en npm Licencia

Qué valida

| Función | Qué comprueba | |---|---| | ruc.esValido(ruc, prefijos?) | 11 dígitos, prefijo 10, 15, 16, 17 o 20, y dígito verificador | | dni.esValido(dni) | 8 dígitos | | alfanumerico.esValido(numero, max) | Hasta max letras o números: carné de extranjería y pasaporte (12), tipos 0 y A (15) | | validarDocumento(tipo, numero) | El número según el tipo de documento del catálogo 06 de la SUNAT | | celular.esValido(celular) | 9 dígitos que empiezan con 9; acepta +51 y separadores | | placa.esValido(placa) | Autos: ABC-123 o A1B-234, con o sin guion. Especiales con prefijo E: E GA-123, eGA-123. Motos: 2171-AY, 5040-6C, C5-4481 | | cci.esValido(cci) | 20 dígitos y los dos dígitos de control; acepta espacios y guiones |

Se comprueba que el número sea válido, no que exista: un RUC puede tener un dígito verificador correcto y aun así no estar inscrito o no estar activo en la SUNAT.

Instalación

npm install @aeunius/peru-rules

Funciona en ESM y en CommonJS, trae sus tipos de TypeScript y no tiene dependencias. Vue solo hace falta para @aeunius/peru-rules/vue.

Uso

import { cci, celular, dni, placa, ruc } from '@aeunius/peru-rules'

ruc.esValido('20131312955')              // true
ruc.esValido('20131312955', [ruc.NATURAL]) // false: solo acepta el prefijo 10
ruc.digitoVerificador('2013131295')      // 5
dni.esValido('00123456')                 // true
celular.esValido('+51 987 654 321')      // true
placa.esValido('C5-4481')                // true
cci.esValido('002-191-000123456789-57')  // true

Los valores se validan tal como llegan: 20-13131295-5 o un RUC con espacios no pasan. Las funciones reciben texto; con cualquier otro tipo devuelven false.

RUC

import { dniDeRuc, formatearRuc, tipoContribuyente } from '@aeunius/peru-rules'

formatearRuc('20131312955')      // "20-13131295-5"
tipoContribuyente('20131312955') // "juridica"; también "natural" o "especial"
dniDeRuc('10123456781')          // "12345678"; null si no es de persona natural
formatearRuc('20131312956')      // null: no es un RUC válido

ruc.formatear(), ruc.tipoContribuyente() y ruc.dni() son las mismas funciones.

Documento según su tipo

Los tipos son los del catálogo 06 de la SUNAT, los mismos de la facturación electrónica:

import { TipoDocumento, validarDocumento } from '@aeunius/peru-rules'

validarDocumento(TipoDocumento.Ruc, '20131312955') // true
validarDocumento('1', '12345678')                  // true: DNI
validarDocumento('9', '12345678')                  // false: el tipo no existe

| Código | TipoDocumento | Se valida con | |---|---|---| | 0 | NoDomiciliadoSinRuc | Hasta 15 letras o números | | 1 | Dni | dni.esValido | | 4 | CarneExtranjeria | Hasta 12 letras o números | | 6 | Ruc | ruc.esValido | | 7 | Pasaporte | Hasta 12 letras o números | | A | CedulaDiplomatica | Hasta 15 letras o números |

También están TIPOS_DOCUMENTO (los seis códigos), esTipoDocumento(), descripcionDocumento() y longitudMaxima().

Celular, placa y CCI: normalizar antes de guardar

Celular, placa y CCI aceptan varias formas de escribir el mismo dato. Para guardarlo siempre igual, normalízalo. Si no es válido, se obtiene null:

celular.normalizar('+51 987 654 321')          // "987654321"
placa.normalizar('abc123')                     // "ABC-123"
placa.normalizar('e GA-123')                   // "EGA-123"
placa.normalizar('2171ay')                     // "2171-AY"
cci.normalizar('002-191-000123456789-57')      // "00219100012345678957"
cci.digitosControl('002191', '000123456789')   // "57"
celular.normalizar('014567890')                // null: no es un celular

En las placas de motos del tipo C5-4481 el guion es obligatorio: sin él, C54481 se lee como la placa de auto C54-481.

Vue

usePeruRules() devuelve reglas con la forma (valor) => true | "mensaje", la que usan Vuetify, Quasar y VeeValidate, así que se pasan sin adaptadores:

<script setup lang="ts">
import { usePeruRules } from '@aeunius/peru-rules/vue'

const { reglas } = usePeruRules()
</script>

<template>
  <!-- Vuetify -->
  <v-text-field v-model="ruc" :rules="[reglas.requerido, reglas.ruc]" />

  <!-- Quasar -->
  <q-input v-model="celular" :rules="[reglas.celular]" />
</template>
// VeeValidate
const { value, errorMessage } = useField('cci', [reglas.requerido, reglas.cci])

| Regla | Qué comprueba | |---|---| | requerido | Que haya un valor: falla con '', null, undefined, solo espacios o una lista vacía | | ruc, rucNatural, rucJuridica | RUC válido; las variantes exigen el prefijo 10 o 20 | | dni | 8 dígitos | | carneExtranjeria, pasaporte | Hasta 12 letras o números | | documento(tipo) | El número según el tipo de documento | | celular, placa, cci | Como las funciones de arriba |

Como en Laravel, las reglas no se aplican a un campo vacío ('', null o undefined): para exigirlo, agrega reglas.requerido. Los números (v-model.number) se validan como texto.

documento recibe el tipo como valor, ref o función, y lo lee cada vez que valida, así que sigue al campo del tipo:

const form = reactive({ tipoDoc: '1', numDoc: '' })
const reglaNumero = reglas.documento(() => form.tipoDoc)

Con DNI, RUC, carné de extranjería y pasaporte, el mensaje de error es el de la regla de ese tipo.

Mensajes

Los mensajes vienen en español (MENSAJES) y se reemplazan uno por uno:

const { reglas } = usePeruRules({
  mensajes: { ruc: 'Revisa el RUC.' },
})

mensajes también puede ser un ref o una función, para que siga al idioma de la aplicación, por ejemplo con vue-i18n:

const { t } = useI18n()
const { reglas } = usePeruRules({
  mensajes: () => ({ ruc: t('validacion.ruc'), dni: t('validacion.dni') }),
})

En el mensaje de documento (tipos 0 y A) se reemplazan :tipo y :max.

Cómo se valida

El RUC usa módulo 11 con los pesos 5 4 3 2 7 6 5 4 3 2; el CCI, pesos 1 y 2 alternados con suma de cifras y complemento a la decena. El paso a paso, con ejemplos, está en el README de laravel-peru-rules.

Los mismos resultados que en Laravel

Los casos de prueba están en tests/fixtures de laravel-peru-rules, y este paquete los descarga desde una etiqueta fija de ese repositorio a test/fixtures. Los dos paquetes se prueban con esos mismos archivos, y el CI comprueba que no se editen a mano.

Donde JavaScript y PHP difieren, el paquete sigue a PHP: trim() y toUpperCase() de JavaScript también tratan caracteres Unicode, y \s reconoce el espacio no separable. Aquí, como en PHP, solo cuentan los espacios y las letras ASCII.

Desarrollo

Todo corre en Docker con la imagen oficial node:24, así que no hace falta tener Node instalado:

make install    # dependencias
make test       # Vitest
make lint       # Biome y tipos, sin cambiar archivos
make build      # compila a dist/
make check      # revisa el paquete que se publicaría
make fixtures   # vuelve a descargar los casos compartidos
make help       # todos los comandos

Para cambiar una regla: se cambian primero los casos en laravel-peru-rules, se publica un tag, y aquí se cambia ETIQUETA en scripts/fixtures.mjs, se corre make fixtures y se ajusta el código hasta que pasen los tests.

Cada release de GitHub publica la versión en npm, con provenance.

El CI prueba con Node 22 y 24.

Los cambios de cada versión están en el CHANGELOG.

Licencia

MIT. Ver LICENSE.md.