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

ivms101

v2.0.0

Published

IVMS101.2023 TypeScript library with legacy 2020 support

Downloads

16,048

Readme

IVMS101 TypeScript Library

A TypeScript library providing type definitions, validation, and conversion utilities for the IVMS101 (interVASP Messaging Standard). Defaults to IVMS101.2023 with full support for legacy 2020 format.

Features

  • 🎯 2023-first API - Modern, clean interface defaulting to the latest standard
  • Runtime validation - Comprehensive Zod schemas with all 12 IVMS101 constraints
  • 🔄 Version conversion - Bidirectional, lossless conversion between 2020 and 2023
  • 🧪 Property-based testing - Fast-check arbitraries for generating compliant test data
  • 📦 Dual format - CommonJS and ESM builds with full TypeScript support
  • 🏗️ Clean architecture - Independent type definitions with no circular dependencies

Installation

npm install ivms101

Upgrading from v1.x to v2.0

Version 2.0 introduces a 2023-first API with breaking changes. Here's how to upgrade:

Breaking Changes

  1. Main export now defaults to IVMS101.2023

    • IVMS101 type is now IVMS101_2023.IVMS101 (not a union)
    • All type exports from main package are 2023 types
  2. 2020 support moved to legacy submodule

    • Import 2020 types from 'ivms101/legacy' instead of main package
    • Conversion functions moved to legacy module
  3. New validation API

    • New validate() function replaces validateIVMS101()
    • Defaults to 2023 validation

Migration Guide

If you're using both 2020 and 2023 (union types)

Before (v1.x):

import { IVMS101, IVMS101_2020, IVMS101_2023 } from 'ivms101';

// IVMS101 was a union type
function process(data: IVMS101) {
  // data could be either version
}

After (v2.0):

import { IVMS101 } from 'ivms101'; // This is now 2023 only
import { IVMS101_2020, IVMS101Schema } from 'ivms101/legacy';

// For union type, import from legacy
import type { IVMS101Type } from 'ivms101/legacy';

function process(data: IVMS101Type) {
  // data can be either version (union)
}

// OR: Keep separate functions for each version
function process2023(data: IVMS101) { /* ... */ }
function process2020(data: IVMS101_2020.IVMS101) { /* ... */ }

If you're using 2020 types

Before (v1.x):

import { IVMS101_2020 } from 'ivms101';

const data: IVMS101_2020.IVMS101 = { /* ... */ };

After (v2.0):

import { IVMS101_2020 } from 'ivms101/legacy';

const data: IVMS101_2020.IVMS101 = { /* ... */ };

If you're using conversion functions

Before (v1.x):

import { convertTo2023, convertFrom2023 } from 'ivms101';

After (v2.0):

import { convertTo2023, convertFrom2023 } from 'ivms101/legacy';

If you're using validation

Before (v1.x):

import { validateIVMS101, isValidIVMS101 } from 'ivms101';

const validated = validateIVMS101(data); // accepts either version

After (v2.0):

// Option 1: Use new validate() function (defaults to 2023)
import { validate } from 'ivms101';
const validated = validate(data); // validates as 2023
const validated2020 = validate(data, { version: '2020' });

// Option 2: Use legacy validateIVMS101 for union validation
import { validateIVMS101, isValidIVMS101 } from 'ivms101/legacy';
const validated = validateIVMS101(data); // accepts either version

If you're using type guards

Before (v1.x):

import { isValidIVMS101_2023 } from 'ivms101';

After (v2.0):

// 2023 type guard in main package
import { isValidIVMS101_2023 } from 'ivms101';

// 2020 type guard in legacy package
import { isValidIVMS101_2020 } from 'ivms101/legacy';

Quick Migration Checklist

  • [ ] Replace import { IVMS101_2020, ... } from 'ivms101' with import { IVMS101_2020, ... } from 'ivms101/legacy'
  • [ ] Replace import { convertTo2023, convertFrom2023 } from 'ivms101' with import { convertTo2023, convertFrom2023 } from 'ivms101/legacy'
  • [ ] If using union types, import IVMS101Type from 'ivms101/legacy' instead of using IVMS101
  • [ ] Update validation calls to use new validate() function or import legacy validators
  • [ ] Update type annotations: IVMS101 is now 2023-only (not a union)

What Stays the Same

✅ All 2023 types work exactly as before (just imported from main package) ✅ All conversion logic is unchanged (just moved to legacy module) ✅ All validation schemas work the same way ✅ ensureVersion() and ivms101_version() still in main package ✅ Arbitraries still work the same way ✅ All tests pass without changes

Recommended Approach

For new code, use the 2023-first API:

import { validate, type IVMS101 } from 'ivms101';

For existing code that needs 2020 support, add legacy import:

import { validate, type IVMS101 } from 'ivms101';
import { IVMS101_2020, convertTo2023 } from 'ivms101/legacy';

Quick Start

Working with IVMS101.2023 (Default)

import { validate, type IVMS101, type NaturalPerson } from 'ivms101';

// The IVMS101 type is IVMS101.2023 by default
const data: IVMS101 = {
  originator: {
    originatorPerson: [{ /* ... */ }]  // Note: singular "Person" in 2023
  },
  beneficiary: {
    beneficiaryPerson: [{ /* ... */ }]
  },
  payloadMetadata: {
    payloadVersion: "101.2023"  // Required in 2023
  }
};

// Validate (defaults to 2023)
const validated = validate(data);

// Or explicitly specify version
const validated2023 = validate(data, { version: '2023' });

Working with Legacy IVMS101 2020

import { IVMS101_2020 } from 'ivms101/legacy';
import { validate } from 'ivms101';

const legacy: IVMS101_2020.IVMS101 = {
  originator: {
    originatorPersons: [{ /* ... */ }]  // Note: plural "Persons" in 2020
  },
  beneficiary: {
    beneficiaryPersons: [{ /* ... */ }]
  }
};

// Validate as 2020 format
const validated = validate(legacy, { version: '2020' });

Converting Between Versions

import { ensureVersion, ivms101_version, PayloadVersionCode } from 'ivms101';
import { convertTo2023, convertFrom2023 } from 'ivms101/legacy';

// Auto-detect version
const version = ivms101_version(data);

// Convert to 2023 (default)
const data2023 = ensureVersion(data);

// Convert to specific version
const data2020 = ensureVersion(PayloadVersionCode.V2020, data);

// Explicit conversions
const converted2023 = convertTo2023(data2020);
const converted2020 = convertFrom2023(data2023);

API Reference

Main Exports (2023-first)

import {
  // Types (all are IVMS101.2023)
  type IVMS101,              // Main IVMS101 type
  type NaturalPerson,        // Natural person type
  type LegalPerson,          // Legal person type
  type Person,               // Person (natural or legal)
  type Originator,           // Originator type
  type Beneficiary,          // Beneficiary type

  // Enums
  PayloadVersionCode,        // Version codes ("101" | "101.2023")

  // Validation
  validate,                  // validate(data, { version?: '2020' | '2023' })
  IVMS101_2023Schema,        // Zod schema for 2023
  isValidIVMS101_2023,       // Type guard for 2023

  // Utilities
  ensureVersion,             // Convert to specific version (defaults to 2023)
  ivms101_version,           // Detect version

  // Testing
  arbitraries,               // Fast-check arbitraries

  // Shared core types (also exported directly)
  type CountryCode,          // ISO country codes
  type AddressTypeCode,      // Address type codes
  type NaturalPersonNameTypeCode,  // Natural person name type codes
  type LegalPersonNameTypeCode,    // Legal person name type codes
  type Address,              // Address structure
  type NationalIdentification,     // National ID structure
  // ... and other core types
} from 'ivms101';

Legacy Exports (2020 support)

import {
  // Types
  IVMS101_2020,              // Namespace with all 2020 types

  // Conversion
  convertTo2023,             // Convert 2020 → 2023
  convertFrom2023,           // Convert 2023 → 2020

  // Validation
  IVMS101_2020Schema,        // Zod schema for 2020
  isValidIVMS101_2020,       // Type guard for 2020
  IVMS101Schema,             // Union schema (2020 | 2023)
  validateIVMS101,           // Validate either version
  isValidIVMS101,            // Type guard for either version
} from 'ivms101/legacy';

Validation

Basic Validation

import { validate } from 'ivms101';

// Validate with default version (2023)
try {
  const validated = validate(unknownData);
  console.log('Valid IVMS101.2023 data:', validated);
} catch (error) {
  console.error('Validation failed:', error.message);
}

// Validate specific version
const validated2020 = validate(data, { version: '2020' });

Type Guards

import { isValidIVMS101_2023 } from 'ivms101';
import { isValidIVMS101_2020, isValidIVMS101 } from 'ivms101/legacy';

// Check if data is valid 2023 format
if (isValidIVMS101_2023(data)) {
  // TypeScript knows data is IVMS101_2023.IVMS101
  console.log(data.originator.originatorPerson);
}

// Check if data is valid 2020 format
if (isValidIVMS101_2020(data)) {
  // TypeScript knows data is IVMS101_2020.IVMS101
  console.log(data.originator.originatorPersons);
}

// Check if data is either version
if (isValidIVMS101(data)) {
  console.log('Valid IVMS101 data (either version)');
}

Schema Validation

import { IVMS101_2023Schema } from 'ivms101';
import { IVMS101_2020Schema, IVMS101Schema } from 'ivms101/legacy';

// Safe parsing (doesn't throw)
const result = IVMS101_2023Schema.safeParse(data);
if (result.success) {
  console.log('Valid data:', result.data);
} else {
  console.log('Validation errors:', result.error.issues);
}

// Parse (throws on invalid data)
const validated = IVMS101_2023Schema.parse(data);

// Union schema for either version
const validatedAny = IVMS101Schema.parse(data);

Version Differences

The 2023 version introduced several breaking changes from 2020:

| Aspect | IVMS101 2020 | IVMS101.2023 | |--------|--------------|--------------| | Originator field | originatorPersons (plural) | originatorPerson (singular) | | Beneficiary field | beneficiaryPersons (plural) | beneficiaryPerson (singular) | | Customer ID (both person types) | customerNumber | customerIdentification | | Natural person name field | nameIdentifierType | naturalPersonNameIdentifierType | | Payload version field | Optional | Required (payloadMetadata.payloadVersion) |

Migration Example

// 2020 format
const data2020 = {
  originator: {
    originatorPersons: [{
      naturalPerson: {
        customerNumber: "12345",
        name: {
          nameIdentifier: [{
            primaryIdentifier: "Doe",
            secondaryIdentifier: "John",
            nameIdentifierType: "LEGL"
          }]
        }
      }
    }]
  },
  // ... rest of structure
};

// 2023 format (after conversion)
const data2023 = {
  originator: {
    originatorPerson: [{
      naturalPerson: {
        customerIdentification: "12345",
        name: {
          nameIdentifier: [{
            primaryIdentifier: "Doe",
            secondaryIdentifier: "John",
            naturalPersonNameIdentifierType: "LEGL"
          }]
        }
      }
    }]
  },
  payloadMetadata: {
    payloadVersion: "101.2023"
  }
  // ... rest of structure
};

Property-Based Testing

The library includes comprehensive fast-check arbitraries for generating valid IVMS101 test data.

Installation

npm install --save-dev fast-check

Basic Usage

import { arbitraries } from 'ivms101';
import * as fc from 'fast-check';

// Generate sample data
const samples2023 = fc.sample(arbitraries.ivms101_2023Valid(), 5);
const samples2020 = fc.sample(arbitraries.ivms101_2020(), 5);
const personSamples = fc.sample(arbitraries.naturalPerson(), 10);

Property-Based Tests

import { arbitraries } from 'ivms101';
import { validate } from 'ivms101';
import { convertTo2023, convertFrom2023 } from 'ivms101/legacy';
import * as fc from 'fast-check';

describe('IVMS101 Properties', () => {
  it('all generated 2023 data should be valid', () => {
    fc.assert(fc.property(arbitraries.ivms101_2023Valid(), (data) => {
      expect(() => validate(data)).not.toThrow();
    }));
  });

  it('should preserve data through roundtrip conversion', () => {
    fc.assert(fc.property(arbitraries.ivms101_2020(), (original) => {
      const converted = convertTo2023(original);
      const backConverted = convertFrom2023(converted);

      expect(backConverted.originator.originatorPersons.length)
        .toBe(original.originator.originatorPersons.length);
    }));
  });
});

Available Arbitraries

Complete Structures

  • ivms101_2020() - Generate IVMS101 2020 objects
  • ivms101_2023() - Generate IVMS101 2023 objects
  • ivms101_2023Valid() - Generate 2023 with guaranteed version field
  • ivms101() - Generate either version randomly

Person Types

  • naturalPerson() - Natural person (2020 format)
  • legalPerson() - Legal person (2020 format)
  • person() - Either natural or legal (2020)
  • naturalPerson2023() - Natural person (2023 format)
  • legalPerson2023() - Legal person (2023 format)
  • person2023() - Either natural or legal (2023)

Components

  • naturalPersonNameId() - Name identifier for natural persons
  • legalPersonNameId() - Name identifier for legal persons
  • address() - Complete address objects
  • naturalPersonNationalIdentification() - National ID for natural persons
  • legalEntityNationalIdentification() - National ID for legal entities

Enums & Codes

  • naturalPersonNameTypeCode() - Name type codes
  • legalPersonNameTypeCode() - Legal person name codes
  • addressTypeCode() - Address type codes
  • countryCode() - ISO country codes
  • nationalIdentifierTypeCode() - National ID type codes
  • transliterationMethodCode() - Transliteration codes

Validation Constraints

The library implements all 12 IVMS101 specification constraints:

  • C1: OriginatorInformationNaturalPerson - Must have address, customer ID, national ID, or date of birth
  • C2: DateInPast - Birth date must be historic
  • C4: OriginatorInformationLegalPerson - Must have address, customer ID, or national ID
  • C5: LegalNamePresentLegalPerson - Must have at least one LEGL name type
  • C6: LegalNamePresentNaturalPerson - Must have at least one LEGL name type
  • C8: ValidAddress - Must have addressLine OR structured address
  • C9: CompleteNationalIdentifierLegalPerson - Complex LEI/registrationAuthority rules
  • C10: RegistrationAuthority format - Must match RA[0-9]{6}
  • C11: ValidLEI format - Must be 20-character alphanumeric
  • C12: sequentialIntegrity - Transfer path sequences must be sequential starting at 0

Array Size Limits

The library enforces these limits during validation:

| Field | Maximum | Rationale | |-------|---------|-----------| | Originator/Beneficiary Persons | 10 | Joint accounts + margin | | Account Numbers | 20 | Multiple corporate wallets | | Name Identifiers (Natural) | 5 | Multiple name variants | | Name Identifiers (Legal) | 3 | Aligns with type codes | | Geographic Addresses | 5 | Multiple addresses | | Transfer Path | 5 | Intermediary VASP chain | | Transliteration Methods | 5 | Character set conversions |

Architecture

The library follows a clean, layered architecture:

countries.ts ← core.ts ← ivms101_2023.ts (independent)
                      ← ivms101_2020.ts (independent)
                      ← validator.ts
                      ← converter.ts
                      ← arbitraries.ts
                      ← index.ts (2023 exports)
                      ← legacy.ts (2020 exports)

Key principle: The 2020 and 2023 type definitions are completely independent, both depending only on shared core types.

TypeScript Support

This library is written in TypeScript and provides complete type definitions:

import type {
  IVMS101,
  NaturalPerson,
  LegalPerson,
  Person,
  Originator,
  Beneficiary,
} from 'ivms101';

import type { IVMS101_2020 } from 'ivms101/legacy';

// Full type safety for both versions
function processData(data: IVMS101) {
  // TypeScript knows this is 2023 format
  console.log(data.originator.originatorPerson); // ✓
}

function processLegacy(data: IVMS101_2020.IVMS101) {
  // TypeScript knows this is 2020 format
  console.log(data.originator.originatorPersons); // ✓
}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License - see LICENSE file for details.

Related Standards