camelcase-keys

Recursively convert snake_case or kebab-case object keys to camelCase (or PascalCase), with exclusions and stop-path control.

Library
npm
v10.0.2
758stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
42/100Fair
Development Activity4
Maintenance20
Community56
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
75/100Good
Architecture82
Code Quality88
Innovation74
Learning Curve55

camelcase-keys is a small, dependency-light JavaScript/TypeScript utility that converts every key in an object — or an array of objects — into camelCase, using Sindre Sorhus’s own camelcase package as its transform engine. It handles nested structures via a deep option, walks into arrays without losing structure, and preserves leading _ and $ characters since they often carry semantic meaning.

Beyond basic conversion, it supports pascalCase for uppercase-first output, preserveConsecutiveUppercase for keeping acronym-like sequences intact, an exclude list (strings or regexes) for keys that must not be touched, and stopPaths for precisely halting recursion at named dot-notation paths — including inside arrays. A built-in LRU cache (via quick-lru) memoizes repeated key transforms, and the library guards against circular references using a WeakMap, making it safe to run over API responses, CLI argument objects, or database rows without special-casing edge cases.

What You Get

  • Deep or shallow key transformation via a single deep boolean option
  • Automatic preservation of circular references and leading _/$ characters
  • Fine-grained exclusion via string or RegExp key matching
  • Dot-notation stopPaths to halt recursion at specific nested paths, including inside arrays
  • Built-in LRU-cached key transforms for repeated-key performance

Common Use Cases

  • Normalizing snake_case JSON responses from REST APIs into camelCase for idiomatic JS consumption
  • Converting CLI argument objects parsed by node:util’s parseArgs into camelCase for cleaner destructuring
  • Mapping database rows (often snake_case column names) into camelCase view models
  • Sanitizing third-party webhook payloads before passing them into strongly-typed application code

Under The Hood

Architecture The package is a single-module, functional design: index.js exports one default function, camelcaseKeys, that dispatches into an internal transform function. That function pre-checks whether a value is a transformable object, handles arrays and objects on separate branches, tracks visited nodes in a WeakMap for circular-reference safety, and threads a parentPath string through recursive calls so stopPaths dot-notation matching works even across array boundaries. Key remapping itself is delegated to map-obj’s mapObject, invoked with a per-branch mapper closure that closes over the current parentPath; the mapper applies the camelcase transform (or bypasses it for excluded/numeric keys) and consults a shared, module-level QuickLru cache to skip repeat string work. There’s no class hierarchy, no I/O, and no external state beyond the process-lifetime cache — every option (deep, stopPaths, exclude, pascalCase, preserveConsecutiveUppercase) is threaded through this one recursive code path rather than isolated into separate strategies, so touching the core transform means touching essentially the whole file.

Tech Stack This is a pure ESM, hand-written TypeScript-typed JavaScript package with no build step — index.js ships alongside a hand-authored index.d.ts rather than compiler output. Runtime dependencies are all from the same author’s ecosystem: camelcase (the actual case-conversion engine), map-obj (pinned to an exact version rather than a range, signaling a known-compatible pairing), quick-lru (a bounded LRU cache), and type-fest (advanced conditional and template-literal types used to compute the exact literal-cased return type). Testing uses ava for behavior and tsd for type-level assertions, linting runs through xo (a stricter ESLint preset), and a micro-benchmark harness lives under bench/. CI runs the full test script across two Node major versions, with engines requiring a current LTS or newer.

Code Quality The test suite is a single flat file covering deep and shallow conversion, exclude, stopPaths (including inside arrays and nested arrays), pascalCase, preserveConsecutiveUppercase, option combinations, non-object arrays, and circular references — an unusually thorough suite for a package this size, layered with extensive type-level tests that assert the sophisticated conditional types in index.d.ts actually infer correctly rather than merely compiling. Error handling is minimal by design, since the function is a pure transform with no I/O or external failure modes to swallow. Naming is consistent throughout, the stricter xo lint preset runs in CI alongside the test run, and a sideEffects: false flag signals bundler-friendliness.

API Design The public API is a single default export with input and an optional options parameter — no configuration object is required for the common case. The CamelCaseKeys conditional type makes the return type reflect exactly which keys were transformed and how, rather than widening to a generic record type, a level of type fidelity most comparably-scoped key-transform utilities don’t attempt. stopPaths — dot-notation, array-boundary-aware — is a distinctive escape hatch letting consumers freeze specific subtrees during a deep conversion instead of an all-or-nothing choice. The tradeoff is genuine complexity: the type definitions use recursive conditional types that are hard to read, and the README itself flags known edge cases around opaque types.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search