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

vin-iso3779-validator

v1.1.0

Published

Tiny, typesafe ISO 3779 VIN validator with check digit

Downloads

2,539

Readme

vin-iso3779-validator

Tiny, typesafe VIN validator for ISO 3779 (length, charset, optional check digit enforcement).
No dependencies. ESM. Strict TypeScript.

Features

  • ISO 3779 structural validation: Length (17 chars) and charset
  • Optional strict check digit validation: Enable North American enforcement when needed
  • Auto-normalization: Removes spaces/hyphens, converts to uppercase
  • TypeScript branded types: Type-safe VIN handling with compile-time guarantees
  • Multiple validation methods: Flexible API for different use cases
  • Zero dependencies: Lightweight and secure
  • ESM-first: Modern JavaScript module support

VIN Format Rules

  • Length: Exactly 17 characters
  • Characters: Uppercase A–Z (excluding I, O, Q) and digits 0–9
  • Check digit: Can be computed for any VIN, but is only mandatory in some markets such as North America
  • Standard: ISO 3779 (applies to vehicles made since 1981)

Install

npm i vin-iso3779-validator
# or
pnpm add vin-iso3779-validator
# or
yarn add vin-iso3779-validator
# or
bun add vin-iso3779-validator

API

validateVIN(input: string, options?: ValidateVINOptions): ValidationResult

Comprehensive validation with detailed error information.

import { validateVIN } from "vin-iso3779-validator";

const result = validateVIN("1HGCM82633A004352");
console.log(result);
// {
//   isValid: true,
//   vin: "1HGCM82633A004352",
//   errors: [],
//   checkDigit: "3",
//   expectedCheckDigit: "3",
//   checkDigitValid: true
// }

// North American strict mode example
const invalid = validateVIN("1HGCM82633A004351", { checkDigit: "required" });
console.log(invalid.errors); // ["INVALID_CHECK_DIGIT"]

// European/general ISO 3779 example
const euVin = validateVIN("VR3F45GFRKY097237");
console.log(euVin.isValid); // true
console.log(euVin.checkDigitValid); // false

isValidVIN(vin: string, options?: ValidateVINOptions): vin is VIN

Type guard for branded VIN type.

import { isValidVIN } from "vin-iso3779-validator";

if (isValidVIN("JHMCM56557C404453")) {
  // TypeScript knows this is a valid VIN (branded type)
  console.log("Valid VIN");
}

isValidVIN("VR3F45GFRKY097237"); // true
isValidVIN("VR3F45GFRKY097237", { checkDigit: "required" }); // false

assertVIN(input: string, options?: ValidateVINOptions): VIN

Throws error if invalid, returns branded VIN type if valid.

import { assertVIN } from "vin-iso3779-validator";

try {
  const vin = assertVIN("1M8GDM9AXKP042788"); // returns branded VIN type
  console.log("Valid VIN:", vin);
} catch (error) {
  console.error("Invalid VIN:", error.message);
}

assertVIN("VR3F45GFRKY097237"); // ok
assertVIN("VR3F45GFRKY097237", { checkDigit: "required" }); // throws

computeCheckDigit(vin: string): string

Calculate the expected check digit for a VIN.

import { computeCheckDigit } from "vin-iso3779-validator";

const checkDigit = computeCheckDigit("1HGCM82633A004352"); // "3"
const checkDigitX = computeCheckDigit("1M8GDM9AXKP042788"); // "X"

normalizeVIN(input: string): string

Normalize VIN input (remove spaces/hyphens, uppercase).

import { normalizeVIN } from "vin-iso3779-validator";

const normalized = normalizeVIN(" 1hg-cm82633a004352 "); // "1HGCM82633A004352"

Error Codes

The validateVIN function returns specific error codes:

  • INVALID_LENGTH: VIN is not exactly 17 characters
  • INVALID_CHARACTERS: Contains forbidden characters (I, O, Q, or non-alphanumeric)
  • INVALID_CHECK_DIGIT: Check digit doesn't match calculated value when strict mode is enabled

Examples

import { validateVIN, isValidVIN, assertVIN, computeCheckDigit, normalizeVIN } from "vin-iso3779-validator";

// Basic validation
const result = validateVIN("1HGCM82633A004352");
console.log(result.isValid); // true

// Handle messy input
const messy = validateVIN(" 1hg-cm82633a004352 ");
console.log(messy.isValid); // true (auto-normalized)

// European/general ISO 3779 validation
const euVin = validateVIN("VR3F45GFRKY097237");
console.log(euVin.isValid); // true

// North American strict validation
const naVin = validateVIN("VR3F45GFRKY097237", { checkDigit: "required" });
console.log(naVin.isValid); // false

// Type-safe validation
if (isValidVIN("JHMCM56557C404453")) {
  // vin is now typed as VIN (branded string)
}

// Exception-based validation
try {
  const vin = assertVIN("1M8GDM9AXKP042788");
  // vin is guaranteed to be valid
} catch (error) {
  // Handle invalid VIN
}

// Check digit calculation
const expected = computeCheckDigit("1HGCM82633A004352"); // "3"

// Manual normalization
const clean = normalizeVIN("JHM CM8-2633-A004352"); // "JHMCM82633A004352"

Testing

Run the test suite:

npm test

Run tests in watch mode:

npm run test:watch

The test suite covers:

  • ✅ Valid VIN validation with known test cases
  • ✅ Input normalization (spaces, hyphens, case conversion)
  • ✅ Invalid length detection
  • ✅ Invalid character detection (I, O, Q, and other non-allowed characters)
  • ✅ Optional strict check digit validation
  • ✅ European/general ISO 3779 VIN acceptance without required check digit
  • ✅ Error handling and branded type assertions
  • ✅ Edge cases and boundary conditions

Requirements

  • Node.js >= 18
  • TypeScript >= 5.0 (for TypeScript projects)

License

MIT

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass: npm test
  5. Submit a pull request

Related