Skip to content

Repository files navigation

Normalizer JS

A small, dependency-free JavaScript/TypeScript library to normalize messy data structures: dates, numbers, booleans, nulls, and object key naming conventions.

npm version License: MIT TypeScript Build Status codecov

Features

  • Date Normalization: Convert various date formats to a consistent format with timezone support
  • Number Normalization: Parse numbers from strings with locale awareness
  • Boolean Normalization: Convert various truthy/falsy values to proper booleans
  • Null Normalization: Standardize null/undefined/empty values with custom null values
  • Key Normalization: Convert object keys to consistent naming conventions (camelCase, snake_case, etc.)
  • Fully Configurable: Customize behavior for each normalizer
  • TypeScript Support: Built with TypeScript for better developer experience
  • Zero Dependencies: 100% dependency-free for maximum compatibility and small bundle size
  • Tree-shakeable: Only include the normalizers you need

Installation

# Using npm
npm install normalizer-js

# Or using yarn
yarn add normalizer-js

# Or using pnpm
pnpm add normalizer-js

Quick Start

You can use either the default exported instance (normalizer) or the Normalizer class.

// Option A: default instance
import normalizer from 'normalizer-js';

// Option B: class (includes Normalizer.normalize static helper)
import Normalizer from 'normalizer-js';

const data = {
  created_at: '2025-09-24',
  price: '1,200',
  is_active: 'yes',
  middle_name: 'N/A',
  user: {
    first_name: 'John',
    last_name: 'Doe',
    login_count: '42',
    preferences: { dark_mode: 'true', notifications: 'on' }
  },
  tags: ['tag_one', 'tag_two']
};

// Using default instance
const a = normalizer.normalize(data, { date: true, number: true, boolean: true, null: true, key: { style: 'camel' } });

// Or using the class helper
const b = Normalizer.normalize(data, { date: true, number: true, boolean: true, null: true, key: { style: 'camel' } });

// a and b will be equivalent

Documentation

Configuration

You can customize the normalization behavior by passing a configuration object:

import Normalizer, { normalizer } from 'normalizer-js';
import type { NormalizerConfig } from 'normalizer-js';

// Global configuration
const config: NormalizerConfig = {
  // Global options
  mode: 'loose',                 // 'strict' | 'loose'
  targetKeys: undefined,         // Only normalize these keys if provided
  deepClone: true,               // Deep clone objects/arrays before normalizing
  logging: false,                // Set to true to console.log normalizations

  // Per-normalizer toggles or configs (true enables with defaults)
  date: {                        // Or: true
    outputFormat: 'iso',         // 'iso' | 'timestamp' | custom pattern like 'YYYY-MM-DD'
    // timezone note: supports 'utc' | 'local' | numeric offsets like '+03:00' or '-0200'
    timezone: 'utc',
    strictMode: false
  },
  number: { allowFloat: true },  // Or: true
  boolean: true,
  null: true,
  key: { style: 'camel', recursive: true, preserve: [] }
};

const instance = new Normalizer(config);
const output = instance.normalize(data);

API Reference

normalize(data: any, config?: NormalizerConfig): any

Normalizes the input data according to the provided configuration.

  • data: The data to normalize (object, array, or primitive)
  • config: Optional configuration object
  • Returns: The normalized data

new Normalizer(config?: NormalizerConfig)

Creates a new normalizer instance with the given configuration.

Examples

Date Normalization

import { normalize } from 'normalizer-js';

const data = {
  date1: '2023-01-01',
  date2: '01/31/2023',
  date3: '2023-12-31T23:59:59.999Z',
  timestamp: 1672531200000
};

const normalized = Normalizer.normalize(data, {
  date: {
    outputFormat: 'MM/dd/yyyy',
    // Timezone support: 'utc' | 'local' | offsets like '+03:00' | '-0200'
    timezone: '+03:00'
  }
});

console.log(normalized);
/*
{
  date1: '12/31/2022',
  date2: '01/31/2023',
  date3: '12/31/2023',
  timestamp: '12/31/2022'
}
*/

Number Normalization

import { normalize } from 'normalizer-js';

const data = {
  int: '42',
  float: '3.14',
  formatted: '1,234.56',
  negative: '-500.25'
};

const normalized = Normalizer.normalize(data, {
  number: {
    allowFloat: false // Round to integers
  }
});

console.log(normalized);
/*
{
  int: 42,
  float: 3,
  formatted: 1234,
  negative: -500
}
*/

Boolean Normalization

import { normalize } from 'normalizer-js';

const data = {
  active: 'yes',
  verified: 'true',
  notifications: 'on',
  subscribed: 'no',
  admin: 'false'
};

const normalized = normalize(data);

console.log(normalized);
/*
{
  active: true,
  verified: true,
  notifications: true,
  subscribed: false,
  admin: false
}
*/

Null Normalization

import { normalize } from 'normalizer-js';

const data = {
  name: 'John Doe',
  middleName: 'N/A',
  age: '',
  address: {
    street: '123 Main St',
    apartment: '--',
    zip: null
  },
  tags: ['', 'tag1', 'N/A']
};

const normalized = normalize(data);

console.log(normalized);
/*
{
  name: 'John Doe',
  middleName: null,
  age: null,
  address: {
    street: '123 Main St',
    apartment: null,
    zip: null
  },
  tags: [null, 'tag1', null]
}
*/

Key Normalization

import { normalize } from 'normalizer-js';

const data = {
  user_name: 'johndoe',
  'first-name': 'John',
  LastName: 'Doe',
  contact_info: {
    email_address: 'john@example.com',
    phone_number: '123-456-7890'
  },
  USER_ROLE: 'admin'
};

// Convert to camelCase (default)
const camelCased = Normalizer.normalize(data, {
  key: {
    style: 'camel',
    preserve: ['USER_ROLE']
  }
});

console.log(camelCased);
/*
{
  userName: 'johndoe',
  firstName: 'John',
  lastName: 'Doe',
  contactInfo: {
    emailAddress: 'john@example.com',
    phoneNumber: '123-456-7890'
  },
  USER_ROLE: 'admin'
}
*/

// Convert to snake_case
const snakeCased = Normalizer.normalize(data, {
  key: {
    style: 'snake',
    recursive: true
  }
});

console.log(snakeCased);
/*
{
  user_name: 'johndoe',
  first_name: 'John',
  last_name: 'Doe',
  contact_info: {
    email_address: 'john@example.com',
    phone_number: '123-456-7890'
  },
  user_role: 'admin'
}
*/

Real-world usage examples

  • CSV ingestion: Convert imported CSV strings to typed values
    • Dates like "01/31/2023" to ISO, amounts like "1,234.56" to numbers, and empty fields to null.
  • API response cleanup: Convert snake_case API payloads to camelCase and coerce types
    • Enable key: { style: 'camel', recursive: true }, plus date: true, number: true, boolean: true, null: true.
  • Strict data validation: Fail fast when encountering invalid values
    • Set mode: 'strict' and enable needed normalizers; invalid values will throw with helpful errors.

TypeScript usage

All public APIs are fully typed. You can import types like NormalizerConfig to author configs safely.

import Normalizer, { type NormalizerConfig } from 'normalizer-js';

const config: NormalizerConfig = { date: true, number: true, key: { style: 'camel' } };
const output = Normalizer.normalize({ created_at: '2023-01-01', amount: '1,000' }, config);

Contributing

Contributions are welcome! If you’d like to help:

  • Open issues for bugs, feature requests, or questions
  • Submit PRs with tests (the repo enforces >= 80% global coverage)
  • Follow the existing code style and lint rules

Before publishing to npm:

  • Update package.json name, author, repository, and bugs fields
  • Run npm run build to generate dist/
  • Verify npm run test passes and coverage thresholds are met
  • Tag a version and publish with npm publish

License

MIT © Kaan Demirel

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages