Skip to content

Commit

Permalink
Require Node.js 14 and move to ESM
Browse files Browse the repository at this point in the history
  • Loading branch information
sindresorhus committed Jun 6, 2022
1 parent 87c57ac commit e445b77
Show file tree
Hide file tree
Showing 9 changed files with 235 additions and 228 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/main.yml
Expand Up @@ -10,12 +10,12 @@ jobs:
fail-fast: false
matrix:
node-version:
- 18
- 16
- 14
- 12
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm install
Expand Down
7 changes: 3 additions & 4 deletions bench/bench.js
@@ -1,8 +1,7 @@
/* globals bench suite set */
'use strict';
const camelcaseKeysNpm = require('camelcase-keys');
const fixture = require('./fixture');
const camelcaseKeys = require('..');
import camelcaseKeysNpm from 'camelcase-keys';
import camelcaseKeys from '../index.js';
import fixture from './fixture.js';

suite('camelcaseKeys', () => {
set('mintime', 1000);
Expand Down
4 changes: 2 additions & 2 deletions fixtures/child-process-for-test.js
@@ -1,5 +1,5 @@
'use strict';
const camelcaseKeys = require('..');
import process from 'node:process';
import camelcaseKeys from '../index.js';

const camelcaseKeysArgs = JSON.parse(process.argv[2]);

Expand Down
146 changes: 75 additions & 71 deletions index.d.ts
Expand Up @@ -9,12 +9,11 @@ Return a default type if input type is nil.
@template T - Input type.
@template U - Default type.
*/
type WithDefault<T, U extends T> = T extends undefined | void | null ? U : T;
type WithDefault<T, U extends T> = T extends undefined | void | null ? U : T; // eslint-disable-line @typescript-eslint/ban-types

// TODO: Replace this with https://github.com/sindresorhus/type-fest/blob/main/source/includes.d.ts
/**
Check if an element is included in a tuple.
TODO: Remove this once https://github.com/sindresorhus/type-fest/pull/217 is merged.
*/
type IsInclude<List extends readonly unknown[], Target> = List extends undefined
? false
Expand Down Expand Up @@ -42,7 +41,7 @@ export type CamelCaseKeys<
IsPascalCase extends boolean = false,
Exclude extends readonly unknown[] = EmptyTuple,
StopPaths extends readonly string[] = EmptyTuple,
Path extends string = ''
Path extends string = '',
> = T extends readonly any[]
// Handle arrays or tuples.
? {
Expand All @@ -62,7 +61,7 @@ export type CamelCaseKeys<
: [IsPascalCase] extends [true]
? PascalCase<P>
: CamelCase<P>]: [IsInclude<StopPaths, AppendPath<Path, P & string>>] extends [
true
true,
]
? T[P]
: [Deep] extends [true]
Expand All @@ -79,68 +78,68 @@ export type CamelCaseKeys<
// Return anything else as-is.
: T;

declare namespace camelcaseKeys {
interface Options {
/**
Recurse nested objects and objects in arrays.
type Options = {
/**
Recurse nested objects and objects in arrays.
@default false
*/
readonly deep?: boolean;

@default false
*/
readonly deep?: boolean;
/**
Exclude keys from being camel-cased.
/**
Exclude keys from being camel-cased.
If this option can be statically determined, it's recommended to add `as const` to it.
If this option can be statically determined, it's recommended to add `as const` to it.
@default []
*/
readonly exclude?: ReadonlyArray<string | RegExp>;

@default []
*/
readonly exclude?: ReadonlyArray<string | RegExp>;
/**
Exclude children at the given object paths in dot-notation from being camel-cased. For example, with an object like `{a: {b: '🦄'}}`, the object path to reach the unicorn is `'a.b'`.
/**
Exclude children at the given object paths in dot-notation from being camel-cased. For example, with an object like `{a: {b: '🦄'}}`, the object path to reach the unicorn is `'a.b'`.
If this option can be statically determined, it's recommended to add `as const` to it.
If this option can be statically determined, it's recommended to add `as const` to it.
@default []
@default []
@example
```
import camelcaseKeys from 'camelcase-keys';
@example
```
camelcaseKeys({
a_b: 1,
a_c: {
c_d: 1,
c_e: {
e_f: 1
}
camelcaseKeys({
a_b: 1,
a_c: {
c_d: 1,
c_e: {
e_f: 1
}
}, {
deep: true,
stopPaths: [
'a_c.c_e'
]
}),
// {
// aB: 1,
// aC: {
// cD: 1,
// cE: {
// e_f: 1
// }
// }
// }
```
*/
readonly stopPaths?: readonly string[];

/**
Uppercase the first character as in `bye-bye` → `ByeBye`.
@default false
*/
readonly pascalCase?: boolean;
}
}
}
}, {
deep: true,
stopPaths: [
'a_c.c_e'
]
}),
// {
// aB: 1,
// aC: {
// cD: 1,
// cE: {
// e_f: 1
// }
// }
// }
```
*/
readonly stopPaths?: readonly string[];

/**
Uppercase the first character as in `bye-bye` → `ByeBye`.
@default false
*/
readonly pascalCase?: boolean;
};

/**
Convert object keys to camel case using [`camelcase`](https://github.com/sindresorhus/camelcase).
Expand All @@ -149,7 +148,7 @@ Convert object keys to camel case using [`camelcase`](https://github.com/sindres
@example
```
import camelcaseKeys = require('camelcase-keys');
import camelcaseKeys from 'camelcase-keys';
// Convert an object
camelcaseKeys({'foo-bar': true});
Expand All @@ -162,31 +161,36 @@ camelcaseKeys([{'foo-bar': true}, {'bar-foo': false}]);
camelcaseKeys({'foo-bar': true, nested: {unicorn_rainbow: true}}, {deep: true});
//=> {fooBar: true, nested: {unicornRainbow: true}}
camelcaseKeys({a_b: 1, a_c: {c_d: 1, c_e: {e_f: 1}}}, {deep: true, stopPaths: ['a_c.c_e']}),
//=> {aB: 1, aC: {cD: 1, cE: {e_f: 1}}}
// Convert object keys to pascal case
camelcaseKeys({'foo-bar': true, nested: {unicorn_rainbow: true}}, {deep: true, pascalCase: true});
//=> {FooBar: true, Nested: {UnicornRainbow: true}}
```
import minimist = require('minimist');
@example
```
import {parseArgs} from 'node:utils';
import camelcaseKeys from 'camelcase-keys';
const argv = minimist(process.argv.slice(2));
const commandLineArguments = parseArgs();
//=> {_: [], 'foo-bar': true}
camelcaseKeys(argv);
camelcaseKeys(commandLineArguments);
//=> {_: [], fooBar: true}
```
*/
declare function camelcaseKeys<
export default function camelcaseKeys<
T extends Record<string, any> | readonly any[],
Options extends camelcaseKeys.Options = camelcaseKeys.Options
OptionsType extends Options = Options,
>(
input: T,
options?: Options
options?: OptionsType
): CamelCaseKeys<
T,
WithDefault<Options['deep'], false>,
WithDefault<Options['pascalCase'], false>,
WithDefault<Options['exclude'], EmptyTuple>,
WithDefault<Options['stopPaths'], EmptyTuple>
WithDefault<OptionsType['deep'], false>,
WithDefault<OptionsType['pascalCase'], false>,
WithDefault<OptionsType['exclude'], EmptyTuple>,
WithDefault<OptionsType['stopPaths'], EmptyTuple>
>;

export default camelcaseKeys;
44 changes: 22 additions & 22 deletions index.js
@@ -1,26 +1,26 @@
'use strict';
const mapObj = require('map-obj');
const camelCase = require('camelcase');
const QuickLru = require('quick-lru');

const has = (array, key) => array.some(x => {
if (typeof x === 'string') {
return x === key;
import mapObject from 'map-obj';
import camelCase from 'camelcase';
import QuickLru from 'quick-lru';

const has = (array, key) => array.some(element => {
if (typeof element === 'string') {
return element === key;
}

x.lastIndex = 0;
return x.test(key);
element.lastIndex = 0;

return element.test(key);
});

const cache = new QuickLru({maxSize: 100000});
const cache = new QuickLru({maxSize: 100_000});

// Reproduces behavior from `map-obj`
// Reproduces behavior from `map-obj`.
const isObject = value =>
typeof value === 'object' &&
value !== null &&
!(value instanceof RegExp) &&
!(value instanceof Error) &&
!(value instanceof Date);
typeof value === 'object'
&& value !== null
&& !(value instanceof RegExp)
&& !(value instanceof Error)
&& !(value instanceof Date);

const camelCaseConvert = (input, options) => {
if (!isObject(input)) {
Expand All @@ -30,7 +30,7 @@ const camelCaseConvert = (input, options) => {
options = {
deep: false,
pascalCase: false,
...options
...options,
};

const {exclude, pascalCase, stopPaths, deep} = options;
Expand All @@ -42,7 +42,7 @@ const camelCaseConvert = (input, options) => {
const path = parentPath === undefined ? key : `${parentPath}.${key}`;

if (!stopPathsSet.has(path)) {
value = mapObj(value, makeMapper(path));
value = mapObject(value, makeMapper(path));
}
}

Expand All @@ -65,13 +65,13 @@ const camelCaseConvert = (input, options) => {
return [key, value];
};

return mapObj(input, makeMapper(undefined));
return mapObject(input, makeMapper(undefined));
};

module.exports = (input, options) => {
export default function camelcaseKeys(input, options) {
if (Array.isArray(input)) {
return Object.keys(input).map(key => camelCaseConvert(input[key], options));
}

return camelCaseConvert(input, options);
};
}

0 comments on commit e445b77

Please sign in to comment.