v0.9.2 released — parseCompact (currency), getWeton (Javanese market day) and addBusinessDays (datetime). Read changelog
Skip to Content
DocumentationChangelog

v0.9.2 - June 1, 2026

New Features

Currency — parseCompact

Inverse of formatCompact. Parses Indonesian compact amount shorthand like "1,5jt", "500k", "2rb", "3 miliar", "1M", "1T" into a number. Comma = decimal, dot = thousands. Case-insensitive and whitespace-tolerant. Returns NaN for missing/unknown multiplier or garbage input.

Multiplier shorthands accepted:

  • rb, ribu, k → 1 000
  • jt, juta → 1 000 000
  • M, miliar, milyar → 1 000 000 000
  • T, triliun → 1 000 000 000 000
import { parseCompact } from '@indodev/toolkit/currency'; parseCompact('1,5jt'); // 1500000 parseCompact('3 miliar'); // 3000000000 parseCompact('500k'); // 500000 parseCompact('1.5'); // NaN (no multiplier)

DateTime — getWeton

Returns the Javanese market-day information for a date: { pasaran, weekday, neptu }. Uses the canonical Javanese calendar anchor (8 July 1633 CE, Sultan Agung inauguration) and a pure day-count algorithm. All 35 unique weton are reachable across a single 35-day cycle; neptu is always in [7, 18].

import { getWeton } from '@indodev/toolkit/datetime'; getWeton(new Date('1945-08-17')); // { weekday: 'Jumat', pasaran: 'Pahing', neptu: 15 } // 17 August 1945 = Friday Pahing, neptu 15

DateTime — addBusinessDays

Adds or subtracts a number of working days, skipping weekends. Standard business-day semantics: Wed+1=Thu, Wed+2=Fri, Wed+3=Mon (weekend is only consumed when the count traverses it). Result is always a weekday for non-zero count. Holidays are not skipped (out of scope by design).

import { addBusinessDays } from '@indodev/toolkit/datetime'; addBusinessDays(new Date('2026-01-07'), 2); // 2026-01-09 (Wed + 2 = Fri) addBusinessDays(new Date('2026-01-09'), 1); // 2026-01-12 (Fri + 1 = Mon)

v0.9.1 - June 1, 2026

API Consistency

Internal refactor for codebase uniformity. Zero breaking changes — every existing import resolves exactly as before.

  • InvalidSplitError moved from src/currency/calc.ts to src/currency/types.ts (the documented convention). Public re-export from @indodev/toolkit and @indodev/toolkit/currency unchanged.
  • The pdp (Privacy Engine) module now carries a module-level JSDoc header with @module pdp, matching the convention used by all other modules.
  • The acronym-vs-full-word naming rule is now documented in architecture.md for new contributors.

Mock Generator Parity

The mock module now generates fixtures for every ID type the library can validate.

  • generateBPJS(options?) — generates a structurally valid BPJS number (Kesehatan 13-digit or Ketenagakerjaan 11-digit). Default scheme: Kesehatan. Output passes validateBPJS(). Supports seed for reproducibility.
  • generateVIN(options?) — generates a valid 17-character VIN including a correct check digit at position 9, no I/O/Q characters. Optional manufacturerPrefix (3-char WMI segment) supported. Output passes validateVIN(). Supports seed.
  • generateMockPerson() now accepts includeBPJS: true to attach a valid BPJS number to the composite person fixture. Default off — existing consumer snapshots preserved exactly.

Documentation

  • Updated stats: 13 modules, 135+ exports, 2088+ tests

v0.9.0 - June 1, 2026

New Modules

BPJS Module

Indonesian BPJS Kesehatan (13-digit) and BPJS Ketenagakerjaan (11-digit) validation, formatting, parsing, and masking:

  • validateBPJS() - Validate BPJS number by type
  • validateBPJSKesehatan() - Validate 13-digit kesehatan number
  • validateBPJSKetenagakerjaan() - Validate 11-digit ketenagakerjaan number
  • detectBPJSType() - Auto-detect BPJS type from length
  • formatBPJS() - Format with proper separators
  • maskBPJS() - Mask for privacy display
  • parseBPJS() - Extract type, raw, and formatted values
  • cleanBPJS() - Strip separators

Mock Module

Generate deterministic fake Indonesian identity data that passes all validators — useful for testing:

  • createMockFactory() - Pre-seeded factory for reproducible data sequences
  • generateMockPerson() - Complete person with all fields (NIK, NPWP, phone, email, plate, name, gender, birthDate)
  • generateNIK(), generateNPWP(), generatePhone(), generateEmail(), generatePlate(), generateName() - Individual generators
  • createLCG() - Linear Congruential Generator for deterministic pseudo-random sequences

All generated data passes corresponding validate*() functions.

Documentation

  • Updated stats: 13 modules, 133+ exports, 2068+ tests
  • README reorganized with code-first examples per module
  • Added BPJS and Mock to module index and navigation

v0.8.0 - May 27, 2026

New Modules

NLP Module

Indonesian Natural Language Processing utilities:

  • stemText() - Strip Indonesian affixes
  • encodePhonetic() - Encode names to phonetic representation
  • isPhoneticMatch() - Compare names for fuzzy matching
  • tokenizeIndo() - Sentence tokenization preserving abbreviations
  • normalizeWhitespace() - Whitespace normalization
  • stripNonAlphanumeric() - Remove special characters

PDP Module (Privacy Engine)

Indonesian PII scanning and masking for UU PDP compliance:

  • scanPII() - Detect PII with confidence scoring
  • maskStringPDP() - Mask PII in strings
  • anonymizeString() - Mask PII with JSON-safe escaping
  • anonymizePDP() - Recursive object anonymization

Supported types: NIK, NPWP, Phone, Email, Passport, BPJS, Bank Account

v0.7.3 - April 26, 2026

API Consistency Fixes

Added missing barrel exports:

  • validateRupiah, RoundUnit, CompactOptions, SplitOptions from currency
  • toCamelCase, toPascalCase, toSnakeCase, countSyllables, LOWERCASE_WORDS, ACRONYMS, ABBREVIATIONS from text
  • OperatorName type from phone
  • PLATE_REGIONS constant from plate

v0.7.2 - April 18, 2026

New Features

Currency Module

  • formatPercentage() - Format number as Indonesian percentage with comma as decimal separator

v0.7.1 - April 10, 2026

New Features

Plate Module

  • maskPlate() - Mask license plate for privacy
  • cleanPlate() - Remove non-alphanumeric characters
  • isPrivatePlate() - Check if private vehicle plate
  • isPublicPlate() - Check if public transportation plate
  • isDiplomatPlate() - Check if diplomat plate

VIN Module

  • maskVIN() - Mask VIN for privacy
  • cleanVIN() - Remove non-alphanumeric characters

NPWP Module

  • cleanNPWP() - Remove non-digit characters
  • isNIKBasedNPWP() - Check if 16-digit NIK-based NPWP

Main Exports

Added missing barrel exports:

  • NIK: cleanNIK, validateNIKDetailed, compareNIK, isAdult
  • Phone: normalizePhoneNumber, comparePhones, getLandlineRegion
  • Currency: splitAmount, percentageOf, difference, InvalidSplitError

Bug Fixes

  • InvalidSplitError - Added readonly code property and default message (was missing, inconsistent with other error classes)

Type Definitions

  • Added PlateMaskOptions interface
  • Added VINMaskOptions interface

v0.7.0 - April 6, 2026

New Features

Error Classes

Custom error classes with code property for programmatic error handling:

  • InvalidPhoneError - Error for invalid phone numbers
  • InvalidNPWPError - Error for invalid NPWP
  • InvalidEmailError - Error for invalid email addresses
  • InvalidPlateError - Error for invalid vehicle plates
  • InvalidVINError - Error for invalid VINs

Parse Functions

  • parseVIN() - Extract VIN components (WMI, VDS, check digit, model year, plant code, serial number)
  • parsePlate() - Extract plate components (prefix, number, suffix, type, formatted)

Breaking Changes with Deprecation

Mask Options Standardization

Standardized mask option names across all modules:

Old NameNew Name
startvisibleStart
endvisibleEnd
charmaskChar

Migration: Old names still work but emit deprecation warnings in console. Support will be removed in v1.0.0.

NIK Module

  • maskNIK() - Now uses visibleStart, visibleEnd, maskChar options

Phone Module

  • maskPhoneNumber() - Now uses visibleStart, visibleEnd, maskChar options

Text Module

  • maskText() - Now uses visibleStart, visibleEnd, maskChar options, added separator support

v0.6.0 - April 6, 2026

New Features

NIK Module

  • cleanNIK(): Normalize NIK input by stripping separators (., -, )
  • compareNIK(): Check if two NIKs belong to the same person
  • isAdult(): Check KTP eligibility (17 years default, configurable)
  • validateNIKDetailed(): Structured validation result with error codes and messages
  • NIKValidationResult, NIKValidationError, NIKErrorCode types
  • Age and GetAgeOptions types

Breaking Changes

NIK Module

  • getAge() now returns { years, months, days } object instead of number
    • Use { asString: true } option for formatted output (“35 Tahun 2 Bulan 6 Hari”)
    • Use age.years for year comparison

Improvements

NIK Module

  • formatBirthDate() now uses internal formatting (consistent with datetime module)

v0.5.0 - April 6, 2026

Breaking Changes

Phone Module

  • generateWALink() and generateSmsLink() now reject landlines
    • WhatsApp and SMS only work on mobile numbers
    • Landline numbers now return empty string ''
    • Use generateTelLink() for landline phone calls

Improvements

Phone Module

  • comparePhones() now properly compares using E.164 format for accurate comparison
  • getLandlineRegion() now uses shared normalizePhoneNumber() utility (removed code duplication)

v0.4.2 - April 6, 2026

Improvements

NIK Module Code Quality

  • Extracted shared date validation logic to utils/date.ts (DRY principle)
  • Added InvalidNIKError custom error class for consistent error handling with datetime module
  • Cached regex pattern in validateNIK() and parseNIK() for ~10% performance improvement

Bug Fixes

  • parseNIK() now properly validates calendar dates (e.g., Feb 30, Feb 31 returned incorrect results)

Documentation

  • Removed sanitizeNIK() from best practices section (function not exported)

v0.4.1 - April 6, 2026

New Features

Phone Module Enhancements

  • normalizePhoneNumber() - New utility to normalize phone numbers to national format (08xx)
  • comparePhones() - Compare two phone numbers regardless of format
  • getLandlineRegion() - Get region name from landline area code

Bug Fixes

  • isMobileNumber() - Fixed 620 prefix edge case bug (was treating invalid 620xxx as valid)
  • Removed code duplication in format.ts and parse.ts (single source of truth in utils.ts)

Improvements

  • getOperator() - Return type now properly typed as OperatorName | null
  • Constants now use as const for better type safety
  • OPERATOR_PREFIXES values typed as OperatorName union type

Documentation

  • Added @public JSDoc tags to generateWALink, generateSmsLink, generateTelLink

v0.4.0 - April 5, 2026

New Features

DateTime Module

A comprehensive new module for Indonesian date/time operations:

  • formatDate() - Format dates with Indonesian locale (6 styles: full, long, medium, short, weekday, month)
  • formatDateRange() - Smart date range formatting with automatic redundancy removal
  • parseDate() - Strict DD-MM-YYYY parser with ISO format auto-detection and leap year validation
  • toRelativeTime() - Relative time in Indonesian (“X menit yang lalu”, “Kemarin”, “Besok”, etc.)
  • getAge() - Age calculation with years, months, days support (object or string output)
  • getIndonesianTimezone() - Map IANA timezone names and UTC offsets to WIB/WITA/WIT
  • isLeapYear() - Leap year validation with proper Gregorian calendar rules
  • daysInMonth() - Days in month calculation accounting for leap years
  • isValidDate() - Type guard for validating Date objects
  • isWeekend() / isWorkingDay() - Weekend and working day detection
  • InvalidDateError / InvalidDateRangeError - Custom error classes with error codes for programmatic handling

v0.3.4 - April 4, 2026

Breaking Changes

  • calculateTax() now requires explicit rate parameter (removed default 0.11) to comply with Data Independence mandate

Fixes

  • formatRupiah() negative numbers now display as -Rp 1.500.000 instead of Rp -1.500.000 (standard accounting format)
  • formatCompact() negative numbers now display as -Rp 1,5 juta (consistent with formatRupiah)
  • addRupiahSymbol() no longer uses browser-dependent toLocaleString — uses internal formatting for consistency

New Features

Currency Module Enhancements

  • splitAmount() - Split amounts into equal or custom-ratio parts with optional rounding (e.g., split bills, installments)
  • percentageOf() - Calculate what percentage a part is of a total (e.g., budget allocation)
  • difference() - Calculate absolute and percentage difference between two amounts with direction tracking
  • validateRupiah() - Validate whether a string is a valid Rupiah format
  • formatCompact() now accepts CompactOptions (symbol, spaceAfterSymbol)
  • toWords() now supports withDecimals option for decimal terbilang (e.g., “satu juta koma lima puluh”)
  • InvalidSplitError custom error class for split validation failures

v0.3.3 - April 4, 2026

New Features

Text Module Enhancements

  • maskText() - Versatile text masking utility with all, middle, and email patterns for privacy-compliant data display
  • toCamelCase() - Convert text to camelCase format (replaces Lodash dependency)
  • toPascalCase() - Convert text to PascalCase format
  • toSnakeCase() - Convert text to snake_case format, handles camelCase boundaries
  • countSyllables() - Algorithm-based syllable counter for Indonesian text with dipthong awareness (ai, au, oi)

v0.3.2 - April 3, 2026

New Features

Email Validator Module

  • validateEmail() - Standard email format validation with optional disposable domain detection
  • normalizeEmail() - Utility to clean and lowercase email addresses
  • maskEmail() - Securely mask email addresses for privacy protection (e.g., u***r@example.com)
  • getEmailInfo() - Extract detailed metadata including domain and provider classification

v0.3.1 - April 3, 2026

New Features

VIN (Vehicle Identification Number) Module

  • validateVIN() - Validate 17-character VIN strings according to ISO 3779 checksum standards

v0.3.0 - April 3, 2026

New Features

NPWP Module

  • validateNPWP() - Validate format and checksums for 15-digit and 16-digit NPWP
  • formatNPWP() - Format 15/16-digit data into standard NPWP notations
  • parseNPWP() - Clean and parse NPWP segments
  • maskNPWP() - Mask NPWP digits for privacy and logging

Vehicle Plate (Plat Nomor) Module

  • validatePlate() - Validate standard Indonesian vehicle plate numbers
  • formatPlate() - Format and normalize plate spacing
  • getRegionFromPlate() - Extract corresponding province and region names based on plate prefix

Text Module Enhancements

  • profanityFilter() - Safely filter out common Indonesian bad words
  • removeStopwords() - Remove excessive filler words (stopwords) from Indonesian text
  • toFormal() - Normalize informal writing variants (slang) into formal Indonesian
  • isAlay() - Detect informal “alay” writing styles or excessive symbol usage
  • contractAbbreviation() - Revert expanded text back into standard abbreviations
  • removeAccents() - Remove diacritic marks (accents) for clean string comparisons

Documentation & Core

  • Reorganized module utilities (utils.ts) into core functional exports
  • Added .prettierrc for enforced source code formatting rules
  • Updated API Documentation with multiple runtime installation tabs (npm, pnpm, yarn, bun)

v0.2.0 - January 2, 2026

New Features

Text Module

  • toTitleCase() - Smart capitalization handling Indonesian particles
  • expandAbbreviation() - Expand common Indonesian abbreviations (Jl., Bpk., etc.)
  • slugify() - URL-friendly slugs with Indonesian conjunction support (& -> dan)
  • truncate() - Smart text truncation respecting word boundaries
  • compareStrings() - Robust string comparison (case/accent/whitespace)
  • similarity() - Calculate string similarity scores (Levenshtein)
  • extractWords() - Word extraction preserving hyphenated words
  • sanitize() - Text cleaning and normalization

Improvements

  • Performance optimizations for text processing
  • Comprehensive test coverage for text utilities

v0.1.0 - December 11, 2025

New Features

NIK Module

  • validateNIK() - Validate Indonesian National Identity Number
  • parseNIK() - Extract province, birth date, and gender information
  • formatNIK() - Format NIK with separators
  • maskNIK() - Mask NIK for privacy protection
  • Support for all 38 Indonesian provinces
  • Leap year validation
  • Gender detection from birth date encoding

Phone Module

  • validatePhoneNumber() - Validate Indonesian phone numbers
  • formatPhoneNumber() - Format to international/national/e164 formats
  • getOperator() - Detect mobile operator (Telkomsel, XL, Indosat, Smartfren, Axis)
  • parsePhoneNumber() - Extract all phone information
  • maskPhoneNumber() - Mask phone numbers for privacy
  • cleanPhoneNumber() - Remove separators and normalize
  • Support for 200+ Indonesian area codes
  • Support for landline and mobile numbers

Currency Module

  • formatRupiah() - Format numbers as Rupiah currency
  • formatCompact() - Compact format with proper Indonesian grammar (1,5 juta)
  • parseRupiah() - Parse formatted strings back to numbers
  • toWords() - Convert numbers to Indonesian words (terbilang)
  • roundToClean() - Round to clean amounts (ribu, ratus-ribu, juta)
  • Support for decimal places and custom separators

Package

  • TypeScript support with full type definitions
  • Dual package support (ESM + CommonJS)
  • Tree-shakeable exports
  • Zero runtime dependencies
  • 175+ test cases with 95%+ coverage
Last updated on