@pixpilot/object 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,6 +25,10 @@ const obj = { user_name: 'john', user_details: { first_name: 'John' } };
25
25
  const camelCaseObj = keysToCamelCase(obj);
26
26
  // { userName: 'john', userDetails: { firstName: 'John' } }
27
27
 
28
+ const guidSafeObj = keysToCamelCase(obj, {
29
+ shouldConvert: (key) => key !== 'legacy_key',
30
+ });
31
+
28
32
  // Manipulate objects
29
33
  const picked = pick({ a: 1, b: 2, c: 3 }, ['a', 'c']); // { a: 1, c: 3 }
30
34
  const omitted = omit({ a: 1, b: 2, c: 3 }, ['b']); // { a: 1, c: 3 }
@@ -48,7 +52,7 @@ if (isObject(value)) {
48
52
 
49
53
  ### Key Transformation
50
54
 
51
- - `keysToCamelCase<T>(obj: T): KeysToCamelCase<T>` - Convert all keys to camelCase
55
+ - `keysToCamelCase<T>(obj: T, options?: { shouldConvert?: (key: string) => boolean }): KeysToCamelCase<T>` - Convert keys to camelCase, except GUID keys and keys rejected by `shouldConvert`
52
56
  - `keysToSnakeCase<T>(obj: T): KeysToSnakeCase<T>` - Convert all keys to snake_case
53
57
 
54
58
  ### Object Manipulation
package/dist/index.d.cts CHANGED
@@ -3,9 +3,9 @@ import { deepMerge, deepMergeMany } from "./deep-merge.cjs";
3
3
  import { deleteObjectPropertyByPath as deleteProperty } from "./delete-object-property-by-path.cjs";
4
4
  import { getObjectValueByPath as getProperty } from "./get-object-value-by-path.cjs";
5
5
  import { hasObjectValueByPath as hasProperty } from "./has-object-value-by-path.cjs";
6
- import { KeysToCamelCase, ToCamelCase, keysToCamelCase } from "./keys-to-camel-case.cjs";
6
+ import { KeysToCamelCase, KeysToCamelCaseOptions, ToCamelCase, keysToCamelCase } from "./keys-to-camel-case.cjs";
7
7
  import { KeysToSnakeCase, ToSnakeCase, keysToSnakeCase } from "./keys-to-snake-case.cjs";
8
8
  import { deepClone, deepEqual, deleteProperty as deleteProperty$1, escapePath, flatKeys, getProperty as getProperty$1, hasProperty as hasProperty$1, mapKeys, mapValues, omit, parsePath, pick, setProperty, stringifyPath, unflatten } from "./manipulation.cjs";
9
9
  import { setObjectValueByPath } from "./set-object-value-by-path.cjs";
10
10
  import { isEmptyObject, isObject, isPlainObject } from "./type-guards.cjs";
11
- export { CleanOptions, KeysToCamelCase, KeysToSnakeCase, ToCamelCase, ToSnakeCase, cleanObject, deepClone, deepEqual, deepMerge, deepMergeMany, deleteProperty as deleteObjectPropertyByPath, deleteProperty$1 as deleteProperty, escapePath, flatKeys, getProperty as getObjectValueByPath, getProperty$1 as getProperty, hasProperty as hasObjectValueByPath, hasProperty$1 as hasProperty, isEmptyObject, isObject, isPlainObject, keysToCamelCase, keysToSnakeCase, mapKeys, mapValues, omit, parsePath, pick, setObjectValueByPath, setProperty, stringifyPath, unflatten };
11
+ export { CleanOptions, KeysToCamelCase, KeysToCamelCaseOptions, KeysToSnakeCase, ToCamelCase, ToSnakeCase, cleanObject, deepClone, deepEqual, deepMerge, deepMergeMany, deleteProperty as deleteObjectPropertyByPath, deleteProperty$1 as deleteProperty, escapePath, flatKeys, getProperty as getObjectValueByPath, getProperty$1 as getProperty, hasProperty as hasObjectValueByPath, hasProperty$1 as hasProperty, isEmptyObject, isObject, isPlainObject, keysToCamelCase, keysToSnakeCase, mapKeys, mapValues, omit, parsePath, pick, setObjectValueByPath, setProperty, stringifyPath, unflatten };
package/dist/index.d.ts CHANGED
@@ -3,9 +3,9 @@ import { deepMerge, deepMergeMany } from "./deep-merge.js";
3
3
  import { deleteObjectPropertyByPath as deleteProperty } from "./delete-object-property-by-path.js";
4
4
  import { getObjectValueByPath as getProperty } from "./get-object-value-by-path.js";
5
5
  import { hasObjectValueByPath as hasProperty } from "./has-object-value-by-path.js";
6
- import { KeysToCamelCase, ToCamelCase, keysToCamelCase } from "./keys-to-camel-case.js";
6
+ import { KeysToCamelCase, KeysToCamelCaseOptions, ToCamelCase, keysToCamelCase } from "./keys-to-camel-case.js";
7
7
  import { KeysToSnakeCase, ToSnakeCase, keysToSnakeCase } from "./keys-to-snake-case.js";
8
8
  import { deepClone, deepEqual, deleteProperty as deleteProperty$1, escapePath, flatKeys, getProperty as getProperty$1, hasProperty as hasProperty$1, mapKeys, mapValues, omit, parsePath, pick, setProperty, stringifyPath, unflatten } from "./manipulation.js";
9
9
  import { setObjectValueByPath } from "./set-object-value-by-path.js";
10
10
  import { isEmptyObject, isObject, isPlainObject } from "./type-guards.js";
11
- export { CleanOptions, KeysToCamelCase, KeysToSnakeCase, ToCamelCase, ToSnakeCase, cleanObject, deepClone, deepEqual, deepMerge, deepMergeMany, deleteProperty as deleteObjectPropertyByPath, deleteProperty$1 as deleteProperty, escapePath, flatKeys, getProperty as getObjectValueByPath, getProperty$1 as getProperty, hasProperty as hasObjectValueByPath, hasProperty$1 as hasProperty, isEmptyObject, isObject, isPlainObject, keysToCamelCase, keysToSnakeCase, mapKeys, mapValues, omit, parsePath, pick, setObjectValueByPath, setProperty, stringifyPath, unflatten };
11
+ export { CleanOptions, KeysToCamelCase, KeysToCamelCaseOptions, KeysToSnakeCase, ToCamelCase, ToSnakeCase, cleanObject, deepClone, deepEqual, deepMerge, deepMergeMany, deleteProperty as deleteObjectPropertyByPath, deleteProperty$1 as deleteProperty, escapePath, flatKeys, getProperty as getObjectValueByPath, getProperty$1 as getProperty, hasProperty as hasObjectValueByPath, hasProperty$1 as hasProperty, isEmptyObject, isObject, isPlainObject, keysToCamelCase, keysToSnakeCase, mapKeys, mapValues, omit, parsePath, pick, setObjectValueByPath, setProperty, stringifyPath, unflatten };
@@ -3,13 +3,39 @@ let __pixpilot_string = require("@pixpilot/string");
3
3
  __pixpilot_string = require_rolldown_runtime.__toESM(__pixpilot_string);
4
4
 
5
5
  //#region src/keys-to-camel-case.ts
6
- function keysToCamelCase(obj) {
7
- if (Array.isArray(obj)) return obj.map(keysToCamelCase);
6
+ const FIRST_CHARACTER_INDEX = 0;
7
+ const GUID_LENGTH = 36;
8
+ const GUID_SEPARATOR_CODE = "-".charCodeAt(FIRST_CHARACTER_INDEX);
9
+ const GUID_SEPARATOR_ONE_INDEX = 8;
10
+ const GUID_SEPARATOR_TWO_INDEX = 13;
11
+ const GUID_SEPARATOR_THREE_INDEX = 18;
12
+ const GUID_SEPARATOR_FOUR_INDEX = 23;
13
+ const ZERO_CODE = "0".charCodeAt(FIRST_CHARACTER_INDEX);
14
+ const NINE_CODE = "9".charCodeAt(FIRST_CHARACTER_INDEX);
15
+ const UPPERCASE_A_CODE = "A".charCodeAt(FIRST_CHARACTER_INDEX);
16
+ const UPPERCASE_F_CODE = "F".charCodeAt(FIRST_CHARACTER_INDEX);
17
+ const LOWERCASE_A_CODE = "a".charCodeAt(FIRST_CHARACTER_INDEX);
18
+ const LOWERCASE_F_CODE = "f".charCodeAt(FIRST_CHARACTER_INDEX);
19
+ function isHexCode(charCode) {
20
+ return charCode >= ZERO_CODE && charCode <= NINE_CODE || charCode >= UPPERCASE_A_CODE && charCode <= UPPERCASE_F_CODE || charCode >= LOWERCASE_A_CODE && charCode <= LOWERCASE_F_CODE;
21
+ }
22
+ function isGuidString(key) {
23
+ if (key.length !== GUID_LENGTH) return false;
24
+ if (key.charCodeAt(GUID_SEPARATOR_ONE_INDEX) !== GUID_SEPARATOR_CODE || key.charCodeAt(GUID_SEPARATOR_TWO_INDEX) !== GUID_SEPARATOR_CODE || key.charCodeAt(GUID_SEPARATOR_THREE_INDEX) !== GUID_SEPARATOR_CODE || key.charCodeAt(GUID_SEPARATOR_FOUR_INDEX) !== GUID_SEPARATOR_CODE) return false;
25
+ for (let index = 0; index < key.length; index += 1) if (!(index === GUID_SEPARATOR_ONE_INDEX || index === GUID_SEPARATOR_TWO_INDEX || index === GUID_SEPARATOR_THREE_INDEX || index === GUID_SEPARATOR_FOUR_INDEX) && !isHexCode(key.charCodeAt(index))) return false;
26
+ return true;
27
+ }
28
+ function shouldConvertKey(key, options) {
29
+ if (isGuidString(key)) return false;
30
+ return options?.shouldConvert?.(key) !== false;
31
+ }
32
+ function keysToCamelCase(obj, options) {
33
+ if (Array.isArray(obj)) return obj.map((value) => keysToCamelCase(value, options));
8
34
  if (obj === null || typeof obj !== "object") return obj;
9
35
  const result = {};
10
36
  for (const [key, value] of Object.entries(obj)) {
11
- const camelKey = (0, __pixpilot_string.toCamelCase)(key);
12
- result[camelKey] = keysToCamelCase(value);
37
+ const camelKey = shouldConvertKey(key, options) ? (0, __pixpilot_string.toCamelCase)(key) : key;
38
+ result[camelKey] = keysToCamelCase(value, options);
13
39
  }
14
40
  return result;
15
41
  }
@@ -1,4 +1,7 @@
1
1
  //#region src/keys-to-camel-case.d.ts
2
+ interface KeysToCamelCaseOptions {
3
+ shouldConvert?: (key: string) => boolean;
4
+ }
2
5
  type CamelizeSegment<S extends string> = S extends '' ? '' : Capitalize<Lowercase<S>>;
3
6
  /**
4
7
  * Convert snake_case to camelCase at the type level.
@@ -12,6 +15,6 @@ type ToCamelCase<S extends string, IsFirst extends boolean = true> = S extends `
12
15
  type Builtin = Date | RegExp | Map<unknown, unknown> | Set<unknown> | WeakMap<object, unknown> | WeakSet<object>;
13
16
  type TupleToCamelCase<T extends readonly unknown[]> = { [I in keyof T]: KeysToCamelCase<T[I]> };
14
17
  type KeysToCamelCase<T> = T extends Builtin ? T : T extends ((...args: unknown[]) => unknown) ? T : T extends readonly unknown[] ? number extends T['length'] ? KeysToCamelCase<T[number]>[] : TupleToCamelCase<T> : T extends object ? { [K in keyof T as K extends string ? ToCamelCase<K> : K]: KeysToCamelCase<T[K]> } : T;
15
- declare function keysToCamelCase<T>(obj: T): KeysToCamelCase<T>;
18
+ declare function keysToCamelCase<T>(obj: T, options?: KeysToCamelCaseOptions): KeysToCamelCase<T>;
16
19
  //#endregion
17
- export { KeysToCamelCase, ToCamelCase, keysToCamelCase };
20
+ export { KeysToCamelCase, KeysToCamelCaseOptions, ToCamelCase, keysToCamelCase };
@@ -1,4 +1,7 @@
1
1
  //#region src/keys-to-camel-case.d.ts
2
+ interface KeysToCamelCaseOptions {
3
+ shouldConvert?: (key: string) => boolean;
4
+ }
2
5
  type CamelizeSegment<S extends string> = S extends '' ? '' : Capitalize<Lowercase<S>>;
3
6
  /**
4
7
  * Convert snake_case to camelCase at the type level.
@@ -12,6 +15,6 @@ type ToCamelCase<S extends string, IsFirst extends boolean = true> = S extends `
12
15
  type Builtin = Date | RegExp | Map<unknown, unknown> | Set<unknown> | WeakMap<object, unknown> | WeakSet<object>;
13
16
  type TupleToCamelCase<T extends readonly unknown[]> = { [I in keyof T]: KeysToCamelCase<T[I]> };
14
17
  type KeysToCamelCase<T> = T extends Builtin ? T : T extends ((...args: unknown[]) => unknown) ? T : T extends readonly unknown[] ? number extends T['length'] ? KeysToCamelCase<T[number]>[] : TupleToCamelCase<T> : T extends object ? { [K in keyof T as K extends string ? ToCamelCase<K> : K]: KeysToCamelCase<T[K]> } : T;
15
- declare function keysToCamelCase<T>(obj: T): KeysToCamelCase<T>;
18
+ declare function keysToCamelCase<T>(obj: T, options?: KeysToCamelCaseOptions): KeysToCamelCase<T>;
16
19
  //#endregion
17
- export { KeysToCamelCase, ToCamelCase, keysToCamelCase };
20
+ export { KeysToCamelCase, KeysToCamelCaseOptions, ToCamelCase, keysToCamelCase };
@@ -1,13 +1,39 @@
1
1
  import { toCamelCase } from "@pixpilot/string";
2
2
 
3
3
  //#region src/keys-to-camel-case.ts
4
- function keysToCamelCase(obj) {
5
- if (Array.isArray(obj)) return obj.map(keysToCamelCase);
4
+ const FIRST_CHARACTER_INDEX = 0;
5
+ const GUID_LENGTH = 36;
6
+ const GUID_SEPARATOR_CODE = "-".charCodeAt(FIRST_CHARACTER_INDEX);
7
+ const GUID_SEPARATOR_ONE_INDEX = 8;
8
+ const GUID_SEPARATOR_TWO_INDEX = 13;
9
+ const GUID_SEPARATOR_THREE_INDEX = 18;
10
+ const GUID_SEPARATOR_FOUR_INDEX = 23;
11
+ const ZERO_CODE = "0".charCodeAt(FIRST_CHARACTER_INDEX);
12
+ const NINE_CODE = "9".charCodeAt(FIRST_CHARACTER_INDEX);
13
+ const UPPERCASE_A_CODE = "A".charCodeAt(FIRST_CHARACTER_INDEX);
14
+ const UPPERCASE_F_CODE = "F".charCodeAt(FIRST_CHARACTER_INDEX);
15
+ const LOWERCASE_A_CODE = "a".charCodeAt(FIRST_CHARACTER_INDEX);
16
+ const LOWERCASE_F_CODE = "f".charCodeAt(FIRST_CHARACTER_INDEX);
17
+ function isHexCode(charCode) {
18
+ return charCode >= ZERO_CODE && charCode <= NINE_CODE || charCode >= UPPERCASE_A_CODE && charCode <= UPPERCASE_F_CODE || charCode >= LOWERCASE_A_CODE && charCode <= LOWERCASE_F_CODE;
19
+ }
20
+ function isGuidString(key) {
21
+ if (key.length !== GUID_LENGTH) return false;
22
+ if (key.charCodeAt(GUID_SEPARATOR_ONE_INDEX) !== GUID_SEPARATOR_CODE || key.charCodeAt(GUID_SEPARATOR_TWO_INDEX) !== GUID_SEPARATOR_CODE || key.charCodeAt(GUID_SEPARATOR_THREE_INDEX) !== GUID_SEPARATOR_CODE || key.charCodeAt(GUID_SEPARATOR_FOUR_INDEX) !== GUID_SEPARATOR_CODE) return false;
23
+ for (let index = 0; index < key.length; index += 1) if (!(index === GUID_SEPARATOR_ONE_INDEX || index === GUID_SEPARATOR_TWO_INDEX || index === GUID_SEPARATOR_THREE_INDEX || index === GUID_SEPARATOR_FOUR_INDEX) && !isHexCode(key.charCodeAt(index))) return false;
24
+ return true;
25
+ }
26
+ function shouldConvertKey(key, options) {
27
+ if (isGuidString(key)) return false;
28
+ return options?.shouldConvert?.(key) !== false;
29
+ }
30
+ function keysToCamelCase(obj, options) {
31
+ if (Array.isArray(obj)) return obj.map((value) => keysToCamelCase(value, options));
6
32
  if (obj === null || typeof obj !== "object") return obj;
7
33
  const result = {};
8
34
  for (const [key, value] of Object.entries(obj)) {
9
- const camelKey = toCamelCase(key);
10
- result[camelKey] = keysToCamelCase(value);
35
+ const camelKey = shouldConvertKey(key, options) ? toCamelCase(key) : key;
36
+ result[camelKey] = keysToCamelCase(value, options);
11
37
  }
12
38
  return result;
13
39
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pixpilot/object",
3
3
  "type": "module",
4
- "version": "2.3.0",
4
+ "version": "2.4.0",
5
5
  "description": "A collection of utility functions for object manipulation and transformation.",
6
6
  "author": "Pixpilot <m.doaie@hotmail.com>",
7
7
  "license": "MIT",
@@ -35,11 +35,11 @@
35
35
  "eslint": "^9.37.0",
36
36
  "tsdown": "^0.15.8",
37
37
  "typescript": "^5.9.3",
38
+ "@internal/eslint-config": "0.3.0",
38
39
  "@internal/prettier-config": "0.0.1",
39
40
  "@internal/tsconfig": "0.1.0",
40
- "@internal/eslint-config": "0.3.0",
41
- "@internal/tsdown-config": "0.1.0",
42
- "@internal/vitest-config": "0.1.0"
41
+ "@internal/vitest-config": "0.1.0",
42
+ "@internal/tsdown-config": "0.1.0"
43
43
  },
44
44
  "prettier": "@internal/prettier-config",
45
45
  "scripts": {