@helpers4/object 3.1.3 → 3.1.4
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/lib/index.d.ts +2 -2
- package/lib/index.js.map +1 -1
- package/llms.txt +3 -3
- package/meta/api.json +5 -5
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -724,7 +724,7 @@ declare function mergeDeep<T extends [object, ...object[]]>(...sources: [...T]):
|
|
|
724
724
|
* // => { a: 1, c: 3 }
|
|
725
725
|
* @since 2.0.0
|
|
726
726
|
*/
|
|
727
|
-
declare function omit<T extends
|
|
727
|
+
declare function omit<T extends object, K extends keyof T>(obj: T, keys: readonly K[]): Omit<T, K>;
|
|
728
728
|
declare function omit(obj: undefined, keys: readonly string[]): undefined;
|
|
729
729
|
declare function omit(obj: null, keys: readonly string[]): null;
|
|
730
730
|
|
|
@@ -820,7 +820,7 @@ declare function pascalCaseKeys<T>(value: T): T;
|
|
|
820
820
|
* // => { a: 1, c: 3 }
|
|
821
821
|
* @since 2.0.0
|
|
822
822
|
*/
|
|
823
|
-
declare function pick<T extends
|
|
823
|
+
declare function pick<T extends object, K extends keyof T>(obj: T, keys: readonly K[]): Pick<T, K>;
|
|
824
824
|
declare function pick(obj: undefined, keys: readonly string[]): undefined;
|
|
825
825
|
declare function pick(obj: null, keys: readonly string[]): null;
|
|
826
826
|
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["equalsDeep","compareDate","arrayDeepEquals"],"sources":["../../../helpers/string/camelCase.ts","../../../helpers/_shared/_unsafeKeys.ts","../../../helpers/guard/isPlainObject.ts","../../../helpers/object/mapDeep.ts","../../../helpers/object/camelCaseKeys.ts","../../../helpers/object/clone.ts","../../../helpers/object/cloneDeep.ts","../../../helpers/object/compact.ts","../../../helpers/array/equalsDeep.ts","../../../helpers/date/timestamp.ts","../../../helpers/date/ensureDate.ts","../../../helpers/date/compare.ts","../../../helpers/guard/isSpecialObject.ts","../../../helpers/object/diff.ts","../../../helpers/object/equalsDeep.ts","../../../helpers/object/equalsShallow.ts","../../../helpers/object/flatten.ts","../../../helpers/_shared/_walkPropertyPath.ts","../../../helpers/object/parsePropertyPath.ts","../../../helpers/object/get.ts","../../../helpers/object/groupBy.ts","../../../helpers/object/invert.ts","../../../helpers/object/isEmpty.ts","../../../helpers/object/isNonEmpty.ts","../../../helpers/string/kebabCase.ts","../../../helpers/object/kebabCaseKeys.ts","../../../helpers/object/map.ts","../../../helpers/object/mergeDeep.ts","../../../helpers/object/omit.ts","../../../helpers/object/omitBy.ts","../../../helpers/string/pascalCase.ts","../../../helpers/object/pascalCaseKeys.ts","../../../helpers/object/pick.ts","../../../helpers/object/pickBy.ts","../../../helpers/guard/isNullish.ts","../../../helpers/object/removeUndefinedNull.ts","../../../helpers/json/parseStrict.ts","../../../helpers/json/safeParseStrict.ts","../../../helpers/object/safeJsonParse.ts","../../../helpers/object/set.ts","../../../helpers/string/snakeCase.ts","../../../helpers/object/snakeCaseKeys.ts","../../../helpers/object/sortKeys.ts","../../../helpers/string/titleCase.ts","../../../helpers/object/titleCaseKeys.ts","../../../helpers/object/unflatten.ts","../../../helpers/object/unset.ts","../../../helpers/object/update.ts"],"sourcesContent":["/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Converts a string to camelCase.\n * Handles PascalCase, kebab-case, snake_case, spaces, and mixed formats.\n *\n * An embedded run of capitals is treated as an acronym boundary: only its last letter starts\n * the next word, the rest are lowercased (matching lodash's `camelCase` convention) — so an\n * already-camelCase identifier containing an acronym is not left untouched.\n * @param str - The string to convert\n * @returns String in camelCase\n * @example\n * camelCase('hello-world')\n * // => 'helloWorld'\n * camelCase('user_name')\n * // => 'userName'\n * camelCase('userID')\n * // => 'userId' (acronym boundary, not left as-is)\n * @since 1.9.0\n */\nexport function camelCase(str: string): string;\nexport function camelCase(str: undefined): undefined;\nexport function camelCase(str: null): null;\nexport function camelCase(str: string | undefined | null): string | undefined | null {\n if (str === undefined || str === null) return str;\n const words = str\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/([A-Z])([A-Z][a-z])/g, '$1 $2')\n .split(/[\\s_-]+/)\n .filter(Boolean);\n if (words.length === 0) return '';\n return (\n words[0]!.toLowerCase() +\n words\n .slice(1)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('')\n );\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Keys that must never be set on a plain object (prototype-pollution guard).\n * @ignore\n */\nconst UNSAFE_KEY_LIST = ['__proto__', 'constructor', 'prototype'] as const;\n\n/** @ignore */\nexport type UnsafeKey = (typeof UNSAFE_KEY_LIST)[number];\n\nexport const UNSAFE_KEYS = /* @__PURE__ */ new Set<string>(UNSAFE_KEY_LIST);\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is a plain object.\n *\n * A plain object is created by `{}`, `new Object()`, or `Object.create(null)`.\n * Returns `false` for arrays, Date, Map, Set, RegExp, class instances, etc.\n *\n * @param value - The value to check\n * @returns True if value is a plain object\n * @example\n * isPlainObject({}) // => true\n * isPlainObject({ a: 1 }) // => true\n * isPlainObject(new Date()) // => false\n * isPlainObject([]) // => false\n * isPlainObject(null) // => false\n * @since 2.0.0\n */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object') return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\nimport { isPlainObject } from '../guard/isPlainObject.js';\n\nfunction transform(\n value: unknown,\n mapValue?: (value: unknown, key: string) => unknown,\n mapKey?: (key: string, value: unknown) => PropertyKey,\n): unknown {\n if (Array.isArray(value))\n return value.map((item, index) => {\n const recursed = transform(item, mapValue, mapKey);\n return mapValue ? mapValue(recursed, String(index)) : recursed;\n });\n if (isPlainObject(value)) {\n const result: Record<PropertyKey, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n const newKey = mapKey ? mapKey(key, val) : key;\n if (typeof newKey === 'string' && UNSAFE_KEYS.has(newKey)) continue;\n const recursed = transform(val, mapValue, mapKey);\n result[newKey] = mapValue ? mapValue(recursed, key) : recursed;\n }\n return result;\n }\n return value;\n}\n\n/**\n * Recursively transforms the keys and/or values of a plain object — the deep counterpart to\n * {@link map}, which only transforms the top level. Descends into nested plain objects and\n * arrays of them; `Date`, `Map`, `Set`, class instances, and primitives are left untouched\n * (only their position is walked into, matching {@link cloneDeep}'s notion of what counts\n * as a plain-data node worth recursing into).\n *\n * Both callbacks are optional and default to identity (no transformation). `mapKey` is called\n * with the *original* key and value (before any recursive value transform); `mapValue` receives\n * the already-recursed value. Entries whose mapped key is a prototype-polluting string\n * (`__proto__`, `constructor`, `prototype`) are silently skipped, same as {@link map}.\n *\n * Array elements also go through `mapValue` (with their stringified index as `key`, since\n * arrays have no property keys of their own) — so values inside a plain array, not just object\n * properties, get transformed too. `mapKey` is never called for array elements, since there is\n * no key to rename.\n *\n * @param obj - The value to transform (typically an object, or an array of objects)\n * @param mapValue - Callback called with `(value, key)` for each entry's (already-recursed) value.\n * For array elements, `key` is the element's index as a string. Defaults to identity.\n * @param mapKey - Callback called with `(key, value)` for each object entry. Defaults to identity.\n * @returns A new value with every plain-object key/value transformed\n * @example\n * mapDeep({ a: { b: 1 } }, v => (typeof v === 'number' ? v * 10 : v))\n * // => { a: { b: 10 } }\n * @example\n * mapDeep({ user_name: 'Alice' }, undefined, key => key.toUpperCase())\n * // => { USER_NAME: 'Alice' }\n * @example\n * mapDeep({ tags: [1, 2, 3] }, v => (typeof v === 'number' ? v * 10 : v))\n * // => { tags: [10, 20, 30] }\n * @since 3.0.3\n */\nexport function mapDeep<T>(\n obj: T,\n mapValue?: (value: unknown, key: string) => unknown,\n mapKey?: (key: string, value: unknown) => PropertyKey,\n): T {\n return transform(obj, mapValue, mapKey) as T;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { camelCase } from '../string/camelCase.js';\nimport { mapDeep } from './mapDeep.js';\n\n/**\n * Recursively transforms every key of a plain object (including keys nested inside arrays and\n * nested objects) to camelCase. Handles snake_case, kebab-case, PascalCase, and space-separated\n * keys. Non-plain-object values (arrays' items aside) — `Date`, `Map`, `Set`, class instances,\n * primitives — are left untouched, only their position is walked into. An entry whose\n * transformed key is a prototype-polluting string (`__proto__`, `constructor`, `prototype`) is\n * silently skipped, same as the rest of `@helpers4/object`.\n * @param value - The object (or array of objects) to transform\n * @returns A new value with every plain-object key converted to camelCase\n * @example\n * camelCaseKeys({ user_name: 'Alice', home_address: { zip_code: '12345' } })\n * // => { userName: 'Alice', homeAddress: { zipCode: '12345' } }\n * @since 3.0.3\n */\nexport function camelCaseKeys<T>(value: T): T {\n return mapDeep(value, undefined, camelCase);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Creates a shallow copy of a value — one level deep, unlike {@link cloneDeep}.\n *\n * Unlike a plain `{ ...value }` spread, this correctly reconstructs `Date`,\n * `Map`, `Set`, and arrays instead of producing an empty (or wrong-shaped)\n * plain object for them. Primitives are returned as-is. Any other object\n * (including class instances not listed above) has its own enumerable string\n * keys shallow-copied into a plain object — the same fallback `cloneDeep`\n * uses, so the two stay consistent for types neither one special-cases.\n *\n * @param value - The value to shallow-clone\n * @returns A shallow copy of `value`\n * @example\n * clone({ a: { b: 1 } })\n * // => { a: { b: 1 } } — new object, but `a` is the *same* nested reference\n * @example\n * clone(new Date('2024-01-01')) // => new Date with the same timestamp\n * clone(new Map([['a', 1]])) // => new Map with the same entries\n * clone([1, 2, 3]) // => new array, same elements\n * @since 3.0.0\n */\nexport function clone<T>(value: T): T {\n if (value === null || typeof value !== 'object') return value;\n if (value instanceof Date) return new Date(value.getTime()) as T;\n if (value instanceof Map) return new Map(value) as T;\n if (value instanceof Set) return new Set(value) as T;\n if (Array.isArray(value)) return [...value] as T;\n\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(value)) {\n if (!UNSAFE_KEYS.has(key)) {\n result[key] = (value as Record<string, unknown>)[key];\n }\n }\n return result as T;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Creates a deep copy of an object or array.\n *\n * Recursively clones own enumerable string keys. `Date` instances are\n * reconstructed with the same epoch value. Prototype-polluting keys\n * (`__proto__`, `constructor`, `prototype`) are silently skipped.\n * Does **not** handle circular references.\n *\n * **Limitation:** symbol-keyed own properties are **not** copied — only string\n * keys are processed. Use `structuredClone` if symbol propagation is required.\n *\n * @param obj - The value to clone\n * @returns A deep copy of `obj`\n * @example\n * cloneDeep({ a: { b: [1, 2] } })\n * // => { a: { b: [1, 2] } } — fully independent copy\n *\n * cloneDeep(new Date('2024-01-01'))\n * // => Date with the same timestamp\n *\n * // Primitives pass through unchanged\n * cloneDeep(42) // => 42\n * cloneDeep(null) // => null\n * @since 1.9.0\n */\nexport function cloneDeep<T>(obj: T): T {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (obj instanceof Date) {\n return new Date(obj.getTime()) as T;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(item => cloneDeep(item)) as T;\n }\n\n const cloned = {} as T;\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key) && !UNSAFE_KEYS.has(key)) {\n cloned[key] = cloneDeep(obj[key]);\n }\n }\n\n return cloned;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Removes all entries with falsy values (`false`, `null`, `undefined`, `0`, `\"\"`, `NaN`) from an object.\n * Own keys that are prototype-polluting strings (`__proto__`, `constructor`, `prototype`) are\n * silently skipped.\n * @param obj - The source object\n * @returns A new object containing only entries with truthy values\n * @example\n * compact({ a: 1, b: null, c: '', d: 0, e: 'hello' })\n * // => { a: 1, e: 'hello' }\n * @since 2.0.0\n */\nexport function compact<T extends Record<string, unknown>>(obj: T): Partial<T>;\nexport function compact(obj: undefined): undefined;\nexport function compact(obj: null): null;\nexport function compact<T extends Record<string, unknown>>(obj: T | undefined | null): Partial<T> | undefined | null {\n if (obj === undefined || obj === null) return obj;\n const result: Partial<T> = {};\n for (const key of Object.keys(obj) as (keyof T)[]) {\n if (UNSAFE_KEYS.has(key as string)) continue;\n if (obj[key]) {\n result[key] = obj[key];\n }\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { isPlainObject } from '../guard/isPlainObject';\n\n/**\n * Recursive structural array equality.\n *\n * Two arrays are equal when they have the same length and each pair of\n * elements at the same index is structurally equal:\n * - Arrays recurse with `equalsDeep`.\n * - Plain objects recurse key-by-key with structural comparison.\n * - `Date` instances are compared by their epoch value.\n * - All other values use strict equality (`===`), which means `NaN !== NaN`\n * and special objects (Map, Set, RegExp, Promise, class instances\\u2026) are\n * compared by reference.\n *\n * For positional one-level comparison use {@link equalsShallow}. For\n * order-independent comparison use {@link equalsUnordered}.\n *\n * @param arrA - First array to compare\n * @param arrB - Second array to compare\n * @returns `true` if arrays are deeply equal, `false` otherwise.\n * @since 2.0.0\n */\nexport function equalsDeep<T>(arrA: readonly T[], arrB: readonly T[]): boolean {\n if (arrA === arrB) {\n return true;\n }\n if (!Array.isArray(arrA) || !Array.isArray(arrB)) {\n return false;\n }\n if (arrA.length !== arrB.length) {\n return false;\n }\n for (let i = 0; i < arrA.length; i++) {\n if (!valuesEqual(arrA[i], arrB[i])) {\n return false;\n }\n }\n return true;\n}\n\nfunction valuesEqual(a: unknown, b: unknown): boolean {\n if (a === b) {\n return true;\n }\n if (Array.isArray(a) && Array.isArray(b)) {\n return equalsDeep(a, b);\n }\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() === b.getTime();\n }\n if (isPlainObject(a) && isPlainObject(b)) {\n const ao = a as Record<string, unknown>;\n const bo = b as Record<string, unknown>;\n const keysA = Object.keys(ao);\n if (keysA.length !== Object.keys(bo).length) {\n return false;\n }\n for (const key of keysA) {\n if (!Object.prototype.hasOwnProperty.call(bo, key)) {\n return false;\n }\n if (!valuesEqual(ao[key], bo[key])) {\n return false;\n }\n }\n return true;\n }\n return false;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { ensureDate } from './ensureDate';\nimport type { DateLike } from './types';\n\n/**\n * Checks if a timestamp is likely in seconds (Java/Unix style) vs milliseconds (JavaScript style)\n * @param timestamp - The timestamp to check\n * @returns True if timestamp appears to be in seconds\n * @since 1.9.0\n */\nexport function isTimestampInSeconds(timestamp: number): boolean {\n // Timestamps before year 2001 in milliseconds are less than 10^10\n // Use Math.abs to correctly handle negative timestamps (before epoch)\n return Math.abs(timestamp) < 10000000000;\n}\n\n/**\n * Converts a timestamp to JavaScript milliseconds format\n * @param timestamp - The timestamp (in seconds or milliseconds)\n * @returns Timestamp in milliseconds\n * @since 1.9.0\n */\nexport function normalizeTimestamp(timestamp: number): number {\n return isTimestampInSeconds(timestamp) ? timestamp * 1000 : timestamp;\n}\n\n/**\n * Converts a date to a timestamp in **seconds** (epoch seconds).\n *\n * Use this when sending a date to a backend API that expects seconds\n * (e.g. Java `Instant.getEpochSecond()`, Python `time.time()`).\n *\n * @param date - The date to convert\n * @returns Seconds since the Unix epoch, or `null` for invalid input\n * @example\n * toSeconds('2025-01-19T12:00:00Z') // => 1737288000\n * toSeconds(null) // => null\n *\n * @since 2.0.0\n */\nexport function toSeconds(date: DateLike): number | null {\n const d = ensureDate(date);\n if (!d) return null;\n return Math.floor(d.getTime() / 1000);\n}\n\n/**\n * Converts a date to a timestamp in **milliseconds** (epoch millis).\n *\n * Use this when you need a plain number from a `DateLike` value\n * (e.g. for `Date.now()` comparisons, localStorage, or JS-native APIs).\n *\n * @param date - The date to convert\n * @returns Milliseconds since the Unix epoch, or `null` for invalid input\n * @example\n * toMillis('2025-01-19T12:00:00Z') // => 1737288000000\n * toMillis(null) // => null\n *\n * @since 2.0.0\n */\nexport function toMillis(date: DateLike): number | null {\n const d = ensureDate(date);\n if (!d) return null;\n return d.getTime();\n}\n\n/**\n * Creates a `Date` from a timestamp in **seconds**.\n *\n * Use this when receiving a timestamp from a backend that sends seconds\n * (e.g. Java `Instant.getEpochSecond()`). No heuristic — the input is\n * always treated as seconds.\n *\n * @param seconds - Seconds since the Unix epoch\n * @returns A valid `Date`, or `null` for `NaN` / non-finite input\n * @example\n * fromSeconds(1737288000) // => Date('2025-01-19T12:00:00Z')\n * fromSeconds(0) // => Date('1970-01-01T00:00:00Z')\n * fromSeconds(NaN) // => null\n *\n * @since 2.0.0\n */\nexport function fromSeconds(seconds: number): Date | null {\n if (!Number.isFinite(seconds)) return null;\n return new Date(seconds * 1000);\n}\n\n/**\n * Creates a `Date` from a timestamp in **milliseconds**.\n *\n * Use this when receiving a timestamp from a JS-native source\n * (e.g. `Date.now()`, `performance.timeOrigin`). No heuristic — the\n * input is always treated as milliseconds.\n *\n * @param ms - Milliseconds since the Unix epoch\n * @returns A valid `Date`, or `null` for `NaN` / non-finite input\n * @example\n * fromMillis(1737288000000) // => Date('2025-01-19T12:00:00Z')\n * fromMillis(0) // => Date('1970-01-01T00:00:00Z')\n * fromMillis(NaN) // => null\n *\n * @since 2.0.0\n */\nexport function fromMillis(ms: number): Date | null {\n if (!Number.isFinite(ms)) return null;\n return new Date(ms);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { normalizeTimestamp } from './timestamp';\nimport type { DateLike } from './types';\n\n/**\n * Type guard that checks whether a value is a `Temporal.Instant` or\n * `Temporal.ZonedDateTime`.\n *\n * Duck-types the `epochMilliseconds` property rather than using `instanceof`,\n * so values crossing a realm boundary (vm context, worker, iframe) are still\n * recognized correctly.\n */\nfunction isEpochMillisecondsLike(value: unknown): value is Temporal.Instant | Temporal.ZonedDateTime {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'epochMilliseconds' in value &&\n typeof value.epochMilliseconds === 'number'\n );\n}\n\n/**\n * Safely converts a date-like value to a valid `Date` object, or returns `null`.\n *\n * Accepts `Date`, timestamps (seconds or milliseconds, auto-detected), date strings,\n * and objects with an `epochMilliseconds` property (e.g. `Temporal.Instant`,\n * `Temporal.ZonedDateTime`).\n * Returns `null` for `null`, `undefined`, empty strings, `0`, and any value that\n * produces an invalid `Date`.\n *\n * This is the date equivalent of {@link ensureArray} — it normalizes flexible\n * input into a guaranteed type (or a safe fallback).\n *\n * @param input - A date-like value to convert\n * @returns A valid `Date` object, or `null` if the input is invalid\n * @example\n * ensureDate('2025-01-19T12:00:00Z') // => Date\n * ensureDate(1737290400) // => Date (from Unix seconds)\n * ensureDate(1737290400000) // => Date (from milliseconds)\n * ensureDate(new Date()) // => Date (same reference)\n * ensureDate(null) // => null\n * ensureDate('invalid') // => null\n *\n * @see {@link DateLike} for the accepted input types\n * @since 2.0.0\n */\nexport function ensureDate(input: DateLike | null | undefined): Date | null {\n if (input === null || input === undefined || input === '' || input === 0) {\n return null;\n }\n\n if (input instanceof Date) {\n return isNaN(input.getTime()) ? null : input;\n }\n\n if (isEpochMillisecondsLike(input)) {\n const date = new Date(input.epochMilliseconds);\n return isNaN(date.getTime()) ? null : date;\n }\n\n if (typeof input === 'number') {\n const normalized = normalizeTimestamp(input);\n const date = new Date(normalized);\n return isNaN(date.getTime()) ? null : date;\n }\n\n if (typeof input === 'string') {\n const date = new Date(input);\n return isNaN(date.getTime()) ? null : date;\n }\n\n return null;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { ensureDate } from './ensureDate';\nimport type { DateLike } from './types';\n\n/**\n * Options for date comparison\n * @since 2.0.0\n */\nexport interface DateCompareOptions {\n /**\n * Comparison precision\n * - 'milliseconds': Compare all including milliseconds (default)\n * - 'seconds': Ignore milliseconds, compare to the second\n * - 'minutes': Ignore seconds and milliseconds, compare to the minute\n * - 'hours': Ignore minutes, seconds and milliseconds, compare to the hour\n * - 'days': Compare only the date part (ignore time completely)\n * - 'months': Compare only year and month\n * - 'years': Compare only year\n */\n precision?: 'milliseconds' | 'seconds' | 'minutes' | 'hours' | 'days' | 'months' | 'years';\n}\n\n/**\n * Comparison of two dates.\n *\n * Accepts any {@link DateLike} input (Date, timestamp, or date string).\n *\n * @param dateA - First date to compare\n * @param dateB - Second date to compare\n * @param options - Comparison options\n * @returns `true` if dates are identical according to the specified precision, `false` otherwise\n * @example\n * compare('2025-01-19', new Date('2025-01-19T08:00:00Z'), { precision: 'days' })\n * // => true\n * @since 2.0.0\n */\nexport function compare(dateA: DateLike, dateB: DateLike, options: DateCompareOptions = {}): boolean {\n const { precision = 'milliseconds' } = options;\n\n const a = ensureDate(dateA);\n const b = ensureDate(dateB);\n\n // Any invalid → not equal\n if (a === null || b === null) {\n return false;\n }\n\n switch (precision) {\n case 'years':\n return a.getFullYear() === b.getFullYear();\n\n case 'months':\n return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();\n\n case 'days':\n return a.toDateString() === b.toDateString();\n\n case 'hours': {\n const hoursA = Math.floor(a.getTime() / (1000 * 60 * 60));\n const hoursB = Math.floor(b.getTime() / (1000 * 60 * 60));\n return hoursA === hoursB;\n }\n\n case 'minutes': {\n const minutesA = Math.floor(a.getTime() / (1000 * 60));\n const minutesB = Math.floor(b.getTime() / (1000 * 60));\n return minutesA === minutesB;\n }\n\n case 'seconds': {\n const secondsA = Math.floor(a.getTime() / 1000);\n const secondsB = Math.floor(b.getTime() / 1000);\n return secondsA === secondsB;\n }\n\n case 'milliseconds':\n default:\n return a.getTime() === b.getTime();\n }\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Determines if a value is a special object that should not have its properties compared deeply.\n * Special objects include: Date, Function, Promise, Observable, RegExp, Error, Map, Set, WeakMap, WeakSet, etc.\n * \n * @param value - The value to check\n * @returns `true` if the value is a special object, `false` otherwise\n * @since 2.0.0\n */\nexport function isSpecialObject(value: unknown): boolean {\n if (value === null || value === undefined) {\n return false;\n }\n\n // Functions are special objects\n if (typeof value === 'function') {\n return true;\n }\n\n // Non-objects are not special\n if (typeof value !== 'object') {\n return false;\n }\n\n // Arrays are not considered special objects for our purposes\n if (Array.isArray(value)) {\n return false;\n }\n\n // Check for built-in special objects\n if (\n value instanceof Date ||\n value instanceof Promise ||\n value instanceof RegExp ||\n value instanceof Error ||\n value instanceof Map ||\n value instanceof Set ||\n value instanceof WeakMap ||\n value instanceof WeakSet ||\n value instanceof ArrayBuffer ||\n value instanceof DataView\n ) {\n return true;\n }\n\n // Check for Observable (RxJS or similar)\n if (value.constructor?.name === 'Observable') {\n return true;\n }\n\n // Check for DOM elements (if in browser environment)\n if (typeof HTMLElement !== 'undefined' && value instanceof HTMLElement) {\n return true;\n }\n\n // Check for other built-in types by constructor name\n const constructorName = value.constructor?.name;\n if (constructorName && [\n 'Buffer', // Node.js Buffer\n 'URL', // Web URL API\n 'URLSearchParams',\n 'File', // Web File API\n 'Blob', // Web Blob API\n 'FormData', // Web FormData API\n 'Headers', // Web Headers API\n 'Request', // Web Request API\n 'Response', // Web Response API\n 'EventTarget', // Web EventTarget API\n 'Symbol' // Symbol objects\n ].includes(constructorName)) {\n return true;\n }\n\n return false;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { equalsDeep as arrayDeepEquals } from '../array/equalsDeep';\nimport { compare as compareDate } from '../date/compare';\nimport { isSpecialObject } from '../guard/isSpecialObject';\n\n/**\n * Per-key diff result. Each entry tells what differs between the two\n * objects:\n * - `\"onlyA\"` \\u2014 the key exists only on the first input.\n * - `\"onlyB\"` \\u2014 the key exists only on the second input.\n * - `false` \\u2014 both inputs have the key but the values differ.\n * - nested `DiffResult` \\u2014 plain-object values that differ deeper.\n *\n * @since 2.0.0\n */\nexport interface DiffResult {\n [key: string]: 'onlyA' | 'onlyB' | false | DiffResult;\n}\n\n/**\n * Options for {@link diff}.\n * @since 2.0.0\n */\nexport interface DiffOptions {\n /**\n * Maximum recursion depth for nested plain objects. Defaults to\n * `Infinity` (full structural diff).\n *\n * - `0` compares values at the top-level only with strict equality.\n * - `1` compares the first level of nested objects with strict equality.\n * - `Infinity` recurses through every plain-object level.\n *\n * Arrays, `Date` and special objects (Map, Set, RegExp\\u2026) are always\n * leaf-compared (via {@link arrayDeepEquals}, epoch comparison, or\n * reference equality respectively) regardless of `depth`.\n */\n depth?: number;\n}\n\n/**\n * Structural object diff.\n *\n * Returns `true` when both inputs are deeply equal, otherwise a\n * {@link DiffResult} describing the differences key by key.\n *\n * Comparison rules:\n * - Same reference \\u2192 `true`.\n * - Either side is `null`/`undefined` (and not both) \\u2192 `false`.\n * - Both `Date` \\u2192 epoch comparison.\n * - Both arrays \\u2192 compared with `array/equalsDeep` (leaf, no diff drill-down).\n * - Special objects (Map, Set, RegExp, Promise, class instances\\u2026) \\u2192 reference equality.\n * - Plain objects \\u2192 key-by-key, recursing up to `options.depth` levels.\n * - Mixed types (e.g. array vs object, Date vs object) \\u2192 `false`.\n *\n * For a boolean wrapper see {@link equalsDeep} from this category.\n * For a one-level boolean check see {@link equalsShallow} from this category.\n *\n * @param objA - First value (object, `null`, or `undefined`).\n * @param objB - Second value (object, `null`, or `undefined`).\n * @param options - See {@link DiffOptions}.\n * @returns `true` when equal, otherwise a {@link DiffResult}, or `false` for incompatible types.\n * @since 2.0.0\n */\nexport function diff(\n objA: object | undefined | null,\n objB: object | undefined | null,\n options: DiffOptions = {},\n): true | false | DiffResult {\n const depth = options.depth ?? Infinity;\n\n // Quick reference equality check\n if (objA === objB) {\n return true;\n }\n\n // Handle null/undefined cases\n if (objA == null || objB == null) {\n return false;\n }\n\n // Handle Date objects\n if (objA instanceof Date && objB instanceof Date) {\n return compareDate(objA, objB);\n }\n\n // Handle Arrays at root level\n if (Array.isArray(objA) && Array.isArray(objB)) {\n return arrayDeepEquals(objA, objB);\n }\n if (Array.isArray(objA) || Array.isArray(objB)) {\n return false;\n }\n\n // Handle special objects - compare by reference only\n if (isSpecialObject(objA) || isSpecialObject(objB)) {\n return objA === objB;\n }\n\n // Plain object detailed comparison\n return diffPlainObjects(objA, objB, depth);\n}\n\nfunction diffPlainObjects(\n objA: object,\n objB: object,\n depth: number,\n): true | DiffResult {\n const keys = Array.from(new Set([...Object.keys(objA), ...Object.keys(objB)]));\n const differences: DiffResult = Object.create(null) as DiffResult;\n\n for (const key of keys) {\n const hasA = Object.prototype.hasOwnProperty.call(objA, key);\n const hasB = Object.prototype.hasOwnProperty.call(objB, key);\n\n if (!hasA && hasB) {\n differences[key] = 'onlyB';\n continue;\n }\n if (hasA && !hasB) {\n differences[key] = 'onlyA';\n continue;\n }\n\n const valueA = (objA as Record<string, unknown>)[key];\n const valueB = (objB as Record<string, unknown>)[key];\n\n if (valueA === valueB) {\n continue;\n }\n\n if (Array.isArray(valueA) && Array.isArray(valueB)) {\n if (!arrayDeepEquals(valueA, valueB)) {\n differences[key] = false;\n }\n continue;\n }\n if (Array.isArray(valueA) || Array.isArray(valueB)) {\n differences[key] = false;\n continue;\n }\n\n if (valueA instanceof Date && valueB instanceof Date) {\n if (!compareDate(valueA, valueB)) {\n differences[key] = false;\n }\n continue;\n }\n if (valueA instanceof Date || valueB instanceof Date) {\n differences[key] = false;\n continue;\n }\n\n if (isSpecialObject(valueA) || isSpecialObject(valueB)) {\n // valueA === valueB already handled above, so any special-object pair\n // that reaches here must differ.\n differences[key] = false;\n continue;\n }\n\n const bothPlainObjects =\n valueA !== null && valueB !== null &&\n typeof valueA === 'object' && typeof valueB === 'object';\n\n if (!bothPlainObjects) {\n differences[key] = false;\n continue;\n }\n\n if (depth <= 0) {\n // depth budget exhausted \\u2192 strict-equal nested objects only match by reference\n differences[key] = false;\n continue;\n }\n\n const nested = diffPlainObjects(valueA as object, valueB as object, depth - 1);\n if (nested !== true) {\n differences[key] = nested;\n }\n }\n\n return Object.keys(differences).length > 0 ? differences : true;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { diff } from './diff';\n\n/**\n * Recursive structural object equality.\n *\n * Boolean wrapper around {@link diff} \\u2014 returns `true` when the two values\n * are deeply equal according to the same rules. Use this when you only\n * need a yes/no answer; use {@link diff} when you also need to know\n * *what* differs.\n *\n * For a one-level boolean check use {@link equalsShallow}.\n *\n * @param objA - First value (object, `null`, or `undefined`).\n * @param objB - Second value (object, `null`, or `undefined`).\n * @returns `true` if both inputs are deeply equal, `false` otherwise.\n * @since 2.0.0\n */\nexport function equalsDeep(\n objA: object | undefined | null,\n objB: object | undefined | null,\n): boolean {\n return diff(objA, objB) === true;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * One-level (shallow) object equality.\n *\n * Two objects are equal when they share the exact same set of own\n * enumerable string keys and each pair of values satisfies strict equality\n * (`===`). No recursion: nested objects/arrays are compared by reference.\n *\n * Falls back to strict equality when either input is `null`, `undefined`\n * or not an object \\u2014 so primitives match if and only if they are `===`.\n * Arrays are not supported; they always return `false` (unless identical\n * references). Use `array/equalsShallow` instead.\n *\n * For recursive structural comparison use {@link equalsDeep}. For a diff\n * structure use {@link diff}.\n *\n * @param objA - First value to compare\n * @param objB - Second value to compare\n * @returns `true` if values are shallowly equal, `false` otherwise.\n * @since 2.0.0\n */\nexport function equalsShallow(objA: unknown, objB: unknown): boolean {\n if (objA === objB) {\n return true;\n }\n if (\n objA === null || objB === null ||\n typeof objA !== 'object' || typeof objB !== 'object'\n ) {\n return false;\n }\n const a = objA as Record<string, unknown>;\n const b = objB as Record<string, unknown>;\n if (Array.isArray(objA) || Array.isArray(objB)) {\n return false;\n }\n const keysA = Object.keys(a);\n if (keysA.length !== Object.keys(b).length) {\n return false;\n }\n for (const key of keysA) {\n if (!Object.prototype.hasOwnProperty.call(b, key) || a[key] !== b[key]) {\n return false;\n }\n }\n return true;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { isPlainObject } from '../guard/isPlainObject.js';\n\nfunction flattenInto(obj: Record<string, unknown>, prefix: string, result: Record<string, unknown>): void {\n for (const [key, value] of Object.entries(obj)) {\n const path = prefix ? `${prefix}.${key}` : key;\n if (isPlainObject(value) && Object.keys(value).length > 0) {\n flattenInto(value, path, result);\n } else {\n result[path] = value;\n }\n }\n}\n\n/**\n * Flattens a nested object into a single-level object whose keys are the\n * dot-notation path to each leaf value. The inverse of {@link unflatten}.\n *\n * Only **plain objects** are recursed into — arrays, `Date`, `Map`, `RegExp`,\n * class instances, and empty plain objects `{}` are kept as opaque leaf\n * values. This keeps `flatten`/`unflatten` a clean, invertible pair: arrays\n * can't be losslessly told apart from plain objects once reduced to dotted\n * keys, so this implementation doesn't attempt it.\n *\n * Caveat shared by every dotted-path flattening scheme: a key that itself\n * contains a literal `.` is indistinguishable from real nesting once\n * flattened (`{ 'a.b': 1 }` and `{ a: { b: 1 } }` both produce `{ 'a.b': 1 }`).\n *\n * @param obj - The object to flatten\n * @returns A single-level object with dot-notation keys\n * @example\n * flatten({ a: { b: { c: 1 }, d: 2 } })\n * // => { 'a.b.c': 1, 'a.d': 2 }\n * @example\n * flatten({ a: [1, 2], b: new Date(0) })\n * // => { a: [1, 2], b: Date } (arrays and special objects stay as leaves)\n * @since 3.0.0\n */\nexport function flatten(obj: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n flattenInto(obj, '', result);\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Walks a value through a sequence of keys, returning the resolved value or `undefined` if any\n * step along the way is missing or not an object. Pure traversal only — string-path parsing\n * (`'a.b.c'` → keys) and default-value substitution are the caller's job.\n *\n * Shared by `object/get.ts` and any `*By`-style accessor elsewhere that needs the same\n * \"resolve a path against a value\" runtime behavior — kept dependency-free (per the `_shared/`\n * convention) so it can be used from any category without adding a cross-category import for\n * this specific piece.\n * @ignore\n */\nexport function walkPropertyPath(value: unknown, keys: readonly PropertyKey[]): unknown {\n let result = value;\n for (const key of keys) {\n if (result == null || typeof result !== 'object') {\n return undefined;\n }\n result = (result as Record<PropertyKey, unknown>)[key];\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n// `g` flag: stateful — callers must reset lastIndex before each use.\nconst BRACKET = /\\[(\\d+)\\]/g;\n\n// Cache parsed paths: real-world callers (get/set) tend to reuse a small, fixed\n// set of literal path strings repeatedly, so parsing the same string on every\n// call is pure waste. Capped so a caller who *does* build many distinct,\n// dynamic path strings can't grow this into an unbounded memory leak.\nconst MAX_CACHE_SIZE = 500;\nconst pathCache = /* @__PURE__ */ new Map<string, readonly (string | number)[]>();\n\n/**\n * Parses a dot/bracket-notation property path into an array of string/number\n * key segments — the same notation accepted by {@link get} and {@link set}.\n *\n * - Dot separators (`.`) split segments; each segment becomes a string key.\n * - Bracket indices (`[n]`) become number keys.\n * - A leading `.` is treated as \"current level\" and stripped before parsing,\n * so `.[0]` ≡ `[0]` and `.a.b` ≡ `a.b`.\n * - Empty string (or a bare `.`) returns `['']` (addresses the `''` key on the root object).\n * - Consecutive dots (`a..b`) produce an empty-string segment: `['a', '', 'b']`.\n *\n * Results are cached (up to 500 distinct path strings, oldest evicted first)\n * since real-world callers tend to reuse a small, fixed set of literal paths.\n *\n * @param path - The dot/bracket-notation path string to parse\n * @returns The parsed key segments\n * @throws {RangeError} When non-bracket text trails the last `]` within a\n * dot-segment (e.g. `'a[0]b'` is ambiguous — use `'a[0].b'` instead)\n * @example\n * parsePropertyPath('a.b.c') // => ['a', 'b', 'c']\n * parsePropertyPath('layers[1].x') // => ['layers', 1, 'x']\n * parsePropertyPath('.[0]') // => [0] (leading dot stripped)\n * parsePropertyPath('a..b') // => ['a', '', 'b'] (empty segment preserved)\n * @since 3.0.0\n */\nexport function parsePropertyPath(path: string): readonly (string | number)[] {\n const cached = pathCache.get(path);\n if (cached !== undefined) return cached;\n\n const result = Object.freeze(parseUncached(path));\n\n // MAX_CACHE_SIZE is a fixed positive constant, so size >= MAX_CACHE_SIZE always\n // implies the cache is non-empty — the iterator's first key is never undefined here.\n if (pathCache.size >= MAX_CACHE_SIZE) {\n pathCache.delete(pathCache.keys().next().value!);\n }\n pathCache.set(path, result);\n\n return result;\n}\n\nfunction parseUncached(path: string): (string | number)[] {\n if (path === '') return [''];\n if (path[0] === '.') path = path.slice(1);\n if (path === '') return [''];\n const result: (string | number)[] = [];\n // Split on `.` first so consecutive dots produce empty segments, then parse `[n]` within each.\n for (const dotSegment of path.split('.')) {\n BRACKET.lastIndex = 0;\n let last = 0;\n let match: RegExpExecArray | null;\n while ((match = BRACKET.exec(dotSegment)) !== null) {\n // String prefix before this [n] — omit only when the segment starts with '['.\n if (match.index > last) result.push(dotSegment.slice(last, match.index));\n result.push(parseInt(match[1], 10));\n last = BRACKET.lastIndex;\n }\n if (last === 0) {\n // No brackets found — push the whole dot-segment as a string key.\n result.push(dotSegment);\n } else if (last < dotSegment.length) {\n // Trailing non-bracket text after the last ']' (e.g. 'a[0]b') — ambiguous and\n // almost always a mistake. Throw rather than silently drop 'b'.\n throw new RangeError(\n `parsePropertyPath: non-bracket text '${dotSegment.slice(last)}' after ']' in segment '${dotSegment}' — use 'a[0].b' instead of 'a[0]b'`,\n );\n }\n // last === dotSegment.length: segment ended right after the last ']', nothing to push.\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { walkPropertyPath } from '../_shared/_walkPropertyPath.js';\nimport { parsePropertyPath } from './parsePropertyPath.js';\nimport type { DeepGet, ParsePath } from './_types.js';\n\n/**\n * Gets a value from an object using a dot/bracket-notated path or explicit key array.\n *\n * **Two path forms are supported:**\n *\n * 1. **String path** — dot notation (`'a.b.c'`) and bracket notation (`'layers[1].name'`)\n * are both accepted and mixed freely.\n * - Dot segments are always string keys: `'a.1'` → key `'1'` (string).\n * - Bracket segments are always number keys: `'a[1]'` → key `1` (number).\n * - String literal paths give **full compile-time type inference** on the return type.\n * - Dynamic (non-literal) strings return `unknown`.\n *\n * 2. **Key array** (`PropertyKey[]`) — explicit array of `string | number | symbol` keys,\n * no parsing performed. Enables symbol-keyed traversal and compile-time type inference:\n * `get(obj, ['a', 'b'] as const)` infers the return type from the path.\n *\n * Both forms support **all objects** (plain objects, arrays, class instances).\n * Symbol keys are only reachable via the key-array form.\n *\n * @param obj - The object to read from\n * @param path - Dot/bracket-notation string literal or explicit `PropertyKey[]`\n * @param defaultValue - Returned when the path is absent or resolves to `undefined`\n * @returns The value at the path, or `defaultValue`\n * @example\n * get({ a: { b: { c: 42 } } }, 'a.b.c') // => 42 (inferred: number | undefined)\n * get({ layers: [{ name: 'bg' }] }, 'layers[0].name') // => 'bg' (inferred: string | undefined)\n * get({ a: { b: 0 } }, 'a.b', 99) // => 0 (falsy values returned as-is)\n * get({ a: 1 }, 'b.c', 'default') // => 'default'\n *\n * const id = Symbol('id')\n * get({ [id]: 'alice' }, [id]) // => 'alice' (symbol key, inferred: string | undefined)\n * @since 1.9.0\n */\nexport function get<D>(obj: null | undefined, path: string | readonly PropertyKey[], defaultValue: D): D;\nexport function get(obj: null | undefined, path: string | readonly PropertyKey[]): undefined;\nexport function get<T extends object, const P extends string | readonly PropertyKey[]>(\n obj: T | null | undefined,\n path: P,\n defaultValue?: DeepGet<T, ParsePath<P>>,\n): DeepGet<T, ParsePath<P>> | undefined;\nexport function get(obj: unknown, path: string | readonly PropertyKey[], defaultValue?: unknown): unknown {\n if (obj == null) return defaultValue;\n const keys: readonly PropertyKey[] = typeof path === 'string' ? parsePropertyPath(path) : path;\n const result = walkPropertyPath(obj, keys);\n return result !== undefined ? result : defaultValue;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Groups an array of items by a key derived from each item.\n *\n * A thin, typed wrapper around `Object.groupBy` (ES2024) that works on\n * older targets and provides stricter return-type inference.\n * `null` and `undefined` are treated as empty arrays and return `{}`.\n * Items whose computed key is a prototype-polluting string (`__proto__`,\n * `constructor`, `prototype`) are silently skipped.\n *\n * @param items - The array to group\n * @param keyFn - Function that returns the group key for each item\n * @returns A record mapping each key to the array of items with that key\n * @example\n * groupBy([1, 2, 3, 4], n => n % 2 === 0 ? 'even' : 'odd')\n * // => { odd: [1, 3], even: [2, 4] }\n * groupBy(null, n => n % 2 === 0 ? 'even' : 'odd')\n * // => {}\n * @since 2.0.0\n */\nexport function groupBy<T, K extends PropertyKey>(\n items: readonly T[] | null | undefined,\n keyFn: (item: T) => K\n): Partial<Record<K, T[]>> {\n const result = {} as Partial<Record<K, T[]>>;\n if (items == null) return result;\n for (const item of items) {\n const key = keyFn(item);\n if (typeof key === 'string' && UNSAFE_KEYS.has(key)) continue;\n if (result[key] === undefined) {\n result[key] = [];\n }\n (result[key] as T[]).push(item);\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Returns a new object with keys and values swapped.\n * If multiple keys share the same value, the last one wins.\n * `null` and `undefined` are treated as empty objects and return `{}`.\n * Entries whose source key **or** value is a prototype-polluting string\n * (`__proto__`, `constructor`, `prototype`) are silently skipped.\n *\n * @param obj - The object whose keys and values are to be swapped\n * @returns A new object with values as keys and original keys as values\n * @example\n * invert({ a: 'x', b: 'y', c: 'z' })\n * // => { x: 'a', y: 'b', z: 'c' }\n *\n * invert({ one: 1, two: 2 })\n * // => { 1: 'one', 2: 'two' }\n *\n * invert(null)\n * // => {}\n * @since 2.0.0\n */\nexport function invert<K extends string, V extends PropertyKey>(obj: Record<K, V> | null | undefined): Record<V, K> {\n const result = {} as Record<V, K>;\n if (obj == null) return result;\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key) && !UNSAFE_KEYS.has(key)) {\n const val = obj[key as K];\n if (typeof val === 'string' && UNSAFE_KEYS.has(val)) continue;\n result[val] = key as unknown as K;\n }\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a plain object has no own enumerable string-keyed properties.\n * `null` and `undefined` are treated as empty objects and return `true`.\n *\n * Symbol-keyed properties are not counted. Use `Object.getOwnPropertySymbols`\n * separately if symbol keys matter for your use case.\n *\n * @param value - The object to check\n * @returns `true` if the object has no own enumerable string-keyed properties, or if `value` is `null`/`undefined`\n * @example\n * isEmpty({}) // => true\n * isEmpty(null) // => true\n * isEmpty(undefined) // => true\n * isEmpty({ a: 1 }) // => false\n * isEmpty({ a: undefined }) // => false (key exists)\n * @since 2.0.3\n */\nexport function isEmpty(value: Record<PropertyKey, unknown> | null | undefined): boolean {\n return value == null || Object.keys(value).length === 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a plain object has at least one own enumerable string-keyed property.\n * `null` and `undefined` are treated as empty objects and return `false`.\n *\n * Symbol-keyed properties are not counted. Use `Object.getOwnPropertySymbols`\n * separately if symbol keys matter for your use case.\n *\n * @param value - The object to check\n * @returns `true` if the object has at least one own enumerable string-keyed property; `false` for empty, `null`, or `undefined`.\n * Acts as a type guard: the `if` branch narrows `Record<PropertyKey, unknown> | null | undefined` to `Record<PropertyKey, unknown>`.\n * @example\n * isNonEmpty({ a: 1 }) // => true\n * isNonEmpty({}) // => false\n * isNonEmpty(null) // => false\n * isNonEmpty(undefined) // => false\n * @since 2.0.3\n */\nexport function isNonEmpty(value: Record<PropertyKey, unknown> | null | undefined): value is Record<PropertyKey, unknown> {\n return value != null && Object.keys(value).length > 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Converts a string to kebab-case.\n * Handles camelCase, PascalCase, snake_case, spaces, and mixed formats.\n * @param str - The string to convert\n * @returns String in kebab-case\n * @example\n * kebabCase('camelCase')\n * // => 'camel-case'\n * kebabCase('user_name')\n * // => 'user-name'\n * @since 1.9.0\n */\nexport function kebabCase(str: string): string;\nexport function kebabCase(str: undefined): undefined;\nexport function kebabCase(str: null): null;\nexport function kebabCase(str: string | undefined | null): string | undefined | null {\n if (str === undefined || str === null) return str;\n const words = str\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/([A-Z])([A-Z][a-z])/g, '$1 $2')\n .split(/[\\s_-]+/)\n .filter(Boolean);\n return words.join('-').toLowerCase();\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { kebabCase } from '../string/kebabCase.js';\nimport { mapDeep } from './mapDeep.js';\n\n/**\n * Recursively transforms every key of a plain object (including keys nested inside arrays and\n * nested objects) to kebab-case. Handles snake_case, camelCase, PascalCase, and space-separated\n * keys. Non-plain-object values — `Date`, `Map`, `Set`, class instances, primitives — are left\n * untouched, only their position is walked into. An entry whose transformed key is a\n * prototype-polluting string (`__proto__`, `constructor`, `prototype`) is silently skipped,\n * same as the rest of `@helpers4/object`.\n * @param value - The object (or array of objects) to transform\n * @returns A new value with every plain-object key converted to kebab-case\n * @example\n * kebabCaseKeys({ userName: 'Alice', homeAddress: { zipCode: '12345' } })\n * // => { 'user-name': 'Alice', 'home-address': { 'zip-code': '12345' } }\n * @since 3.0.3\n */\nexport function kebabCaseKeys<T>(value: T): T {\n return mapDeep(value, undefined, kebabCase);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Transforms the values and/or keys of a plain object in a single pass.\n *\n * Both callbacks are optional and default to identity (no transformation).\n * When `mapValue` is omitted the original values are preserved;\n * when `mapKey` is omitted the original keys are preserved.\n *\n * Note: if two different keys map to the same output key the last one wins\n * (insertion order). Entries whose mapped key is a prototype-polluting string\n * (`__proto__`, `constructor`, `prototype`) are silently skipped.\n *\n * @param obj - The source object\n * @param mapValue - Callback called with `(value, key)` for each entry.\n * Defaults to identity.\n * @param mapKey - Callback called with `(key, value)` for each entry.\n * Defaults to identity.\n * @returns A new object with transformed keys and/or values\n * @example\n * map({ a: 1, b: 2 }, v => v * 10)\n * // => { a: 10, b: 20 }\n *\n * map({ a: 1, b: 2 }, undefined, k => k.toUpperCase())\n * // => { A: 1, B: 2 }\n *\n * map({ a: 1, b: 2 }, v => v * 10, k => k.toUpperCase())\n * // => { A: 10, B: 20 }\n * @since 2.0.0\n */\nexport function map<\n TObj extends Record<string, unknown>,\n TVal = TObj[keyof TObj],\n TKey extends PropertyKey = keyof TObj,\n>(\n obj: TObj | null | undefined,\n mapValue?: (value: TObj[keyof TObj], key: keyof TObj) => TVal,\n mapKey?: (key: keyof TObj, value: TObj[keyof TObj]) => TKey\n): Record<TKey, TVal> {\n const result = {} as Record<TKey, TVal>;\n if (obj == null) return result;\n for (const key of Object.keys(obj) as (keyof TObj)[]) {\n const value = obj[key];\n const newKey = mapKey ? mapKey(key, value) : (key as unknown as TKey);\n if (typeof newKey === 'string' && UNSAFE_KEYS.has(newKey)) continue;\n const newVal = mapValue ? mapValue(value, key) : (value as unknown as TVal);\n result[newKey] = newVal;\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { cloneDeep } from './cloneDeep.js';\nimport { isPlainObject } from '../guard/isPlainObject';\nimport type { MergeResult } from './_types.js';\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\nfunction applyKey(\n result: Record<PropertyKey, unknown>,\n source: Record<PropertyKey, unknown>,\n key: PropertyKey,\n): void {\n const resultValue = result[key];\n const sourceValue = source[key];\n if (isPlainObject(resultValue) && isPlainObject(sourceValue)) {\n result[key] = mergeDeep(\n resultValue as Record<PropertyKey, unknown>,\n sourceValue as Record<PropertyKey, unknown>,\n );\n } else if (sourceValue !== undefined) {\n result[key] = (isPlainObject(sourceValue) || Array.isArray(sourceValue))\n ? cloneDeep(sourceValue)\n : sourceValue;\n }\n}\n\nfunction applySource(\n result: Record<PropertyKey, unknown>,\n source: Record<PropertyKey, unknown>,\n): void {\n for (const key in source) {\n if (!Object.hasOwn(source, key) || UNSAFE_KEYS.has(key)) continue;\n applyKey(result, source, key);\n }\n for (const sym of Object.getOwnPropertySymbols(source)) {\n if (!Object.prototype.propertyIsEnumerable.call(source, sym)) continue;\n applyKey(result, source, sym);\n }\n}\n\n/**\n * Merges two or more objects deeply, returning a **new** object without mutating any input.\n *\n * Sources are applied left to right. For each key:\n * - If both sides are plain objects → merged recursively into a new object.\n * - Otherwise → **later source wins** (the earlier value is overwritten).\n * - `undefined` in a source **never overwrites** an existing value.\n * - `null` in a source **does overwrite** and prevents a later source from\n * deep-merging into that key: `mergeDeep({ a: { x: 1 } }, { a: null }, { a: { y: 2 } })`\n * → `{ a: { y: 2 } }` — `x: 1` is permanently lost.\n * - Arrays, class instances, and all non-plain-object values are **replaced**, not merged.\n *\n * Own enumerable string and symbol keys of each source are processed at the top level;\n * inherited and non-enumerable properties are skipped. Prototype-polluting keys\n * (`__proto__`, `constructor`, `prototype`) are silently ignored.\n * **Note:** symbol keys inside nested plain-object values are not preserved — they are\n * lost when those values are deep-cloned. Only top-level symbol keys survive.\n *\n * **TypeScript return type — intersection semantics**\n *\n * The return type is `A & B & C …` (intersection of all source types). This is accurate\n * when keys are disjoint or share the same type:\n * ```ts\n * mergeDeep({ a: 1 }, { b: 'x' }) // { a: number } & { b: string } ✓\n * mergeDeep({ a: { b: 1 } }, { a: { c: 2 } }) // { a: { b: number } & { c: number } } ✓\n * ```\n * When the same key carries **incompatible types** across sources, the intersection\n * resolves to `never` for that key — TypeScript surfaces the conflict rather than\n * silently picking a type:\n * ```ts\n * mergeDeep({ a: 1 }, { a: 'x' }) // { a: never } ← type conflict detected\n * ```\n * At runtime the later source always wins (`'x'`), but the `never` type signals that\n * the caller should align their source types. If intentional, cast the result.\n *\n * @param sources - Two or more objects to merge (none are mutated)\n * @returns A new object that is the deep merge of all sources\n * @example\n * mergeDeep({ a: 1, b: { c: 2 } }, { b: { d: 3 }, e: 4 })\n * // => { a: 1, b: { c: 2, d: 3 }, e: 4 }\n *\n * // Later source wins for non-object values\n * mergeDeep({ a: 1, arr: [1, 2] }, { a: 2, arr: [3] })\n * // => { a: 2, arr: [3] }\n *\n * // undefined never overwrites\n * mergeDeep({ a: 1 }, { a: undefined })\n * // => { a: 1 }\n *\n * // Three sources, left to right\n * mergeDeep({ x: 1 }, { y: 2 }, { x: 99, z: 3 })\n * // => { x: 99, y: 2, z: 3 }\n * @since 1.9.0\n */\nexport function mergeDeep<T extends [object, ...object[]]>(...sources: [...T]): MergeResult<T>;\nexport function mergeDeep(...sources: object[]): object {\n const result: Record<PropertyKey, unknown> = {};\n for (const source of sources) {\n if (source !== null && source !== undefined) {\n applySource(result, source as Record<PropertyKey, unknown>);\n }\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Creates a new object without the specified keys.\n * @param obj - The source object\n * @param keys - The keys to omit\n * @returns A new object without the omitted keys\n * @example\n * omit({ a: 1, b: 2, c: 3 }, ['b'])\n * // => { a: 1, c: 3 }\n * @since 2.0.0\n */\nexport function omit<T extends Record<string, unknown>, K extends keyof T>(obj: T, keys: readonly K[]): Omit<T, K>;\nexport function omit(obj: undefined, keys: readonly string[]): undefined;\nexport function omit(obj: null, keys: readonly string[]): null;\nexport function omit<T extends Record<string, unknown>, K extends keyof T>(\n obj: T | undefined | null,\n keys: readonly K[]\n): Omit<T, K> | undefined | null {\n if (obj === undefined || obj === null) return obj;\n const result = { ...obj };\n for (const key of keys) {\n delete result[key];\n }\n return result as Omit<T, K>;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Creates a new object without the own enumerable entries for which\n * `predicate` returns `true`.\n *\n * Complements {@link omit} for when the keys to remove aren't known ahead of\n * time — `omit` takes an explicit key list, `omitBy` takes a predicate.\n *\n * @param obj - The source object. `null`/`undefined` pass through unchanged.\n * @param predicate - Called with `(value, key)` for each own enumerable entry\n * @returns A new object without the matching entries\n * @example\n * omitBy({ a: 1, b: undefined, c: 2 }, (value) => value === undefined)\n * // => { a: 1, c: 2 }\n * @since 3.0.0\n */\nexport function omitBy<T extends Record<string, unknown>>(\n obj: T | undefined | null,\n predicate: (value: T[keyof T], key: keyof T) => boolean,\n): Partial<T> | undefined | null {\n if (obj == null) return obj;\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n const typedKey = key as keyof T;\n if (!predicate(obj[typedKey], typedKey)) {\n result[key] = obj[typedKey];\n }\n }\n return result as Partial<T>;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Converts a string to PascalCase.\n * Handles camelCase, kebab-case, snake_case, spaces, and mixed formats.\n * @param str - The string to convert\n * @returns String in PascalCase\n * @example\n * pascalCase('hello-world')\n * // => 'HelloWorld'\n * @since 2.0.0\n */\nexport function pascalCase(str: string): string;\nexport function pascalCase(str: undefined): undefined;\nexport function pascalCase(str: null): null;\nexport function pascalCase(str: string | undefined | null): string | undefined | null {\n if (str === undefined || str === null) return str;\n return str\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/([A-Z])([A-Z][a-z])/g, '$1 $2')\n .split(/[\\s_-]+/)\n .filter(Boolean)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('');\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { pascalCase } from '../string/pascalCase.js';\nimport { mapDeep } from './mapDeep.js';\n\n/**\n * Recursively transforms every key of a plain object (including keys nested inside arrays and\n * nested objects) to PascalCase. Handles camelCase, snake_case, kebab-case, and space-separated\n * keys. Non-plain-object values — `Date`, `Map`, `Set`, class instances, primitives — are left\n * untouched, only their position is walked into. An entry whose transformed key is a\n * prototype-polluting string (`__proto__`, `constructor`, `prototype`) is silently skipped,\n * same as the rest of `@helpers4/object`.\n * @param value - The object (or array of objects) to transform\n * @returns A new value with every plain-object key converted to PascalCase\n * @example\n * pascalCaseKeys({ user_name: 'Alice', home_address: { zip_code: '12345' } })\n * // => { UserName: 'Alice', HomeAddress: { ZipCode: '12345' } }\n * @since 3.0.3\n */\nexport function pascalCaseKeys<T>(value: T): T {\n return mapDeep(value, undefined, pascalCase);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Creates a new object with only the specified keys.\n * Keys that are prototype-polluting strings (`__proto__`, `constructor`, `prototype`) are\n * silently skipped.\n * @param obj - The source object\n * @param keys - The keys to pick\n * @returns A new object with only the picked keys\n * @example\n * pick({ a: 1, b: 2, c: 3 }, ['a', 'c'])\n * // => { a: 1, c: 3 }\n * @since 2.0.0\n */\nexport function pick<T extends Record<string, unknown>, K extends keyof T>(obj: T, keys: readonly K[]): Pick<T, K>;\nexport function pick(obj: undefined, keys: readonly string[]): undefined;\nexport function pick(obj: null, keys: readonly string[]): null;\nexport function pick<T extends Record<string, unknown>, K extends keyof T>(\n obj: T | undefined | null,\n keys: readonly K[]\n): Pick<T, K> | undefined | null {\n if (obj === undefined || obj === null) return obj;\n const result = {} as Pick<T, K>;\n for (const key of keys) {\n if (typeof key === 'string' && UNSAFE_KEYS.has(key)) continue;\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result[key] = obj[key];\n }\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Creates a new object with only the own enumerable entries for which\n * `predicate` returns `true`.\n *\n * Complements {@link pick} for when the keys to keep aren't known ahead of\n * time — `pick` takes an explicit key list, `pickBy` takes a predicate.\n *\n * @param obj - The source object. `null`/`undefined` pass through unchanged.\n * @param predicate - Called with `(value, key)` for each own enumerable entry\n * @returns A new object with only the matching entries\n * @example\n * pickBy({ a: 1, b: 0, c: 2 }, (value) => value > 0)\n * // => { a: 1, c: 2 }\n * @since 3.0.0\n */\nexport function pickBy<T extends Record<string, unknown>>(\n obj: T | undefined | null,\n predicate: (value: T[keyof T], key: keyof T) => boolean,\n): Partial<T> | undefined | null {\n if (obj == null) return obj;\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n if (UNSAFE_KEYS.has(key)) continue;\n const typedKey = key as keyof T;\n if (predicate(obj[typedKey], typedKey)) {\n result[key] = obj[typedKey];\n }\n }\n return result as Partial<T>;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is null or undefined (nullish).\n * @param value - The value to check\n * @returns True if value is null or undefined\n * @example\n * isNullish(null) // => true\n * isNullish(undefined) // => true\n * isNullish(0) // => false\n * isNullish('') // => false\n *\n * @see {@link isDefined} for the inverse check (`!isNullish`)\n * @see {@link isFalsy} to also catch `0`, `\"\"`, `false`, and `NaN`\n * @since 2.0.0\n */\nexport function isNullish(value: unknown): value is null | undefined {\n return value === null || value === undefined;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { isNullish } from '../guard/isNullish';\n\n/**\n * Remove null and undefined values from an object.\n *\n * @param obj an object\n * @returns A shallow copy of the object without null or undefined values\n * @since 1.0.0\n */\nexport function removeUndefinedNull<T extends Record<string, string | number | boolean | null | undefined>>(obj: T): Partial<T>;\n\n/**\n * Remove null and undefined values from an object.\n *\n * @param obj a null object\n * @returns null\n * @since 1.0.0\n */\nexport function removeUndefinedNull(obj: null): null;\n\n/**\n * Remove null and undefined values from an object.\n *\n * @param obj an undefined object\n * @returns undefined\n * @since 1.0.0\n */\nexport function removeUndefinedNull(obj: undefined): undefined;\n\n/**\n * Remove null and undefined values from an object.\n *\n * @param obj an object\n * @returns A shallow copy of the object without null or undefined values\n * @since 1.0.0\n */\nexport function removeUndefinedNull<T extends Record<string, string | number | boolean | null | undefined>>(obj: T | null | undefined): Partial<T> | null | undefined {\n if (!obj) return obj;\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) {\n if (!isNullish(v)) { result[k] = v; }\n }\n return result as Partial<T>;\n}\n\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Parses strict JSON (RFC 8259) — exactly what `JSON.parse` accepts, nothing more.\n *\n * **Accepts:** standard JSON only — double-quoted strings and keys, finite decimal numbers,\n * `true`/`false`/`null`, objects and arrays, surrounding whitespace.\n *\n * **Rejects:** comments, trailing commas, single quotes, unquoted keys, hexadecimal numbers,\n * `NaN`/`Infinity`, a leading byte order mark (U+FEFF), and anything else that isn't strict JSON.\n *\n * **On invalid input:** throws the native `SyntaxError` from `JSON.parse`.\n *\n * Use it to validate input that must be strict JSON, e.g. an API payload. To also read config\n * files with comments or JSON5, use {@link parse}. To never throw, use {@link safeParseStrict}.\n *\n * @param text - The JSON text to parse\n * @returns The parsed value, typed as `T`\n * @throws {SyntaxError} When `text` isn't strict JSON\n * @see {@link safeParseStrict} — same parsing, returns `null` or a fallback instead of throwing\n * @see {@link parse} — also accepts JSONC and JSON5\n * @see {@link parseLines} — one value per line (NDJSON, JSON Lines)\n * @see {@link parseSequence} — JSON text sequences (RFC 7464)\n * @example\n * parseStrict<{ a: number }>('{\"a\":1}') // => { a: 1 }\n * parseStrict('{\"a\":1,}') // throws SyntaxError (trailing comma)\n * @since 3.1.3\n */\nexport function parseStrict<T = unknown>(text: string): T {\n return JSON.parse(text) as T;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { parseStrict } from './parseStrict';\n\n/**\n * Parses strict JSON like {@link parseStrict}, but returns `null` (or `fallback`) instead of\n * throwing on invalid input.\n *\n * **Accepts / rejects:** exactly what {@link parseStrict} does — standard JSON only, no comments,\n * no trailing commas, no JSON5 syntax, no leading byte order mark.\n *\n * **On invalid input:** returns `fallback` when one is given — even `undefined`, which is told\n * apart from an omitted argument — and `null` otherwise. Never throws.\n *\n * @param text - The JSON text to parse\n * @param fallback - Value returned on invalid input. Defaults to `null` when omitted.\n * @returns The parsed value typed as `T`, or `fallback` on invalid input\n * @see {@link parseStrict} — same parsing, throws a `SyntaxError` instead\n * @see {@link safeParse} — also accepts JSONC and JSON5\n * @example\n * safeParseStrict<{ a: number }>('{\"a\":1}') // => { a: 1 }\n * safeParseStrict('{\"a\":1,}') // => null\n * safeParseStrict('oops', {}) // => {}\n * @since 3.1.3\n */\nexport function safeParseStrict<T = unknown>(text: string): T | null;\nexport function safeParseStrict<T = unknown, F = T>(text: string, fallback: F): T | F;\nexport function safeParseStrict<T, F>(text: string, fallback?: F): T | F | null {\n try {\n return parseStrict<T>(text);\n } catch {\n return arguments.length < 2 ? null : (fallback as F);\n }\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { safeParseStrict } from '../json/safeParseStrict';\n\n/**\n * Parses a JSON string, returning `null` (or a fallback) on any parse failure.\n *\n * Unlike `JSON.parse`, this never throws. Invalid JSON strings and other\n * parsing edge-cases resolve to `null` or the provided `fallback`.\n *\n * @param input - The JSON string to parse.\n * @param fallback - Value returned on failure. Defaults to `null` when omitted.\n * @returns The parsed value typed as `T`, or `fallback` on failure.\n * @example\n * safeJsonParse<{ a: number }>('{\"a\":1}') // => { a: 1 }\n * safeJsonParse('invalid') // => null\n * safeJsonParse('invalid', []) // => []\n * @deprecated Use `safeParseStrict` from `@helpers4/json` instead — same parsing, same\n * `fallback` behavior. `safeJsonParse` will be removed in v4.\n * @since 2.0.0\n */\nexport function safeJsonParse<T>(input: string): T | null;\nexport function safeJsonParse<T>(input: string, fallback: T): T;\nexport function safeJsonParse<T>(input: string, fallback?: T): T | null {\n // Forward the fallback only when one was passed, so \"no fallback\" (→ null) stays distinct from\n // an explicit `undefined` fallback (→ undefined).\n return arguments.length < 2 ? safeParseStrict<T>(input) : safeParseStrict<T>(input, fallback as T);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { parsePropertyPath } from './parsePropertyPath.js';\nimport type { ContainsUnsafeStringKey, DeepGet, DeepSet, ParsePath } from './_types.js';\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Sets a value in an object at the given path, creating intermediate objects as needed.\n *\n * **Two path forms are supported:**\n *\n * 1. **String path** — dot notation and bracket notation, mixed freely.\n * - Dot segments are always string keys: `'layers.1.name'` → keys `['layers', '1', 'name']`.\n * - Bracket segments are always number keys: `'layers[1].name'` → keys `['layers', 1, 'name']`.\n * - String literal paths give **full compile-time type inference** on the return type.\n * - Dynamic (non-literal) strings return `T` (same object type).\n *\n * 2. **Key array** (`PropertyKey[]`) — explicit array of `string | number | symbol` keys,\n * no parsing performed. Enables symbol-keyed access and precise return-type inference.\n *\n * Both forms support **all objects** (plain objects, arrays, class instances).\n * Symbol keys are only reachable via the key-array form.\n *\n * Intermediate nodes that are absent, `null`, or not an object are replaced with `{}`.\n * Any path containing a string segment equal to `__proto__`, `constructor`, or `prototype`\n * is rejected and the original object is returned unchanged (prototype-pollution guard).\n *\n * @param obj - The object to mutate\n * @param path - Dot/bracket-notation string literal or explicit `PropertyKey[]`\n * @param value - Value to assign at the path\n * @returns The mutated object (same reference, narrowed type)\n * @example\n * // Dot notation — \"1\" stays a string key\n * set({}, 'a.b.c', 42)\n * // => { a: { b: { c: 42 } } }\n *\n * // Bracket notation — [1] becomes a number key\n * set({ layers: [{}, { name: 'old' }] }, 'layers[1].name', 'bg')\n * // => { layers: [{}, { name: 'bg' }] }\n *\n * // Key array — supports symbols\n * const id = Symbol('id')\n * set({}, ['user', id], 'alice')\n * // => { user: { [id]: 'alice' } }\n * @since 1.9.0\n */\nexport function set<\n T extends object,\n const P extends string | readonly PropertyKey[],\n V extends DeepGet<T, ParsePath<P>>,\n>(\n obj: T,\n path: P,\n value: V,\n): string extends P ? T : readonly PropertyKey[] extends P ? T : ContainsUnsafeStringKey<ParsePath<P>> extends true ? T : DeepSet<T, ParsePath<P>, V>;\nexport function set(obj: object, path: string | PropertyKey[], value: unknown): object {\n const keys: readonly PropertyKey[] = typeof path === 'string' ? parsePropertyPath(path) : path;\n\n if (keys.length === 0) return obj;\n if (keys.some((k) => typeof k === 'string' && UNSAFE_KEYS.has(k))) return obj;\n\n let current = obj as Record<PropertyKey, unknown>;\n\n for (let i = 0; i < keys.length - 1; i++) {\n const key = keys[i];\n\n // Object.hasOwn (not `key in current`) is intentional: `in` checks the prototype chain,\n // which would silently traverse into — and potentially mutate — an inherited object.\n // Using hasOwn ensures we only follow own properties; inherited intermediate nodes are\n // shadowed with a fresh own `{}` instead of being followed into the prototype.\n if (!Object.hasOwn(current, key) || typeof current[key] !== 'object' || current[key] === null) {\n current[key] = {};\n }\n\n current = current[key] as Record<PropertyKey, unknown>;\n }\n\n current[keys[keys.length - 1]] = value;\n return obj;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Converts a string to snake_case.\n * Handles camelCase, PascalCase, kebab-case, spaces, and mixed formats.\n * @param str - The string to convert\n * @returns String in snake_case\n * @example\n * snakeCase('camelCase')\n * // => 'camel_case'\n * @since 2.0.0\n */\nexport function snakeCase(str: string): string;\nexport function snakeCase(str: undefined): undefined;\nexport function snakeCase(str: null): null;\nexport function snakeCase(str: string | undefined | null): string | undefined | null {\n if (str === undefined || str === null) return str;\n return str\n .replace(/([a-z0-9])([A-Z])/g, '$1_$2')\n .replace(/([A-Z])([A-Z][a-z])/g, '$1_$2')\n .replace(/[\\s-]+/g, '_')\n .toLowerCase();\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { snakeCase } from '../string/snakeCase.js';\nimport { mapDeep } from './mapDeep.js';\n\n/**\n * Recursively transforms every key of a plain object (including keys nested inside arrays and\n * nested objects) to snake_case. Handles camelCase, PascalCase, kebab-case, and space-separated\n * keys. Non-plain-object values — `Date`, `Map`, `Set`, class instances, primitives — are left\n * untouched, only their position is walked into. An entry whose transformed key is a\n * prototype-polluting string (`__proto__`, `constructor`, `prototype`) is silently skipped,\n * same as the rest of `@helpers4/object`.\n * @param value - The object (or array of objects) to transform\n * @returns A new value with every plain-object key converted to snake_case\n * @example\n * snakeCaseKeys({ userName: 'Alice', homeAddress: { zipCode: '12345' } })\n * // => { user_name: 'Alice', home_address: { zip_code: '12345' } }\n * @since 3.0.3\n */\nexport function snakeCaseKeys<T>(value: T): T {\n return mapDeep(value, undefined, snakeCase);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Creates a new object with the same entries as the input, but with its own keys sorted.\n * Shallow only — nested objects are copied as-is, their keys are not re-sorted.\n * Key order matters for things like `JSON.stringify` diffs and snapshot stability; this does\n * not change equality (`{a:1,b:2}` and `{b:2,a:1}` are already equal), just iteration/serialization order.\n * Note: integer-index-like keys (`\"0\"`, `\"1\"`, `\"42\"`...) are always iterated first, in numeric\n * order, by the JS engine itself — no object key ordering can override that language behavior.\n * A prototype-polluting key (`__proto__`, `constructor`, `prototype`) is silently skipped,\n * same as the rest of `@helpers4/object`.\n * @param obj - The object whose keys to sort\n * @param compareFn - Optional custom comparator, passed directly to `Array.prototype.sort`\n * @returns A new object with the same entries, own keys in sorted order\n * @example\n * sortKeys({ b: 2, a: 1, c: 3 })\n * // => { a: 1, b: 2, c: 3 }\n * @since 3.0.3\n */\nexport function sortKeys<T extends Record<string, unknown>>(\n obj: T,\n compareFn?: (a: string, b: string) => number,\n): T {\n const sortedKeys = Object.keys(obj).toSorted(compareFn);\n const result = {} as T;\n for (const key of sortedKeys) {\n if (UNSAFE_KEYS.has(key)) continue;\n result[key as keyof T] = obj[key as keyof T];\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Converts a string to Title Case.\n * Handles camelCase, PascalCase, kebab-case, snake_case, spaces, and mixed formats.\n * @param str - The string to convert\n * @returns String in Title Case\n * @example\n * titleCase('hello-world')\n * // => 'Hello World'\n * @example\n * titleCase('queryItems')\n * // => 'Query Items'\n * @since 2.0.0\n */\nexport function titleCase(str: string): string;\nexport function titleCase(str: undefined): undefined;\nexport function titleCase(str: null): null;\nexport function titleCase(str: string | undefined | null): string | undefined | null {\n if (str === undefined || str === null) return str;\n return str\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/([A-Z])([A-Z][a-z])/g, '$1 $2')\n .split(/[\\s_-]+/)\n .filter(Boolean)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ');\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { titleCase } from '../string/titleCase.js';\nimport { mapDeep } from './mapDeep.js';\n\n/**\n * Recursively transforms every key of a plain object (including keys nested inside arrays and\n * nested objects) to Title Case. Handles camelCase, snake_case, kebab-case, and space-separated\n * keys. Non-plain-object values — `Date`, `Map`, `Set`, class instances, primitives — are left\n * untouched, only their position is walked into. An entry whose transformed key is a\n * prototype-polluting string (`__proto__`, `constructor`, `prototype`) is silently skipped,\n * same as the rest of `@helpers4/object`.\n *\n * Note: unlike the other `*CaseKeys` variants, `titleCase` joins words with spaces (e.g.\n * `'User Name'`) — those keys are only usable via bracket access (`obj['User Name']`), not dot\n * notation. Useful for display-facing structures (form labels, table headers), not wire formats.\n * @param value - The object (or array of objects) to transform\n * @returns A new value with every plain-object key converted to Title Case\n * @example\n * titleCaseKeys({ user_name: 'Alice', home_address: { zip_code: '12345' } })\n * // => { 'User Name': 'Alice', 'Home Address': { 'Zip Code': '12345' } }\n * @since 3.0.3\n */\nexport function titleCaseKeys<T>(value: T): T {\n return mapDeep(value, undefined, titleCase);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { set } from './set.js';\n\n/**\n * Rebuilds a nested object from a single-level object whose keys are\n * dot-notation paths. The inverse of {@link flatten}.\n *\n * Uses {@link set} internally, so intermediate nodes are always created as\n * plain objects (never arrays — see {@link flatten}'s doc for why), and any\n * key segment equal to `__proto__`, `constructor`, or `prototype` is silently\n * rejected (same prototype-pollution guard as `set`).\n *\n * @param obj - A single-level object with dot-notation keys\n * @returns The rebuilt nested object\n * @example\n * unflatten({ 'a.b.c': 1, 'a.d': 2 })\n * // => { a: { b: { c: 1 }, d: 2 } }\n * @since 3.0.0\n */\nexport function unflatten(obj: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n set(result, key, value);\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { parsePropertyPath } from './parsePropertyPath.js';\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Removes the value at a dot/bracket-notation path or explicit key array,\n * mutating the object in place. Uses the same path syntax as {@link get}/{@link set}.\n *\n * A missing intermediate segment is a no-op (nothing to remove), not an error.\n * As with `set`, any path containing a string segment equal to `__proto__`,\n * `constructor`, or `prototype` is rejected and the object is returned unchanged.\n *\n * The removed key stops appearing in `Object.keys`/`for...in` — unlike setting\n * it to `undefined`, which would keep the key present.\n *\n * @param obj - The object to mutate\n * @param path - Dot/bracket-notation string, or explicit `PropertyKey[]`\n * @returns The same object reference, with the key removed if it existed\n * @example\n * unset({ a: { b: 1, c: 2 } }, 'a.b')\n * // => { a: { c: 2 } }\n * @example\n * unset({ a: 1 }, 'x.y') // path doesn't exist — no-op\n * // => { a: 1 }\n * @since 3.0.0\n */\nexport function unset<T extends object>(obj: T, path: string | readonly PropertyKey[]): T {\n const keys: readonly PropertyKey[] = typeof path === 'string' ? parsePropertyPath(path) : path;\n\n if (keys.length === 0) return obj;\n if (keys.some((key) => typeof key === 'string' && UNSAFE_KEYS.has(key))) return obj;\n\n let current: unknown = obj;\n for (let i = 0; i < keys.length - 1; i++) {\n if (current == null || typeof current !== 'object') return obj;\n current = (current as Record<PropertyKey, unknown>)[keys[i]];\n }\n\n if (current != null && typeof current === 'object') {\n delete (current as Record<PropertyKey, unknown>)[keys[keys.length - 1]];\n }\n\n return obj;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { get } from './get.js';\nimport { set } from './set.js';\nimport type { ContainsUnsafeStringKey, DeepGet, DeepSet, ParsePath } from './_types.js';\n\n/**\n * Updates the value at a path by applying a function to its current value,\n * creating intermediate objects as needed. Equivalent to\n * `set(obj, path, updater(get(obj, path)))` in a single call.\n *\n * Uses the same path syntax and type-inference rules as {@link get} and\n * {@link set} — see those for the full behavior (string vs. `PropertyKey[]`\n * paths, prototype-pollution guarding, etc.).\n *\n * @param obj - The object to mutate\n * @param path - Dot/bracket-notation string literal or explicit `PropertyKey[]`\n * @param updater - Called with the current value (`undefined` if the path is\n * absent); its return value is written back at the path\n * @returns The mutated object (same reference, narrowed type)\n * @example\n * update({ count: 1 }, 'count', (n) => (n ?? 0) + 1)\n * // => { count: 2 }\n * @example\n * // Missing intermediate objects are created, just like set()\n * update({}, 'stats.hits', (n: number | undefined) => (n ?? 0) + 1)\n * // => { stats: { hits: 1 } }\n * @since 3.0.0\n */\nexport function update<\n T extends object,\n const P extends string | readonly PropertyKey[],\n V extends DeepGet<T, ParsePath<P>>,\n>(\n obj: T,\n path: P,\n updater: (current: DeepGet<T, ParsePath<P>> | undefined) => V,\n): string extends P ? T : readonly PropertyKey[] extends P ? T : ContainsUnsafeStringKey<ParsePath<P>> extends true ? T : DeepSet<T, ParsePath<P>, V>;\nexport function update(\n obj: object,\n path: string | PropertyKey[],\n updater: (current: unknown) => unknown,\n): object {\n const current = get(obj, path);\n return set(obj, path, updater(current));\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["equalsDeep","compareDate","arrayDeepEquals"],"sources":["../../../helpers/string/camelCase.ts","../../../helpers/_shared/_unsafeKeys.ts","../../../helpers/guard/isPlainObject.ts","../../../helpers/object/mapDeep.ts","../../../helpers/object/camelCaseKeys.ts","../../../helpers/object/clone.ts","../../../helpers/object/cloneDeep.ts","../../../helpers/object/compact.ts","../../../helpers/array/equalsDeep.ts","../../../helpers/date/timestamp.ts","../../../helpers/date/ensureDate.ts","../../../helpers/date/compare.ts","../../../helpers/guard/isSpecialObject.ts","../../../helpers/object/diff.ts","../../../helpers/object/equalsDeep.ts","../../../helpers/object/equalsShallow.ts","../../../helpers/object/flatten.ts","../../../helpers/_shared/_walkPropertyPath.ts","../../../helpers/object/parsePropertyPath.ts","../../../helpers/object/get.ts","../../../helpers/object/groupBy.ts","../../../helpers/object/invert.ts","../../../helpers/object/isEmpty.ts","../../../helpers/object/isNonEmpty.ts","../../../helpers/string/kebabCase.ts","../../../helpers/object/kebabCaseKeys.ts","../../../helpers/object/map.ts","../../../helpers/object/mergeDeep.ts","../../../helpers/object/omit.ts","../../../helpers/object/omitBy.ts","../../../helpers/string/pascalCase.ts","../../../helpers/object/pascalCaseKeys.ts","../../../helpers/object/pick.ts","../../../helpers/object/pickBy.ts","../../../helpers/guard/isNullish.ts","../../../helpers/object/removeUndefinedNull.ts","../../../helpers/json/parseStrict.ts","../../../helpers/json/safeParseStrict.ts","../../../helpers/object/safeJsonParse.ts","../../../helpers/object/set.ts","../../../helpers/string/snakeCase.ts","../../../helpers/object/snakeCaseKeys.ts","../../../helpers/object/sortKeys.ts","../../../helpers/string/titleCase.ts","../../../helpers/object/titleCaseKeys.ts","../../../helpers/object/unflatten.ts","../../../helpers/object/unset.ts","../../../helpers/object/update.ts"],"sourcesContent":["/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Converts a string to camelCase.\n * Handles PascalCase, kebab-case, snake_case, spaces, and mixed formats.\n *\n * An embedded run of capitals is treated as an acronym boundary: only its last letter starts\n * the next word, the rest are lowercased (matching lodash's `camelCase` convention) — so an\n * already-camelCase identifier containing an acronym is not left untouched.\n * @param str - The string to convert\n * @returns String in camelCase\n * @example\n * camelCase('hello-world')\n * // => 'helloWorld'\n * camelCase('user_name')\n * // => 'userName'\n * camelCase('userID')\n * // => 'userId' (acronym boundary, not left as-is)\n * @since 1.9.0\n */\nexport function camelCase(str: string): string;\nexport function camelCase(str: undefined): undefined;\nexport function camelCase(str: null): null;\nexport function camelCase(str: string | undefined | null): string | undefined | null {\n if (str === undefined || str === null) return str;\n const words = str\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/([A-Z])([A-Z][a-z])/g, '$1 $2')\n .split(/[\\s_-]+/)\n .filter(Boolean);\n if (words.length === 0) return '';\n return (\n words[0]!.toLowerCase() +\n words\n .slice(1)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('')\n );\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Keys that must never be set on a plain object (prototype-pollution guard).\n * @ignore\n */\nconst UNSAFE_KEY_LIST = ['__proto__', 'constructor', 'prototype'] as const;\n\n/** @ignore */\nexport type UnsafeKey = (typeof UNSAFE_KEY_LIST)[number];\n\nexport const UNSAFE_KEYS = /* @__PURE__ */ new Set<string>(UNSAFE_KEY_LIST);\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is a plain object.\n *\n * A plain object is created by `{}`, `new Object()`, or `Object.create(null)`.\n * Returns `false` for arrays, Date, Map, Set, RegExp, class instances, etc.\n *\n * @param value - The value to check\n * @returns True if value is a plain object\n * @example\n * isPlainObject({}) // => true\n * isPlainObject({ a: 1 }) // => true\n * isPlainObject(new Date()) // => false\n * isPlainObject([]) // => false\n * isPlainObject(null) // => false\n * @since 2.0.0\n */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object') return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\nimport { isPlainObject } from '../guard/isPlainObject.js';\n\nfunction transform(\n value: unknown,\n mapValue?: (value: unknown, key: string) => unknown,\n mapKey?: (key: string, value: unknown) => PropertyKey,\n): unknown {\n if (Array.isArray(value))\n return value.map((item, index) => {\n const recursed = transform(item, mapValue, mapKey);\n return mapValue ? mapValue(recursed, String(index)) : recursed;\n });\n if (isPlainObject(value)) {\n const result: Record<PropertyKey, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n const newKey = mapKey ? mapKey(key, val) : key;\n if (typeof newKey === 'string' && UNSAFE_KEYS.has(newKey)) continue;\n const recursed = transform(val, mapValue, mapKey);\n result[newKey] = mapValue ? mapValue(recursed, key) : recursed;\n }\n return result;\n }\n return value;\n}\n\n/**\n * Recursively transforms the keys and/or values of a plain object — the deep counterpart to\n * {@link map}, which only transforms the top level. Descends into nested plain objects and\n * arrays of them; `Date`, `Map`, `Set`, class instances, and primitives are left untouched\n * (only their position is walked into, matching {@link cloneDeep}'s notion of what counts\n * as a plain-data node worth recursing into).\n *\n * Both callbacks are optional and default to identity (no transformation). `mapKey` is called\n * with the *original* key and value (before any recursive value transform); `mapValue` receives\n * the already-recursed value. Entries whose mapped key is a prototype-polluting string\n * (`__proto__`, `constructor`, `prototype`) are silently skipped, same as {@link map}.\n *\n * Array elements also go through `mapValue` (with their stringified index as `key`, since\n * arrays have no property keys of their own) — so values inside a plain array, not just object\n * properties, get transformed too. `mapKey` is never called for array elements, since there is\n * no key to rename.\n *\n * @param obj - The value to transform (typically an object, or an array of objects)\n * @param mapValue - Callback called with `(value, key)` for each entry's (already-recursed) value.\n * For array elements, `key` is the element's index as a string. Defaults to identity.\n * @param mapKey - Callback called with `(key, value)` for each object entry. Defaults to identity.\n * @returns A new value with every plain-object key/value transformed\n * @example\n * mapDeep({ a: { b: 1 } }, v => (typeof v === 'number' ? v * 10 : v))\n * // => { a: { b: 10 } }\n * @example\n * mapDeep({ user_name: 'Alice' }, undefined, key => key.toUpperCase())\n * // => { USER_NAME: 'Alice' }\n * @example\n * mapDeep({ tags: [1, 2, 3] }, v => (typeof v === 'number' ? v * 10 : v))\n * // => { tags: [10, 20, 30] }\n * @since 3.0.3\n */\nexport function mapDeep<T>(\n obj: T,\n mapValue?: (value: unknown, key: string) => unknown,\n mapKey?: (key: string, value: unknown) => PropertyKey,\n): T {\n return transform(obj, mapValue, mapKey) as T;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { camelCase } from '../string/camelCase.js';\nimport { mapDeep } from './mapDeep.js';\n\n/**\n * Recursively transforms every key of a plain object (including keys nested inside arrays and\n * nested objects) to camelCase. Handles snake_case, kebab-case, PascalCase, and space-separated\n * keys. Non-plain-object values (arrays' items aside) — `Date`, `Map`, `Set`, class instances,\n * primitives — are left untouched, only their position is walked into. An entry whose\n * transformed key is a prototype-polluting string (`__proto__`, `constructor`, `prototype`) is\n * silently skipped, same as the rest of `@helpers4/object`.\n * @param value - The object (or array of objects) to transform\n * @returns A new value with every plain-object key converted to camelCase\n * @example\n * camelCaseKeys({ user_name: 'Alice', home_address: { zip_code: '12345' } })\n * // => { userName: 'Alice', homeAddress: { zipCode: '12345' } }\n * @since 3.0.3\n */\nexport function camelCaseKeys<T>(value: T): T {\n return mapDeep(value, undefined, camelCase);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Creates a shallow copy of a value — one level deep, unlike {@link cloneDeep}.\n *\n * Unlike a plain `{ ...value }` spread, this correctly reconstructs `Date`,\n * `Map`, `Set`, and arrays instead of producing an empty (or wrong-shaped)\n * plain object for them. Primitives are returned as-is. Any other object\n * (including class instances not listed above) has its own enumerable string\n * keys shallow-copied into a plain object — the same fallback `cloneDeep`\n * uses, so the two stay consistent for types neither one special-cases.\n *\n * @param value - The value to shallow-clone\n * @returns A shallow copy of `value`\n * @example\n * clone({ a: { b: 1 } })\n * // => { a: { b: 1 } } — new object, but `a` is the *same* nested reference\n * @example\n * clone(new Date('2024-01-01')) // => new Date with the same timestamp\n * clone(new Map([['a', 1]])) // => new Map with the same entries\n * clone([1, 2, 3]) // => new array, same elements\n * @since 3.0.0\n */\nexport function clone<T>(value: T): T {\n if (value === null || typeof value !== 'object') return value;\n if (value instanceof Date) return new Date(value.getTime()) as T;\n if (value instanceof Map) return new Map(value) as T;\n if (value instanceof Set) return new Set(value) as T;\n if (Array.isArray(value)) return [...value] as T;\n\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(value)) {\n if (!UNSAFE_KEYS.has(key)) {\n result[key] = (value as Record<string, unknown>)[key];\n }\n }\n return result as T;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Creates a deep copy of an object or array.\n *\n * Recursively clones own enumerable string keys. `Date` instances are\n * reconstructed with the same epoch value. Prototype-polluting keys\n * (`__proto__`, `constructor`, `prototype`) are silently skipped.\n * Does **not** handle circular references.\n *\n * **Limitation:** symbol-keyed own properties are **not** copied — only string\n * keys are processed. Use `structuredClone` if symbol propagation is required.\n *\n * @param obj - The value to clone\n * @returns A deep copy of `obj`\n * @example\n * cloneDeep({ a: { b: [1, 2] } })\n * // => { a: { b: [1, 2] } } — fully independent copy\n *\n * cloneDeep(new Date('2024-01-01'))\n * // => Date with the same timestamp\n *\n * // Primitives pass through unchanged\n * cloneDeep(42) // => 42\n * cloneDeep(null) // => null\n * @since 1.9.0\n */\nexport function cloneDeep<T>(obj: T): T {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (obj instanceof Date) {\n return new Date(obj.getTime()) as T;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(item => cloneDeep(item)) as T;\n }\n\n const cloned = {} as T;\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key) && !UNSAFE_KEYS.has(key)) {\n cloned[key] = cloneDeep(obj[key]);\n }\n }\n\n return cloned;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Removes all entries with falsy values (`false`, `null`, `undefined`, `0`, `\"\"`, `NaN`) from an object.\n * Own keys that are prototype-polluting strings (`__proto__`, `constructor`, `prototype`) are\n * silently skipped.\n * @param obj - The source object\n * @returns A new object containing only entries with truthy values\n * @example\n * compact({ a: 1, b: null, c: '', d: 0, e: 'hello' })\n * // => { a: 1, e: 'hello' }\n * @since 2.0.0\n */\nexport function compact<T extends Record<string, unknown>>(obj: T): Partial<T>;\nexport function compact(obj: undefined): undefined;\nexport function compact(obj: null): null;\nexport function compact<T extends Record<string, unknown>>(obj: T | undefined | null): Partial<T> | undefined | null {\n if (obj === undefined || obj === null) return obj;\n const result: Partial<T> = {};\n for (const key of Object.keys(obj) as (keyof T)[]) {\n if (UNSAFE_KEYS.has(key as string)) continue;\n if (obj[key]) {\n result[key] = obj[key];\n }\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { isPlainObject } from '../guard/isPlainObject';\n\n/**\n * Recursive structural array equality.\n *\n * Two arrays are equal when they have the same length and each pair of\n * elements at the same index is structurally equal:\n * - Arrays recurse with `equalsDeep`.\n * - Plain objects recurse key-by-key with structural comparison.\n * - `Date` instances are compared by their epoch value.\n * - All other values use strict equality (`===`), which means `NaN !== NaN`\n * and special objects (Map, Set, RegExp, Promise, class instances\\u2026) are\n * compared by reference.\n *\n * For positional one-level comparison use {@link equalsShallow}. For\n * order-independent comparison use {@link equalsUnordered}.\n *\n * @param arrA - First array to compare\n * @param arrB - Second array to compare\n * @returns `true` if arrays are deeply equal, `false` otherwise.\n * @since 2.0.0\n */\nexport function equalsDeep<T>(arrA: readonly T[], arrB: readonly T[]): boolean {\n if (arrA === arrB) {\n return true;\n }\n if (!Array.isArray(arrA) || !Array.isArray(arrB)) {\n return false;\n }\n if (arrA.length !== arrB.length) {\n return false;\n }\n for (let i = 0; i < arrA.length; i++) {\n if (!valuesEqual(arrA[i], arrB[i])) {\n return false;\n }\n }\n return true;\n}\n\nfunction valuesEqual(a: unknown, b: unknown): boolean {\n if (a === b) {\n return true;\n }\n if (Array.isArray(a) && Array.isArray(b)) {\n return equalsDeep(a, b);\n }\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() === b.getTime();\n }\n if (isPlainObject(a) && isPlainObject(b)) {\n const ao = a as Record<string, unknown>;\n const bo = b as Record<string, unknown>;\n const keysA = Object.keys(ao);\n if (keysA.length !== Object.keys(bo).length) {\n return false;\n }\n for (const key of keysA) {\n if (!Object.prototype.hasOwnProperty.call(bo, key)) {\n return false;\n }\n if (!valuesEqual(ao[key], bo[key])) {\n return false;\n }\n }\n return true;\n }\n return false;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { ensureDate } from './ensureDate';\nimport type { DateLike } from './types';\n\n/**\n * Checks if a timestamp is likely in seconds (Java/Unix style) vs milliseconds (JavaScript style)\n * @param timestamp - The timestamp to check\n * @returns True if timestamp appears to be in seconds\n * @since 1.9.0\n */\nexport function isTimestampInSeconds(timestamp: number): boolean {\n // Timestamps before year 2001 in milliseconds are less than 10^10\n // Use Math.abs to correctly handle negative timestamps (before epoch)\n return Math.abs(timestamp) < 10000000000;\n}\n\n/**\n * Converts a timestamp to JavaScript milliseconds format\n * @param timestamp - The timestamp (in seconds or milliseconds)\n * @returns Timestamp in milliseconds\n * @since 1.9.0\n */\nexport function normalizeTimestamp(timestamp: number): number {\n return isTimestampInSeconds(timestamp) ? timestamp * 1000 : timestamp;\n}\n\n/**\n * Converts a date to a timestamp in **seconds** (epoch seconds).\n *\n * Use this when sending a date to a backend API that expects seconds\n * (e.g. Java `Instant.getEpochSecond()`, Python `time.time()`).\n *\n * @param date - The date to convert\n * @returns Seconds since the Unix epoch, or `null` for invalid input\n * @example\n * toSeconds('2025-01-19T12:00:00Z') // => 1737288000\n * toSeconds(null) // => null\n *\n * @since 2.0.0\n */\nexport function toSeconds(date: DateLike): number | null {\n const d = ensureDate(date);\n if (!d) return null;\n return Math.floor(d.getTime() / 1000);\n}\n\n/**\n * Converts a date to a timestamp in **milliseconds** (epoch millis).\n *\n * Use this when you need a plain number from a `DateLike` value\n * (e.g. for `Date.now()` comparisons, localStorage, or JS-native APIs).\n *\n * @param date - The date to convert\n * @returns Milliseconds since the Unix epoch, or `null` for invalid input\n * @example\n * toMillis('2025-01-19T12:00:00Z') // => 1737288000000\n * toMillis(null) // => null\n *\n * @since 2.0.0\n */\nexport function toMillis(date: DateLike): number | null {\n const d = ensureDate(date);\n if (!d) return null;\n return d.getTime();\n}\n\n/**\n * Creates a `Date` from a timestamp in **seconds**.\n *\n * Use this when receiving a timestamp from a backend that sends seconds\n * (e.g. Java `Instant.getEpochSecond()`). No heuristic — the input is\n * always treated as seconds.\n *\n * @param seconds - Seconds since the Unix epoch\n * @returns A valid `Date`, or `null` for `NaN` / non-finite input\n * @example\n * fromSeconds(1737288000) // => Date('2025-01-19T12:00:00Z')\n * fromSeconds(0) // => Date('1970-01-01T00:00:00Z')\n * fromSeconds(NaN) // => null\n *\n * @since 2.0.0\n */\nexport function fromSeconds(seconds: number): Date | null {\n if (!Number.isFinite(seconds)) return null;\n return new Date(seconds * 1000);\n}\n\n/**\n * Creates a `Date` from a timestamp in **milliseconds**.\n *\n * Use this when receiving a timestamp from a JS-native source\n * (e.g. `Date.now()`, `performance.timeOrigin`). No heuristic — the\n * input is always treated as milliseconds.\n *\n * @param ms - Milliseconds since the Unix epoch\n * @returns A valid `Date`, or `null` for `NaN` / non-finite input\n * @example\n * fromMillis(1737288000000) // => Date('2025-01-19T12:00:00Z')\n * fromMillis(0) // => Date('1970-01-01T00:00:00Z')\n * fromMillis(NaN) // => null\n *\n * @since 2.0.0\n */\nexport function fromMillis(ms: number): Date | null {\n if (!Number.isFinite(ms)) return null;\n return new Date(ms);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { normalizeTimestamp } from './timestamp';\nimport type { DateLike } from './types';\n\n/**\n * Type guard that checks whether a value is a `Temporal.Instant` or\n * `Temporal.ZonedDateTime`.\n *\n * Duck-types the `epochMilliseconds` property rather than using `instanceof`,\n * so values crossing a realm boundary (vm context, worker, iframe) are still\n * recognized correctly.\n */\nfunction isEpochMillisecondsLike(value: unknown): value is Temporal.Instant | Temporal.ZonedDateTime {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'epochMilliseconds' in value &&\n typeof value.epochMilliseconds === 'number'\n );\n}\n\n/**\n * Safely converts a date-like value to a valid `Date` object, or returns `null`.\n *\n * Accepts `Date`, timestamps (seconds or milliseconds, auto-detected), date strings,\n * and objects with an `epochMilliseconds` property (e.g. `Temporal.Instant`,\n * `Temporal.ZonedDateTime`).\n * Returns `null` for `null`, `undefined`, empty strings, `0`, and any value that\n * produces an invalid `Date`.\n *\n * This is the date equivalent of {@link ensureArray} — it normalizes flexible\n * input into a guaranteed type (or a safe fallback).\n *\n * @param input - A date-like value to convert\n * @returns A valid `Date` object, or `null` if the input is invalid\n * @example\n * ensureDate('2025-01-19T12:00:00Z') // => Date\n * ensureDate(1737290400) // => Date (from Unix seconds)\n * ensureDate(1737290400000) // => Date (from milliseconds)\n * ensureDate(new Date()) // => Date (same reference)\n * ensureDate(null) // => null\n * ensureDate('invalid') // => null\n *\n * @see {@link DateLike} for the accepted input types\n * @since 2.0.0\n */\nexport function ensureDate(input: DateLike | null | undefined): Date | null {\n if (input === null || input === undefined || input === '' || input === 0) {\n return null;\n }\n\n if (input instanceof Date) {\n return isNaN(input.getTime()) ? null : input;\n }\n\n if (isEpochMillisecondsLike(input)) {\n const date = new Date(input.epochMilliseconds);\n return isNaN(date.getTime()) ? null : date;\n }\n\n if (typeof input === 'number') {\n const normalized = normalizeTimestamp(input);\n const date = new Date(normalized);\n return isNaN(date.getTime()) ? null : date;\n }\n\n if (typeof input === 'string') {\n const date = new Date(input);\n return isNaN(date.getTime()) ? null : date;\n }\n\n return null;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { ensureDate } from './ensureDate';\nimport type { DateLike } from './types';\n\n/**\n * Options for date comparison\n * @since 2.0.0\n */\nexport interface DateCompareOptions {\n /**\n * Comparison precision\n * - 'milliseconds': Compare all including milliseconds (default)\n * - 'seconds': Ignore milliseconds, compare to the second\n * - 'minutes': Ignore seconds and milliseconds, compare to the minute\n * - 'hours': Ignore minutes, seconds and milliseconds, compare to the hour\n * - 'days': Compare only the date part (ignore time completely)\n * - 'months': Compare only year and month\n * - 'years': Compare only year\n */\n precision?: 'milliseconds' | 'seconds' | 'minutes' | 'hours' | 'days' | 'months' | 'years';\n}\n\n/**\n * Comparison of two dates.\n *\n * Accepts any {@link DateLike} input (Date, timestamp, or date string).\n *\n * @param dateA - First date to compare\n * @param dateB - Second date to compare\n * @param options - Comparison options\n * @returns `true` if dates are identical according to the specified precision, `false` otherwise\n * @example\n * compare('2025-01-19', new Date('2025-01-19T08:00:00Z'), { precision: 'days' })\n * // => true\n * @since 2.0.0\n */\nexport function compare(dateA: DateLike, dateB: DateLike, options: DateCompareOptions = {}): boolean {\n const { precision = 'milliseconds' } = options;\n\n const a = ensureDate(dateA);\n const b = ensureDate(dateB);\n\n // Any invalid → not equal\n if (a === null || b === null) {\n return false;\n }\n\n switch (precision) {\n case 'years':\n return a.getFullYear() === b.getFullYear();\n\n case 'months':\n return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();\n\n case 'days':\n return a.toDateString() === b.toDateString();\n\n case 'hours': {\n const hoursA = Math.floor(a.getTime() / (1000 * 60 * 60));\n const hoursB = Math.floor(b.getTime() / (1000 * 60 * 60));\n return hoursA === hoursB;\n }\n\n case 'minutes': {\n const minutesA = Math.floor(a.getTime() / (1000 * 60));\n const minutesB = Math.floor(b.getTime() / (1000 * 60));\n return minutesA === minutesB;\n }\n\n case 'seconds': {\n const secondsA = Math.floor(a.getTime() / 1000);\n const secondsB = Math.floor(b.getTime() / 1000);\n return secondsA === secondsB;\n }\n\n case 'milliseconds':\n default:\n return a.getTime() === b.getTime();\n }\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Determines if a value is a special object that should not have its properties compared deeply.\n * Special objects include: Date, Function, Promise, Observable, RegExp, Error, Map, Set, WeakMap, WeakSet, etc.\n * \n * @param value - The value to check\n * @returns `true` if the value is a special object, `false` otherwise\n * @since 2.0.0\n */\nexport function isSpecialObject(value: unknown): boolean {\n if (value === null || value === undefined) {\n return false;\n }\n\n // Functions are special objects\n if (typeof value === 'function') {\n return true;\n }\n\n // Non-objects are not special\n if (typeof value !== 'object') {\n return false;\n }\n\n // Arrays are not considered special objects for our purposes\n if (Array.isArray(value)) {\n return false;\n }\n\n // Check for built-in special objects\n if (\n value instanceof Date ||\n value instanceof Promise ||\n value instanceof RegExp ||\n value instanceof Error ||\n value instanceof Map ||\n value instanceof Set ||\n value instanceof WeakMap ||\n value instanceof WeakSet ||\n value instanceof ArrayBuffer ||\n value instanceof DataView\n ) {\n return true;\n }\n\n // Check for Observable (RxJS or similar)\n if (value.constructor?.name === 'Observable') {\n return true;\n }\n\n // Check for DOM elements (if in browser environment)\n if (typeof HTMLElement !== 'undefined' && value instanceof HTMLElement) {\n return true;\n }\n\n // Check for other built-in types by constructor name\n const constructorName = value.constructor?.name;\n if (constructorName && [\n 'Buffer', // Node.js Buffer\n 'URL', // Web URL API\n 'URLSearchParams',\n 'File', // Web File API\n 'Blob', // Web Blob API\n 'FormData', // Web FormData API\n 'Headers', // Web Headers API\n 'Request', // Web Request API\n 'Response', // Web Response API\n 'EventTarget', // Web EventTarget API\n 'Symbol' // Symbol objects\n ].includes(constructorName)) {\n return true;\n }\n\n return false;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { equalsDeep as arrayDeepEquals } from '../array/equalsDeep';\nimport { compare as compareDate } from '../date/compare';\nimport { isSpecialObject } from '../guard/isSpecialObject';\n\n/**\n * Per-key diff result. Each entry tells what differs between the two\n * objects:\n * - `\"onlyA\"` \\u2014 the key exists only on the first input.\n * - `\"onlyB\"` \\u2014 the key exists only on the second input.\n * - `false` \\u2014 both inputs have the key but the values differ.\n * - nested `DiffResult` \\u2014 plain-object values that differ deeper.\n *\n * @since 2.0.0\n */\nexport interface DiffResult {\n [key: string]: 'onlyA' | 'onlyB' | false | DiffResult;\n}\n\n/**\n * Options for {@link diff}.\n * @since 2.0.0\n */\nexport interface DiffOptions {\n /**\n * Maximum recursion depth for nested plain objects. Defaults to\n * `Infinity` (full structural diff).\n *\n * - `0` compares values at the top-level only with strict equality.\n * - `1` compares the first level of nested objects with strict equality.\n * - `Infinity` recurses through every plain-object level.\n *\n * Arrays, `Date` and special objects (Map, Set, RegExp\\u2026) are always\n * leaf-compared (via {@link arrayDeepEquals}, epoch comparison, or\n * reference equality respectively) regardless of `depth`.\n */\n depth?: number;\n}\n\n/**\n * Structural object diff.\n *\n * Returns `true` when both inputs are deeply equal, otherwise a\n * {@link DiffResult} describing the differences key by key.\n *\n * Comparison rules:\n * - Same reference \\u2192 `true`.\n * - Either side is `null`/`undefined` (and not both) \\u2192 `false`.\n * - Both `Date` \\u2192 epoch comparison.\n * - Both arrays \\u2192 compared with `array/equalsDeep` (leaf, no diff drill-down).\n * - Special objects (Map, Set, RegExp, Promise, class instances\\u2026) \\u2192 reference equality.\n * - Plain objects \\u2192 key-by-key, recursing up to `options.depth` levels.\n * - Mixed types (e.g. array vs object, Date vs object) \\u2192 `false`.\n *\n * For a boolean wrapper see {@link equalsDeep} from this category.\n * For a one-level boolean check see {@link equalsShallow} from this category.\n *\n * @param objA - First value (object, `null`, or `undefined`).\n * @param objB - Second value (object, `null`, or `undefined`).\n * @param options - See {@link DiffOptions}.\n * @returns `true` when equal, otherwise a {@link DiffResult}, or `false` for incompatible types.\n * @since 2.0.0\n */\nexport function diff(\n objA: object | undefined | null,\n objB: object | undefined | null,\n options: DiffOptions = {},\n): true | false | DiffResult {\n const depth = options.depth ?? Infinity;\n\n // Quick reference equality check\n if (objA === objB) {\n return true;\n }\n\n // Handle null/undefined cases\n if (objA == null || objB == null) {\n return false;\n }\n\n // Handle Date objects\n if (objA instanceof Date && objB instanceof Date) {\n return compareDate(objA, objB);\n }\n\n // Handle Arrays at root level\n if (Array.isArray(objA) && Array.isArray(objB)) {\n return arrayDeepEquals(objA, objB);\n }\n if (Array.isArray(objA) || Array.isArray(objB)) {\n return false;\n }\n\n // Handle special objects - compare by reference only\n if (isSpecialObject(objA) || isSpecialObject(objB)) {\n return objA === objB;\n }\n\n // Plain object detailed comparison\n return diffPlainObjects(objA, objB, depth);\n}\n\nfunction diffPlainObjects(\n objA: object,\n objB: object,\n depth: number,\n): true | DiffResult {\n const keys = Array.from(new Set([...Object.keys(objA), ...Object.keys(objB)]));\n const differences: DiffResult = Object.create(null) as DiffResult;\n\n for (const key of keys) {\n const hasA = Object.prototype.hasOwnProperty.call(objA, key);\n const hasB = Object.prototype.hasOwnProperty.call(objB, key);\n\n if (!hasA && hasB) {\n differences[key] = 'onlyB';\n continue;\n }\n if (hasA && !hasB) {\n differences[key] = 'onlyA';\n continue;\n }\n\n const valueA = (objA as Record<string, unknown>)[key];\n const valueB = (objB as Record<string, unknown>)[key];\n\n if (valueA === valueB) {\n continue;\n }\n\n if (Array.isArray(valueA) && Array.isArray(valueB)) {\n if (!arrayDeepEquals(valueA, valueB)) {\n differences[key] = false;\n }\n continue;\n }\n if (Array.isArray(valueA) || Array.isArray(valueB)) {\n differences[key] = false;\n continue;\n }\n\n if (valueA instanceof Date && valueB instanceof Date) {\n if (!compareDate(valueA, valueB)) {\n differences[key] = false;\n }\n continue;\n }\n if (valueA instanceof Date || valueB instanceof Date) {\n differences[key] = false;\n continue;\n }\n\n if (isSpecialObject(valueA) || isSpecialObject(valueB)) {\n // valueA === valueB already handled above, so any special-object pair\n // that reaches here must differ.\n differences[key] = false;\n continue;\n }\n\n const bothPlainObjects =\n valueA !== null && valueB !== null &&\n typeof valueA === 'object' && typeof valueB === 'object';\n\n if (!bothPlainObjects) {\n differences[key] = false;\n continue;\n }\n\n if (depth <= 0) {\n // depth budget exhausted \\u2192 strict-equal nested objects only match by reference\n differences[key] = false;\n continue;\n }\n\n const nested = diffPlainObjects(valueA as object, valueB as object, depth - 1);\n if (nested !== true) {\n differences[key] = nested;\n }\n }\n\n return Object.keys(differences).length > 0 ? differences : true;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { diff } from './diff';\n\n/**\n * Recursive structural object equality.\n *\n * Boolean wrapper around {@link diff} \\u2014 returns `true` when the two values\n * are deeply equal according to the same rules. Use this when you only\n * need a yes/no answer; use {@link diff} when you also need to know\n * *what* differs.\n *\n * For a one-level boolean check use {@link equalsShallow}.\n *\n * @param objA - First value (object, `null`, or `undefined`).\n * @param objB - Second value (object, `null`, or `undefined`).\n * @returns `true` if both inputs are deeply equal, `false` otherwise.\n * @since 2.0.0\n */\nexport function equalsDeep(\n objA: object | undefined | null,\n objB: object | undefined | null,\n): boolean {\n return diff(objA, objB) === true;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * One-level (shallow) object equality.\n *\n * Two objects are equal when they share the exact same set of own\n * enumerable string keys and each pair of values satisfies strict equality\n * (`===`). No recursion: nested objects/arrays are compared by reference.\n *\n * Falls back to strict equality when either input is `null`, `undefined`\n * or not an object \\u2014 so primitives match if and only if they are `===`.\n * Arrays are not supported; they always return `false` (unless identical\n * references). Use `array/equalsShallow` instead.\n *\n * For recursive structural comparison use {@link equalsDeep}. For a diff\n * structure use {@link diff}.\n *\n * @param objA - First value to compare\n * @param objB - Second value to compare\n * @returns `true` if values are shallowly equal, `false` otherwise.\n * @since 2.0.0\n */\nexport function equalsShallow(objA: unknown, objB: unknown): boolean {\n if (objA === objB) {\n return true;\n }\n if (\n objA === null || objB === null ||\n typeof objA !== 'object' || typeof objB !== 'object'\n ) {\n return false;\n }\n const a = objA as Record<string, unknown>;\n const b = objB as Record<string, unknown>;\n if (Array.isArray(objA) || Array.isArray(objB)) {\n return false;\n }\n const keysA = Object.keys(a);\n if (keysA.length !== Object.keys(b).length) {\n return false;\n }\n for (const key of keysA) {\n if (!Object.prototype.hasOwnProperty.call(b, key) || a[key] !== b[key]) {\n return false;\n }\n }\n return true;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { isPlainObject } from '../guard/isPlainObject.js';\n\nfunction flattenInto(obj: Record<string, unknown>, prefix: string, result: Record<string, unknown>): void {\n for (const [key, value] of Object.entries(obj)) {\n const path = prefix ? `${prefix}.${key}` : key;\n if (isPlainObject(value) && Object.keys(value).length > 0) {\n flattenInto(value, path, result);\n } else {\n result[path] = value;\n }\n }\n}\n\n/**\n * Flattens a nested object into a single-level object whose keys are the\n * dot-notation path to each leaf value. The inverse of {@link unflatten}.\n *\n * Only **plain objects** are recursed into — arrays, `Date`, `Map`, `RegExp`,\n * class instances, and empty plain objects `{}` are kept as opaque leaf\n * values. This keeps `flatten`/`unflatten` a clean, invertible pair: arrays\n * can't be losslessly told apart from plain objects once reduced to dotted\n * keys, so this implementation doesn't attempt it.\n *\n * Caveat shared by every dotted-path flattening scheme: a key that itself\n * contains a literal `.` is indistinguishable from real nesting once\n * flattened (`{ 'a.b': 1 }` and `{ a: { b: 1 } }` both produce `{ 'a.b': 1 }`).\n *\n * @param obj - The object to flatten\n * @returns A single-level object with dot-notation keys\n * @example\n * flatten({ a: { b: { c: 1 }, d: 2 } })\n * // => { 'a.b.c': 1, 'a.d': 2 }\n * @example\n * flatten({ a: [1, 2], b: new Date(0) })\n * // => { a: [1, 2], b: Date } (arrays and special objects stay as leaves)\n * @since 3.0.0\n */\nexport function flatten(obj: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n flattenInto(obj, '', result);\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Walks a value through a sequence of keys, returning the resolved value or `undefined` if any\n * step along the way is missing or not an object. Pure traversal only — string-path parsing\n * (`'a.b.c'` → keys) and default-value substitution are the caller's job.\n *\n * Shared by `object/get.ts` and any `*By`-style accessor elsewhere that needs the same\n * \"resolve a path against a value\" runtime behavior — kept dependency-free (per the `_shared/`\n * convention) so it can be used from any category without adding a cross-category import for\n * this specific piece.\n * @ignore\n */\nexport function walkPropertyPath(value: unknown, keys: readonly PropertyKey[]): unknown {\n let result = value;\n for (const key of keys) {\n if (result == null || typeof result !== 'object') {\n return undefined;\n }\n result = (result as Record<PropertyKey, unknown>)[key];\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n// `g` flag: stateful — callers must reset lastIndex before each use.\nconst BRACKET = /\\[(\\d+)\\]/g;\n\n// Cache parsed paths: real-world callers (get/set) tend to reuse a small, fixed\n// set of literal path strings repeatedly, so parsing the same string on every\n// call is pure waste. Capped so a caller who *does* build many distinct,\n// dynamic path strings can't grow this into an unbounded memory leak.\nconst MAX_CACHE_SIZE = 500;\nconst pathCache = /* @__PURE__ */ new Map<string, readonly (string | number)[]>();\n\n/**\n * Parses a dot/bracket-notation property path into an array of string/number\n * key segments — the same notation accepted by {@link get} and {@link set}.\n *\n * - Dot separators (`.`) split segments; each segment becomes a string key.\n * - Bracket indices (`[n]`) become number keys.\n * - A leading `.` is treated as \"current level\" and stripped before parsing,\n * so `.[0]` ≡ `[0]` and `.a.b` ≡ `a.b`.\n * - Empty string (or a bare `.`) returns `['']` (addresses the `''` key on the root object).\n * - Consecutive dots (`a..b`) produce an empty-string segment: `['a', '', 'b']`.\n *\n * Results are cached (up to 500 distinct path strings, oldest evicted first)\n * since real-world callers tend to reuse a small, fixed set of literal paths.\n *\n * @param path - The dot/bracket-notation path string to parse\n * @returns The parsed key segments\n * @throws {RangeError} When non-bracket text trails the last `]` within a\n * dot-segment (e.g. `'a[0]b'` is ambiguous — use `'a[0].b'` instead)\n * @example\n * parsePropertyPath('a.b.c') // => ['a', 'b', 'c']\n * parsePropertyPath('layers[1].x') // => ['layers', 1, 'x']\n * parsePropertyPath('.[0]') // => [0] (leading dot stripped)\n * parsePropertyPath('a..b') // => ['a', '', 'b'] (empty segment preserved)\n * @since 3.0.0\n */\nexport function parsePropertyPath(path: string): readonly (string | number)[] {\n const cached = pathCache.get(path);\n if (cached !== undefined) return cached;\n\n const result = Object.freeze(parseUncached(path));\n\n // MAX_CACHE_SIZE is a fixed positive constant, so size >= MAX_CACHE_SIZE always\n // implies the cache is non-empty — the iterator's first key is never undefined here.\n if (pathCache.size >= MAX_CACHE_SIZE) {\n pathCache.delete(pathCache.keys().next().value!);\n }\n pathCache.set(path, result);\n\n return result;\n}\n\nfunction parseUncached(path: string): (string | number)[] {\n if (path === '') return [''];\n if (path[0] === '.') path = path.slice(1);\n if (path === '') return [''];\n const result: (string | number)[] = [];\n // Split on `.` first so consecutive dots produce empty segments, then parse `[n]` within each.\n for (const dotSegment of path.split('.')) {\n BRACKET.lastIndex = 0;\n let last = 0;\n let match: RegExpExecArray | null;\n while ((match = BRACKET.exec(dotSegment)) !== null) {\n // String prefix before this [n] — omit only when the segment starts with '['.\n if (match.index > last) result.push(dotSegment.slice(last, match.index));\n result.push(parseInt(match[1], 10));\n last = BRACKET.lastIndex;\n }\n if (last === 0) {\n // No brackets found — push the whole dot-segment as a string key.\n result.push(dotSegment);\n } else if (last < dotSegment.length) {\n // Trailing non-bracket text after the last ']' (e.g. 'a[0]b') — ambiguous and\n // almost always a mistake. Throw rather than silently drop 'b'.\n throw new RangeError(\n `parsePropertyPath: non-bracket text '${dotSegment.slice(last)}' after ']' in segment '${dotSegment}' — use 'a[0].b' instead of 'a[0]b'`,\n );\n }\n // last === dotSegment.length: segment ended right after the last ']', nothing to push.\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { walkPropertyPath } from '../_shared/_walkPropertyPath.js';\nimport { parsePropertyPath } from './parsePropertyPath.js';\nimport type { DeepGet, ParsePath } from './_types.js';\n\n/**\n * Gets a value from an object using a dot/bracket-notated path or explicit key array.\n *\n * **Two path forms are supported:**\n *\n * 1. **String path** — dot notation (`'a.b.c'`) and bracket notation (`'layers[1].name'`)\n * are both accepted and mixed freely.\n * - Dot segments are always string keys: `'a.1'` → key `'1'` (string).\n * - Bracket segments are always number keys: `'a[1]'` → key `1` (number).\n * - String literal paths give **full compile-time type inference** on the return type.\n * - Dynamic (non-literal) strings return `unknown`.\n *\n * 2. **Key array** (`PropertyKey[]`) — explicit array of `string | number | symbol` keys,\n * no parsing performed. Enables symbol-keyed traversal and compile-time type inference:\n * `get(obj, ['a', 'b'] as const)` infers the return type from the path.\n *\n * Both forms support **all objects** (plain objects, arrays, class instances).\n * Symbol keys are only reachable via the key-array form.\n *\n * @param obj - The object to read from\n * @param path - Dot/bracket-notation string literal or explicit `PropertyKey[]`\n * @param defaultValue - Returned when the path is absent or resolves to `undefined`\n * @returns The value at the path, or `defaultValue`\n * @example\n * get({ a: { b: { c: 42 } } }, 'a.b.c') // => 42 (inferred: number | undefined)\n * get({ layers: [{ name: 'bg' }] }, 'layers[0].name') // => 'bg' (inferred: string | undefined)\n * get({ a: { b: 0 } }, 'a.b', 99) // => 0 (falsy values returned as-is)\n * get({ a: 1 }, 'b.c', 'default') // => 'default'\n *\n * const id = Symbol('id')\n * get({ [id]: 'alice' }, [id]) // => 'alice' (symbol key, inferred: string | undefined)\n * @since 1.9.0\n */\nexport function get<D>(obj: null | undefined, path: string | readonly PropertyKey[], defaultValue: D): D;\nexport function get(obj: null | undefined, path: string | readonly PropertyKey[]): undefined;\nexport function get<T extends object, const P extends string | readonly PropertyKey[]>(\n obj: T | null | undefined,\n path: P,\n defaultValue?: DeepGet<T, ParsePath<P>>,\n): DeepGet<T, ParsePath<P>> | undefined;\nexport function get(obj: unknown, path: string | readonly PropertyKey[], defaultValue?: unknown): unknown {\n if (obj == null) return defaultValue;\n const keys: readonly PropertyKey[] = typeof path === 'string' ? parsePropertyPath(path) : path;\n const result = walkPropertyPath(obj, keys);\n return result !== undefined ? result : defaultValue;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Groups an array of items by a key derived from each item.\n *\n * A thin, typed wrapper around `Object.groupBy` (ES2024) that works on\n * older targets and provides stricter return-type inference.\n * `null` and `undefined` are treated as empty arrays and return `{}`.\n * Items whose computed key is a prototype-polluting string (`__proto__`,\n * `constructor`, `prototype`) are silently skipped.\n *\n * @param items - The array to group\n * @param keyFn - Function that returns the group key for each item\n * @returns A record mapping each key to the array of items with that key\n * @example\n * groupBy([1, 2, 3, 4], n => n % 2 === 0 ? 'even' : 'odd')\n * // => { odd: [1, 3], even: [2, 4] }\n * groupBy(null, n => n % 2 === 0 ? 'even' : 'odd')\n * // => {}\n * @since 2.0.0\n */\nexport function groupBy<T, K extends PropertyKey>(\n items: readonly T[] | null | undefined,\n keyFn: (item: T) => K\n): Partial<Record<K, T[]>> {\n const result = {} as Partial<Record<K, T[]>>;\n if (items == null) return result;\n for (const item of items) {\n const key = keyFn(item);\n if (typeof key === 'string' && UNSAFE_KEYS.has(key)) continue;\n if (result[key] === undefined) {\n result[key] = [];\n }\n (result[key] as T[]).push(item);\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Returns a new object with keys and values swapped.\n * If multiple keys share the same value, the last one wins.\n * `null` and `undefined` are treated as empty objects and return `{}`.\n * Entries whose source key **or** value is a prototype-polluting string\n * (`__proto__`, `constructor`, `prototype`) are silently skipped.\n *\n * @param obj - The object whose keys and values are to be swapped\n * @returns A new object with values as keys and original keys as values\n * @example\n * invert({ a: 'x', b: 'y', c: 'z' })\n * // => { x: 'a', y: 'b', z: 'c' }\n *\n * invert({ one: 1, two: 2 })\n * // => { 1: 'one', 2: 'two' }\n *\n * invert(null)\n * // => {}\n * @since 2.0.0\n */\nexport function invert<K extends string, V extends PropertyKey>(obj: Record<K, V> | null | undefined): Record<V, K> {\n const result = {} as Record<V, K>;\n if (obj == null) return result;\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key) && !UNSAFE_KEYS.has(key)) {\n const val = obj[key as K];\n if (typeof val === 'string' && UNSAFE_KEYS.has(val)) continue;\n result[val] = key as unknown as K;\n }\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a plain object has no own enumerable string-keyed properties.\n * `null` and `undefined` are treated as empty objects and return `true`.\n *\n * Symbol-keyed properties are not counted. Use `Object.getOwnPropertySymbols`\n * separately if symbol keys matter for your use case.\n *\n * @param value - The object to check\n * @returns `true` if the object has no own enumerable string-keyed properties, or if `value` is `null`/`undefined`\n * @example\n * isEmpty({}) // => true\n * isEmpty(null) // => true\n * isEmpty(undefined) // => true\n * isEmpty({ a: 1 }) // => false\n * isEmpty({ a: undefined }) // => false (key exists)\n * @since 2.0.3\n */\nexport function isEmpty(value: Record<PropertyKey, unknown> | null | undefined): boolean {\n return value == null || Object.keys(value).length === 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a plain object has at least one own enumerable string-keyed property.\n * `null` and `undefined` are treated as empty objects and return `false`.\n *\n * Symbol-keyed properties are not counted. Use `Object.getOwnPropertySymbols`\n * separately if symbol keys matter for your use case.\n *\n * @param value - The object to check\n * @returns `true` if the object has at least one own enumerable string-keyed property; `false` for empty, `null`, or `undefined`.\n * Acts as a type guard: the `if` branch narrows `Record<PropertyKey, unknown> | null | undefined` to `Record<PropertyKey, unknown>`.\n * @example\n * isNonEmpty({ a: 1 }) // => true\n * isNonEmpty({}) // => false\n * isNonEmpty(null) // => false\n * isNonEmpty(undefined) // => false\n * @since 2.0.3\n */\nexport function isNonEmpty(value: Record<PropertyKey, unknown> | null | undefined): value is Record<PropertyKey, unknown> {\n return value != null && Object.keys(value).length > 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Converts a string to kebab-case.\n * Handles camelCase, PascalCase, snake_case, spaces, and mixed formats.\n * @param str - The string to convert\n * @returns String in kebab-case\n * @example\n * kebabCase('camelCase')\n * // => 'camel-case'\n * kebabCase('user_name')\n * // => 'user-name'\n * @since 1.9.0\n */\nexport function kebabCase(str: string): string;\nexport function kebabCase(str: undefined): undefined;\nexport function kebabCase(str: null): null;\nexport function kebabCase(str: string | undefined | null): string | undefined | null {\n if (str === undefined || str === null) return str;\n const words = str\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/([A-Z])([A-Z][a-z])/g, '$1 $2')\n .split(/[\\s_-]+/)\n .filter(Boolean);\n return words.join('-').toLowerCase();\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { kebabCase } from '../string/kebabCase.js';\nimport { mapDeep } from './mapDeep.js';\n\n/**\n * Recursively transforms every key of a plain object (including keys nested inside arrays and\n * nested objects) to kebab-case. Handles snake_case, camelCase, PascalCase, and space-separated\n * keys. Non-plain-object values — `Date`, `Map`, `Set`, class instances, primitives — are left\n * untouched, only their position is walked into. An entry whose transformed key is a\n * prototype-polluting string (`__proto__`, `constructor`, `prototype`) is silently skipped,\n * same as the rest of `@helpers4/object`.\n * @param value - The object (or array of objects) to transform\n * @returns A new value with every plain-object key converted to kebab-case\n * @example\n * kebabCaseKeys({ userName: 'Alice', homeAddress: { zipCode: '12345' } })\n * // => { 'user-name': 'Alice', 'home-address': { 'zip-code': '12345' } }\n * @since 3.0.3\n */\nexport function kebabCaseKeys<T>(value: T): T {\n return mapDeep(value, undefined, kebabCase);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Transforms the values and/or keys of a plain object in a single pass.\n *\n * Both callbacks are optional and default to identity (no transformation).\n * When `mapValue` is omitted the original values are preserved;\n * when `mapKey` is omitted the original keys are preserved.\n *\n * Note: if two different keys map to the same output key the last one wins\n * (insertion order). Entries whose mapped key is a prototype-polluting string\n * (`__proto__`, `constructor`, `prototype`) are silently skipped.\n *\n * @param obj - The source object\n * @param mapValue - Callback called with `(value, key)` for each entry.\n * Defaults to identity.\n * @param mapKey - Callback called with `(key, value)` for each entry.\n * Defaults to identity.\n * @returns A new object with transformed keys and/or values\n * @example\n * map({ a: 1, b: 2 }, v => v * 10)\n * // => { a: 10, b: 20 }\n *\n * map({ a: 1, b: 2 }, undefined, k => k.toUpperCase())\n * // => { A: 1, B: 2 }\n *\n * map({ a: 1, b: 2 }, v => v * 10, k => k.toUpperCase())\n * // => { A: 10, B: 20 }\n * @since 2.0.0\n */\nexport function map<\n TObj extends Record<string, unknown>,\n TVal = TObj[keyof TObj],\n TKey extends PropertyKey = keyof TObj,\n>(\n obj: TObj | null | undefined,\n mapValue?: (value: TObj[keyof TObj], key: keyof TObj) => TVal,\n mapKey?: (key: keyof TObj, value: TObj[keyof TObj]) => TKey\n): Record<TKey, TVal> {\n const result = {} as Record<TKey, TVal>;\n if (obj == null) return result;\n for (const key of Object.keys(obj) as (keyof TObj)[]) {\n const value = obj[key];\n const newKey = mapKey ? mapKey(key, value) : (key as unknown as TKey);\n if (typeof newKey === 'string' && UNSAFE_KEYS.has(newKey)) continue;\n const newVal = mapValue ? mapValue(value, key) : (value as unknown as TVal);\n result[newKey] = newVal;\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { cloneDeep } from './cloneDeep.js';\nimport { isPlainObject } from '../guard/isPlainObject';\nimport type { MergeResult } from './_types.js';\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\nfunction applyKey(\n result: Record<PropertyKey, unknown>,\n source: Record<PropertyKey, unknown>,\n key: PropertyKey,\n): void {\n const resultValue = result[key];\n const sourceValue = source[key];\n if (isPlainObject(resultValue) && isPlainObject(sourceValue)) {\n result[key] = mergeDeep(\n resultValue as Record<PropertyKey, unknown>,\n sourceValue as Record<PropertyKey, unknown>,\n );\n } else if (sourceValue !== undefined) {\n result[key] = (isPlainObject(sourceValue) || Array.isArray(sourceValue))\n ? cloneDeep(sourceValue)\n : sourceValue;\n }\n}\n\nfunction applySource(\n result: Record<PropertyKey, unknown>,\n source: Record<PropertyKey, unknown>,\n): void {\n for (const key in source) {\n if (!Object.hasOwn(source, key) || UNSAFE_KEYS.has(key)) continue;\n applyKey(result, source, key);\n }\n for (const sym of Object.getOwnPropertySymbols(source)) {\n if (!Object.prototype.propertyIsEnumerable.call(source, sym)) continue;\n applyKey(result, source, sym);\n }\n}\n\n/**\n * Merges two or more objects deeply, returning a **new** object without mutating any input.\n *\n * Sources are applied left to right. For each key:\n * - If both sides are plain objects → merged recursively into a new object.\n * - Otherwise → **later source wins** (the earlier value is overwritten).\n * - `undefined` in a source **never overwrites** an existing value.\n * - `null` in a source **does overwrite** and prevents a later source from\n * deep-merging into that key: `mergeDeep({ a: { x: 1 } }, { a: null }, { a: { y: 2 } })`\n * → `{ a: { y: 2 } }` — `x: 1` is permanently lost.\n * - Arrays, class instances, and all non-plain-object values are **replaced**, not merged.\n *\n * Own enumerable string and symbol keys of each source are processed at the top level;\n * inherited and non-enumerable properties are skipped. Prototype-polluting keys\n * (`__proto__`, `constructor`, `prototype`) are silently ignored.\n * **Note:** symbol keys inside nested plain-object values are not preserved — they are\n * lost when those values are deep-cloned. Only top-level symbol keys survive.\n *\n * **TypeScript return type — intersection semantics**\n *\n * The return type is `A & B & C …` (intersection of all source types). This is accurate\n * when keys are disjoint or share the same type:\n * ```ts\n * mergeDeep({ a: 1 }, { b: 'x' }) // { a: number } & { b: string } ✓\n * mergeDeep({ a: { b: 1 } }, { a: { c: 2 } }) // { a: { b: number } & { c: number } } ✓\n * ```\n * When the same key carries **incompatible types** across sources, the intersection\n * resolves to `never` for that key — TypeScript surfaces the conflict rather than\n * silently picking a type:\n * ```ts\n * mergeDeep({ a: 1 }, { a: 'x' }) // { a: never } ← type conflict detected\n * ```\n * At runtime the later source always wins (`'x'`), but the `never` type signals that\n * the caller should align their source types. If intentional, cast the result.\n *\n * @param sources - Two or more objects to merge (none are mutated)\n * @returns A new object that is the deep merge of all sources\n * @example\n * mergeDeep({ a: 1, b: { c: 2 } }, { b: { d: 3 }, e: 4 })\n * // => { a: 1, b: { c: 2, d: 3 }, e: 4 }\n *\n * // Later source wins for non-object values\n * mergeDeep({ a: 1, arr: [1, 2] }, { a: 2, arr: [3] })\n * // => { a: 2, arr: [3] }\n *\n * // undefined never overwrites\n * mergeDeep({ a: 1 }, { a: undefined })\n * // => { a: 1 }\n *\n * // Three sources, left to right\n * mergeDeep({ x: 1 }, { y: 2 }, { x: 99, z: 3 })\n * // => { x: 99, y: 2, z: 3 }\n * @since 1.9.0\n */\nexport function mergeDeep<T extends [object, ...object[]]>(...sources: [...T]): MergeResult<T>;\nexport function mergeDeep(...sources: object[]): object {\n const result: Record<PropertyKey, unknown> = {};\n for (const source of sources) {\n if (source !== null && source !== undefined) {\n applySource(result, source as Record<PropertyKey, unknown>);\n }\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Creates a new object without the specified keys.\n * @param obj - The source object\n * @param keys - The keys to omit\n * @returns A new object without the omitted keys\n * @example\n * omit({ a: 1, b: 2, c: 3 }, ['b'])\n * // => { a: 1, c: 3 }\n * @since 2.0.0\n */\nexport function omit<T extends object, K extends keyof T>(obj: T, keys: readonly K[]): Omit<T, K>;\nexport function omit(obj: undefined, keys: readonly string[]): undefined;\nexport function omit(obj: null, keys: readonly string[]): null;\nexport function omit<T extends object, K extends keyof T>(\n obj: T | undefined | null,\n keys: readonly K[]\n): Omit<T, K> | undefined | null {\n if (obj === undefined || obj === null) return obj;\n const result = { ...obj };\n for (const key of keys) {\n delete result[key];\n }\n return result as Omit<T, K>;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Creates a new object without the own enumerable entries for which\n * `predicate` returns `true`.\n *\n * Complements {@link omit} for when the keys to remove aren't known ahead of\n * time — `omit` takes an explicit key list, `omitBy` takes a predicate.\n *\n * @param obj - The source object. `null`/`undefined` pass through unchanged.\n * @param predicate - Called with `(value, key)` for each own enumerable entry\n * @returns A new object without the matching entries\n * @example\n * omitBy({ a: 1, b: undefined, c: 2 }, (value) => value === undefined)\n * // => { a: 1, c: 2 }\n * @since 3.0.0\n */\nexport function omitBy<T extends Record<string, unknown>>(\n obj: T | undefined | null,\n predicate: (value: T[keyof T], key: keyof T) => boolean,\n): Partial<T> | undefined | null {\n if (obj == null) return obj;\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n const typedKey = key as keyof T;\n if (!predicate(obj[typedKey], typedKey)) {\n result[key] = obj[typedKey];\n }\n }\n return result as Partial<T>;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Converts a string to PascalCase.\n * Handles camelCase, kebab-case, snake_case, spaces, and mixed formats.\n * @param str - The string to convert\n * @returns String in PascalCase\n * @example\n * pascalCase('hello-world')\n * // => 'HelloWorld'\n * @since 2.0.0\n */\nexport function pascalCase(str: string): string;\nexport function pascalCase(str: undefined): undefined;\nexport function pascalCase(str: null): null;\nexport function pascalCase(str: string | undefined | null): string | undefined | null {\n if (str === undefined || str === null) return str;\n return str\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/([A-Z])([A-Z][a-z])/g, '$1 $2')\n .split(/[\\s_-]+/)\n .filter(Boolean)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('');\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { pascalCase } from '../string/pascalCase.js';\nimport { mapDeep } from './mapDeep.js';\n\n/**\n * Recursively transforms every key of a plain object (including keys nested inside arrays and\n * nested objects) to PascalCase. Handles camelCase, snake_case, kebab-case, and space-separated\n * keys. Non-plain-object values — `Date`, `Map`, `Set`, class instances, primitives — are left\n * untouched, only their position is walked into. An entry whose transformed key is a\n * prototype-polluting string (`__proto__`, `constructor`, `prototype`) is silently skipped,\n * same as the rest of `@helpers4/object`.\n * @param value - The object (or array of objects) to transform\n * @returns A new value with every plain-object key converted to PascalCase\n * @example\n * pascalCaseKeys({ user_name: 'Alice', home_address: { zip_code: '12345' } })\n * // => { UserName: 'Alice', HomeAddress: { ZipCode: '12345' } }\n * @since 3.0.3\n */\nexport function pascalCaseKeys<T>(value: T): T {\n return mapDeep(value, undefined, pascalCase);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Creates a new object with only the specified keys.\n * Keys that are prototype-polluting strings (`__proto__`, `constructor`, `prototype`) are\n * silently skipped.\n * @param obj - The source object\n * @param keys - The keys to pick\n * @returns A new object with only the picked keys\n * @example\n * pick({ a: 1, b: 2, c: 3 }, ['a', 'c'])\n * // => { a: 1, c: 3 }\n * @since 2.0.0\n */\nexport function pick<T extends object, K extends keyof T>(obj: T, keys: readonly K[]): Pick<T, K>;\nexport function pick(obj: undefined, keys: readonly string[]): undefined;\nexport function pick(obj: null, keys: readonly string[]): null;\nexport function pick<T extends object, K extends keyof T>(\n obj: T | undefined | null,\n keys: readonly K[]\n): Pick<T, K> | undefined | null {\n if (obj === undefined || obj === null) return obj;\n const result = {} as Pick<T, K>;\n for (const key of keys) {\n if (typeof key === 'string' && UNSAFE_KEYS.has(key)) continue;\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result[key] = obj[key];\n }\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Creates a new object with only the own enumerable entries for which\n * `predicate` returns `true`.\n *\n * Complements {@link pick} for when the keys to keep aren't known ahead of\n * time — `pick` takes an explicit key list, `pickBy` takes a predicate.\n *\n * @param obj - The source object. `null`/`undefined` pass through unchanged.\n * @param predicate - Called with `(value, key)` for each own enumerable entry\n * @returns A new object with only the matching entries\n * @example\n * pickBy({ a: 1, b: 0, c: 2 }, (value) => value > 0)\n * // => { a: 1, c: 2 }\n * @since 3.0.0\n */\nexport function pickBy<T extends Record<string, unknown>>(\n obj: T | undefined | null,\n predicate: (value: T[keyof T], key: keyof T) => boolean,\n): Partial<T> | undefined | null {\n if (obj == null) return obj;\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n if (UNSAFE_KEYS.has(key)) continue;\n const typedKey = key as keyof T;\n if (predicate(obj[typedKey], typedKey)) {\n result[key] = obj[typedKey];\n }\n }\n return result as Partial<T>;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is null or undefined (nullish).\n * @param value - The value to check\n * @returns True if value is null or undefined\n * @example\n * isNullish(null) // => true\n * isNullish(undefined) // => true\n * isNullish(0) // => false\n * isNullish('') // => false\n *\n * @see {@link isDefined} for the inverse check (`!isNullish`)\n * @see {@link isFalsy} to also catch `0`, `\"\"`, `false`, and `NaN`\n * @since 2.0.0\n */\nexport function isNullish(value: unknown): value is null | undefined {\n return value === null || value === undefined;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { isNullish } from '../guard/isNullish';\n\n/**\n * Remove null and undefined values from an object.\n *\n * @param obj an object\n * @returns A shallow copy of the object without null or undefined values\n * @since 1.0.0\n */\nexport function removeUndefinedNull<T extends Record<string, string | number | boolean | null | undefined>>(obj: T): Partial<T>;\n\n/**\n * Remove null and undefined values from an object.\n *\n * @param obj a null object\n * @returns null\n * @since 1.0.0\n */\nexport function removeUndefinedNull(obj: null): null;\n\n/**\n * Remove null and undefined values from an object.\n *\n * @param obj an undefined object\n * @returns undefined\n * @since 1.0.0\n */\nexport function removeUndefinedNull(obj: undefined): undefined;\n\n/**\n * Remove null and undefined values from an object.\n *\n * @param obj an object\n * @returns A shallow copy of the object without null or undefined values\n * @since 1.0.0\n */\nexport function removeUndefinedNull<T extends Record<string, string | number | boolean | null | undefined>>(obj: T | null | undefined): Partial<T> | null | undefined {\n if (!obj) return obj;\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) {\n if (!isNullish(v)) { result[k] = v; }\n }\n return result as Partial<T>;\n}\n\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Parses strict JSON (RFC 8259) — exactly what `JSON.parse` accepts, nothing more.\n *\n * **Accepts:** standard JSON only — double-quoted strings and keys, finite decimal numbers,\n * `true`/`false`/`null`, objects and arrays, surrounding whitespace.\n *\n * **Rejects:** comments, trailing commas, single quotes, unquoted keys, hexadecimal numbers,\n * `NaN`/`Infinity`, a leading byte order mark (U+FEFF), and anything else that isn't strict JSON.\n *\n * **On invalid input:** throws the native `SyntaxError` from `JSON.parse`.\n *\n * Use it to validate input that must be strict JSON, e.g. an API payload. To also read config\n * files with comments or JSON5, use {@link parse}. To never throw, use {@link safeParseStrict}.\n *\n * @param text - The JSON text to parse\n * @returns The parsed value, typed as `T`\n * @throws {SyntaxError} When `text` isn't strict JSON\n * @see {@link safeParseStrict} — same parsing, returns `null` or a fallback instead of throwing\n * @see {@link parse} — also accepts JSONC and JSON5\n * @see {@link parseLines} — one value per line (NDJSON, JSON Lines)\n * @see {@link parseSequence} — JSON text sequences (RFC 7464)\n * @example\n * parseStrict<{ a: number }>('{\"a\":1}') // => { a: 1 }\n * parseStrict('{\"a\":1,}') // throws SyntaxError (trailing comma)\n * @since 3.1.3\n */\nexport function parseStrict<T = unknown>(text: string): T {\n return JSON.parse(text) as T;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { parseStrict } from './parseStrict';\n\n/**\n * Parses strict JSON like {@link parseStrict}, but returns `null` (or `fallback`) instead of\n * throwing on invalid input.\n *\n * **Accepts / rejects:** exactly what {@link parseStrict} does — standard JSON only, no comments,\n * no trailing commas, no JSON5 syntax, no leading byte order mark.\n *\n * **On invalid input:** returns `fallback` when one is given — even `undefined`, which is told\n * apart from an omitted argument — and `null` otherwise. Never throws.\n *\n * @param text - The JSON text to parse\n * @param fallback - Value returned on invalid input. Defaults to `null` when omitted.\n * @returns The parsed value typed as `T`, or `fallback` on invalid input\n * @see {@link parseStrict} — same parsing, throws a `SyntaxError` instead\n * @see {@link safeParse} — also accepts JSONC and JSON5\n * @example\n * safeParseStrict<{ a: number }>('{\"a\":1}') // => { a: 1 }\n * safeParseStrict('{\"a\":1,}') // => null\n * safeParseStrict('oops', {}) // => {}\n * @since 3.1.3\n */\nexport function safeParseStrict<T = unknown>(text: string): T | null;\nexport function safeParseStrict<T = unknown, F = T>(text: string, fallback: F): T | F;\nexport function safeParseStrict<T, F>(text: string, fallback?: F): T | F | null {\n try {\n return parseStrict<T>(text);\n } catch {\n return arguments.length < 2 ? null : (fallback as F);\n }\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { safeParseStrict } from '../json/safeParseStrict';\n\n/**\n * Parses a JSON string, returning `null` (or a fallback) on any parse failure.\n *\n * Unlike `JSON.parse`, this never throws. Invalid JSON strings and other\n * parsing edge-cases resolve to `null` or the provided `fallback`.\n *\n * @param input - The JSON string to parse.\n * @param fallback - Value returned on failure. Defaults to `null` when omitted.\n * @returns The parsed value typed as `T`, or `fallback` on failure.\n * @example\n * safeJsonParse<{ a: number }>('{\"a\":1}') // => { a: 1 }\n * safeJsonParse('invalid') // => null\n * safeJsonParse('invalid', []) // => []\n * @deprecated Use `safeParseStrict` from `@helpers4/json` instead — same parsing, same\n * `fallback` behavior. `safeJsonParse` will be removed in v4.\n * @since 2.0.0\n */\nexport function safeJsonParse<T>(input: string): T | null;\nexport function safeJsonParse<T>(input: string, fallback: T): T;\nexport function safeJsonParse<T>(input: string, fallback?: T): T | null {\n // Forward the fallback only when one was passed, so \"no fallback\" (→ null) stays distinct from\n // an explicit `undefined` fallback (→ undefined).\n return arguments.length < 2 ? safeParseStrict<T>(input) : safeParseStrict<T>(input, fallback as T);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { parsePropertyPath } from './parsePropertyPath.js';\nimport type { ContainsUnsafeStringKey, DeepGet, DeepSet, ParsePath } from './_types.js';\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Sets a value in an object at the given path, creating intermediate objects as needed.\n *\n * **Two path forms are supported:**\n *\n * 1. **String path** — dot notation and bracket notation, mixed freely.\n * - Dot segments are always string keys: `'layers.1.name'` → keys `['layers', '1', 'name']`.\n * - Bracket segments are always number keys: `'layers[1].name'` → keys `['layers', 1, 'name']`.\n * - String literal paths give **full compile-time type inference** on the return type.\n * - Dynamic (non-literal) strings return `T` (same object type).\n *\n * 2. **Key array** (`PropertyKey[]`) — explicit array of `string | number | symbol` keys,\n * no parsing performed. Enables symbol-keyed access and precise return-type inference.\n *\n * Both forms support **all objects** (plain objects, arrays, class instances).\n * Symbol keys are only reachable via the key-array form.\n *\n * Intermediate nodes that are absent, `null`, or not an object are replaced with `{}`.\n * Any path containing a string segment equal to `__proto__`, `constructor`, or `prototype`\n * is rejected and the original object is returned unchanged (prototype-pollution guard).\n *\n * @param obj - The object to mutate\n * @param path - Dot/bracket-notation string literal or explicit `PropertyKey[]`\n * @param value - Value to assign at the path\n * @returns The mutated object (same reference, narrowed type)\n * @example\n * // Dot notation — \"1\" stays a string key\n * set({}, 'a.b.c', 42)\n * // => { a: { b: { c: 42 } } }\n *\n * // Bracket notation — [1] becomes a number key\n * set({ layers: [{}, { name: 'old' }] }, 'layers[1].name', 'bg')\n * // => { layers: [{}, { name: 'bg' }] }\n *\n * // Key array — supports symbols\n * const id = Symbol('id')\n * set({}, ['user', id], 'alice')\n * // => { user: { [id]: 'alice' } }\n * @since 1.9.0\n */\nexport function set<\n T extends object,\n const P extends string | readonly PropertyKey[],\n V extends DeepGet<T, ParsePath<P>>,\n>(\n obj: T,\n path: P,\n value: V,\n): string extends P ? T : readonly PropertyKey[] extends P ? T : ContainsUnsafeStringKey<ParsePath<P>> extends true ? T : DeepSet<T, ParsePath<P>, V>;\nexport function set(obj: object, path: string | PropertyKey[], value: unknown): object {\n const keys: readonly PropertyKey[] = typeof path === 'string' ? parsePropertyPath(path) : path;\n\n if (keys.length === 0) return obj;\n if (keys.some((k) => typeof k === 'string' && UNSAFE_KEYS.has(k))) return obj;\n\n let current = obj as Record<PropertyKey, unknown>;\n\n for (let i = 0; i < keys.length - 1; i++) {\n const key = keys[i];\n\n // Object.hasOwn (not `key in current`) is intentional: `in` checks the prototype chain,\n // which would silently traverse into — and potentially mutate — an inherited object.\n // Using hasOwn ensures we only follow own properties; inherited intermediate nodes are\n // shadowed with a fresh own `{}` instead of being followed into the prototype.\n if (!Object.hasOwn(current, key) || typeof current[key] !== 'object' || current[key] === null) {\n current[key] = {};\n }\n\n current = current[key] as Record<PropertyKey, unknown>;\n }\n\n current[keys[keys.length - 1]] = value;\n return obj;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Converts a string to snake_case.\n * Handles camelCase, PascalCase, kebab-case, spaces, and mixed formats.\n * @param str - The string to convert\n * @returns String in snake_case\n * @example\n * snakeCase('camelCase')\n * // => 'camel_case'\n * @since 2.0.0\n */\nexport function snakeCase(str: string): string;\nexport function snakeCase(str: undefined): undefined;\nexport function snakeCase(str: null): null;\nexport function snakeCase(str: string | undefined | null): string | undefined | null {\n if (str === undefined || str === null) return str;\n return str\n .replace(/([a-z0-9])([A-Z])/g, '$1_$2')\n .replace(/([A-Z])([A-Z][a-z])/g, '$1_$2')\n .replace(/[\\s-]+/g, '_')\n .toLowerCase();\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { snakeCase } from '../string/snakeCase.js';\nimport { mapDeep } from './mapDeep.js';\n\n/**\n * Recursively transforms every key of a plain object (including keys nested inside arrays and\n * nested objects) to snake_case. Handles camelCase, PascalCase, kebab-case, and space-separated\n * keys. Non-plain-object values — `Date`, `Map`, `Set`, class instances, primitives — are left\n * untouched, only their position is walked into. An entry whose transformed key is a\n * prototype-polluting string (`__proto__`, `constructor`, `prototype`) is silently skipped,\n * same as the rest of `@helpers4/object`.\n * @param value - The object (or array of objects) to transform\n * @returns A new value with every plain-object key converted to snake_case\n * @example\n * snakeCaseKeys({ userName: 'Alice', homeAddress: { zipCode: '12345' } })\n * // => { user_name: 'Alice', home_address: { zip_code: '12345' } }\n * @since 3.0.3\n */\nexport function snakeCaseKeys<T>(value: T): T {\n return mapDeep(value, undefined, snakeCase);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Creates a new object with the same entries as the input, but with its own keys sorted.\n * Shallow only — nested objects are copied as-is, their keys are not re-sorted.\n * Key order matters for things like `JSON.stringify` diffs and snapshot stability; this does\n * not change equality (`{a:1,b:2}` and `{b:2,a:1}` are already equal), just iteration/serialization order.\n * Note: integer-index-like keys (`\"0\"`, `\"1\"`, `\"42\"`...) are always iterated first, in numeric\n * order, by the JS engine itself — no object key ordering can override that language behavior.\n * A prototype-polluting key (`__proto__`, `constructor`, `prototype`) is silently skipped,\n * same as the rest of `@helpers4/object`.\n * @param obj - The object whose keys to sort\n * @param compareFn - Optional custom comparator, passed directly to `Array.prototype.sort`\n * @returns A new object with the same entries, own keys in sorted order\n * @example\n * sortKeys({ b: 2, a: 1, c: 3 })\n * // => { a: 1, b: 2, c: 3 }\n * @since 3.0.3\n */\nexport function sortKeys<T extends Record<string, unknown>>(\n obj: T,\n compareFn?: (a: string, b: string) => number,\n): T {\n const sortedKeys = Object.keys(obj).toSorted(compareFn);\n const result = {} as T;\n for (const key of sortedKeys) {\n if (UNSAFE_KEYS.has(key)) continue;\n result[key as keyof T] = obj[key as keyof T];\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Converts a string to Title Case.\n * Handles camelCase, PascalCase, kebab-case, snake_case, spaces, and mixed formats.\n * @param str - The string to convert\n * @returns String in Title Case\n * @example\n * titleCase('hello-world')\n * // => 'Hello World'\n * @example\n * titleCase('queryItems')\n * // => 'Query Items'\n * @since 2.0.0\n */\nexport function titleCase(str: string): string;\nexport function titleCase(str: undefined): undefined;\nexport function titleCase(str: null): null;\nexport function titleCase(str: string | undefined | null): string | undefined | null {\n if (str === undefined || str === null) return str;\n return str\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/([A-Z])([A-Z][a-z])/g, '$1 $2')\n .split(/[\\s_-]+/)\n .filter(Boolean)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ');\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { titleCase } from '../string/titleCase.js';\nimport { mapDeep } from './mapDeep.js';\n\n/**\n * Recursively transforms every key of a plain object (including keys nested inside arrays and\n * nested objects) to Title Case. Handles camelCase, snake_case, kebab-case, and space-separated\n * keys. Non-plain-object values — `Date`, `Map`, `Set`, class instances, primitives — are left\n * untouched, only their position is walked into. An entry whose transformed key is a\n * prototype-polluting string (`__proto__`, `constructor`, `prototype`) is silently skipped,\n * same as the rest of `@helpers4/object`.\n *\n * Note: unlike the other `*CaseKeys` variants, `titleCase` joins words with spaces (e.g.\n * `'User Name'`) — those keys are only usable via bracket access (`obj['User Name']`), not dot\n * notation. Useful for display-facing structures (form labels, table headers), not wire formats.\n * @param value - The object (or array of objects) to transform\n * @returns A new value with every plain-object key converted to Title Case\n * @example\n * titleCaseKeys({ user_name: 'Alice', home_address: { zip_code: '12345' } })\n * // => { 'User Name': 'Alice', 'Home Address': { 'Zip Code': '12345' } }\n * @since 3.0.3\n */\nexport function titleCaseKeys<T>(value: T): T {\n return mapDeep(value, undefined, titleCase);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { set } from './set.js';\n\n/**\n * Rebuilds a nested object from a single-level object whose keys are\n * dot-notation paths. The inverse of {@link flatten}.\n *\n * Uses {@link set} internally, so intermediate nodes are always created as\n * plain objects (never arrays — see {@link flatten}'s doc for why), and any\n * key segment equal to `__proto__`, `constructor`, or `prototype` is silently\n * rejected (same prototype-pollution guard as `set`).\n *\n * @param obj - A single-level object with dot-notation keys\n * @returns The rebuilt nested object\n * @example\n * unflatten({ 'a.b.c': 1, 'a.d': 2 })\n * // => { a: { b: { c: 1 }, d: 2 } }\n * @since 3.0.0\n */\nexport function unflatten(obj: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n set(result, key, value);\n }\n return result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { parsePropertyPath } from './parsePropertyPath.js';\nimport { UNSAFE_KEYS } from '../_shared/_unsafeKeys.js';\n\n/**\n * Removes the value at a dot/bracket-notation path or explicit key array,\n * mutating the object in place. Uses the same path syntax as {@link get}/{@link set}.\n *\n * A missing intermediate segment is a no-op (nothing to remove), not an error.\n * As with `set`, any path containing a string segment equal to `__proto__`,\n * `constructor`, or `prototype` is rejected and the object is returned unchanged.\n *\n * The removed key stops appearing in `Object.keys`/`for...in` — unlike setting\n * it to `undefined`, which would keep the key present.\n *\n * @param obj - The object to mutate\n * @param path - Dot/bracket-notation string, or explicit `PropertyKey[]`\n * @returns The same object reference, with the key removed if it existed\n * @example\n * unset({ a: { b: 1, c: 2 } }, 'a.b')\n * // => { a: { c: 2 } }\n * @example\n * unset({ a: 1 }, 'x.y') // path doesn't exist — no-op\n * // => { a: 1 }\n * @since 3.0.0\n */\nexport function unset<T extends object>(obj: T, path: string | readonly PropertyKey[]): T {\n const keys: readonly PropertyKey[] = typeof path === 'string' ? parsePropertyPath(path) : path;\n\n if (keys.length === 0) return obj;\n if (keys.some((key) => typeof key === 'string' && UNSAFE_KEYS.has(key))) return obj;\n\n let current: unknown = obj;\n for (let i = 0; i < keys.length - 1; i++) {\n if (current == null || typeof current !== 'object') return obj;\n current = (current as Record<PropertyKey, unknown>)[keys[i]];\n }\n\n if (current != null && typeof current === 'object') {\n delete (current as Record<PropertyKey, unknown>)[keys[keys.length - 1]];\n }\n\n return obj;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { get } from './get.js';\nimport { set } from './set.js';\nimport type { ContainsUnsafeStringKey, DeepGet, DeepSet, ParsePath } from './_types.js';\n\n/**\n * Updates the value at a path by applying a function to its current value,\n * creating intermediate objects as needed. Equivalent to\n * `set(obj, path, updater(get(obj, path)))` in a single call.\n *\n * Uses the same path syntax and type-inference rules as {@link get} and\n * {@link set} — see those for the full behavior (string vs. `PropertyKey[]`\n * paths, prototype-pollution guarding, etc.).\n *\n * @param obj - The object to mutate\n * @param path - Dot/bracket-notation string literal or explicit `PropertyKey[]`\n * @param updater - Called with the current value (`undefined` if the path is\n * absent); its return value is written back at the path\n * @returns The mutated object (same reference, narrowed type)\n * @example\n * update({ count: 1 }, 'count', (n) => (n ?? 0) + 1)\n * // => { count: 2 }\n * @example\n * // Missing intermediate objects are created, just like set()\n * update({}, 'stats.hits', (n: number | undefined) => (n ?? 0) + 1)\n * // => { stats: { hits: 1 } }\n * @since 3.0.0\n */\nexport function update<\n T extends object,\n const P extends string | readonly PropertyKey[],\n V extends DeepGet<T, ParsePath<P>>,\n>(\n obj: T,\n path: P,\n updater: (current: DeepGet<T, ParsePath<P>> | undefined) => V,\n): string extends P ? T : readonly PropertyKey[] extends P ? T : ContainsUnsafeStringKey<ParsePath<P>> extends true ? T : DeepSet<T, ParsePath<P>, V>;\nexport function update(\n obj: object,\n path: string | PropertyKey[],\n updater: (current: unknown) => unknown,\n): object {\n const current = get(obj, path);\n return set(obj, path, updater(current));\n}\n"],"mappings":"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"}
|
package/llms.txt
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @helpers4/object
|
|
2
2
|
|
|
3
3
|
> Tree-shakable TypeScript utility functions for the `object` domain.
|
|
4
|
-
> Package: `@helpers4/object` — Version: 3.1.
|
|
4
|
+
> Package: `@helpers4/object` — Version: 3.1.4
|
|
5
5
|
> License: LGPL-3.0-or-later
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
@@ -954,7 +954,7 @@ Creates a new object without the specified keys.
|
|
|
954
954
|
```typescript
|
|
955
955
|
import { omit } from '@helpers4/object';
|
|
956
956
|
|
|
957
|
-
omit<T extends
|
|
957
|
+
omit<T extends object, K extends string | number | symbol>(obj: T, keys: readonly K[]): Omit<T, K>
|
|
958
958
|
```
|
|
959
959
|
|
|
960
960
|
**Parameters:**
|
|
@@ -1148,7 +1148,7 @@ silently skipped.
|
|
|
1148
1148
|
```typescript
|
|
1149
1149
|
import { pick } from '@helpers4/object';
|
|
1150
1150
|
|
|
1151
|
-
pick<T extends
|
|
1151
|
+
pick<T extends object, K extends string | number | symbol>(obj: T, keys: readonly K[]): Pick<T, K>
|
|
1152
1152
|
```
|
|
1153
1153
|
|
|
1154
1154
|
**Parameters:**
|
package/meta/api.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"category": "object",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.4",
|
|
4
4
|
"functions": [
|
|
5
5
|
{
|
|
6
6
|
"name": "camelCaseKeys",
|
|
@@ -850,7 +850,7 @@
|
|
|
850
850
|
"since": "2.0.0",
|
|
851
851
|
"signatures": [
|
|
852
852
|
{
|
|
853
|
-
"signature": "omit<T extends
|
|
853
|
+
"signature": "omit<T extends object, K extends string | number | symbol>(obj: T, keys: readonly K[]): Omit<T, K>",
|
|
854
854
|
"description": "Creates a new object without the specified keys.",
|
|
855
855
|
"params": [
|
|
856
856
|
{
|
|
@@ -871,7 +871,7 @@
|
|
|
871
871
|
"typeParameters": [
|
|
872
872
|
{
|
|
873
873
|
"name": "T",
|
|
874
|
-
"constraint": "
|
|
874
|
+
"constraint": "object"
|
|
875
875
|
},
|
|
876
876
|
{
|
|
877
877
|
"name": "K",
|
|
@@ -1060,7 +1060,7 @@
|
|
|
1060
1060
|
"since": "2.0.0",
|
|
1061
1061
|
"signatures": [
|
|
1062
1062
|
{
|
|
1063
|
-
"signature": "pick<T extends
|
|
1063
|
+
"signature": "pick<T extends object, K extends string | number | symbol>(obj: T, keys: readonly K[]): Pick<T, K>",
|
|
1064
1064
|
"description": "Creates a new object with only the specified keys.\nKeys that are prototype-polluting strings (`__proto__`, `constructor`, `prototype`) are\nsilently skipped.",
|
|
1065
1065
|
"params": [
|
|
1066
1066
|
{
|
|
@@ -1081,7 +1081,7 @@
|
|
|
1081
1081
|
"typeParameters": [
|
|
1082
1082
|
{
|
|
1083
1083
|
"name": "T",
|
|
1084
|
-
"constraint": "
|
|
1084
|
+
"constraint": "object"
|
|
1085
1085
|
},
|
|
1086
1086
|
{
|
|
1087
1087
|
"name": "K",
|