| | |
| | | |
| | | /** @type {WeakMap<EXPECTED_OBJECT, WeakMap<EXPECTED_OBJECT, EXPECTED_OBJECT>>} */ |
| | | const mergeCache = new WeakMap(); |
| | | /** @type {WeakMap<EXPECTED_OBJECT, Map<string, Map<string | number | boolean, EXPECTED_OBJECT>>>} */ |
| | | /** @typedef {Map<string, Map<string | number | boolean, EXPECTED_OBJECT>>} InnerPropertyCache */ |
| | | /** @type {WeakMap<EXPECTED_OBJECT, InnerPropertyCache>} */ |
| | | const setPropertyCache = new WeakMap(); |
| | | const DELETE = Symbol("DELETE"); |
| | | const DYNAMIC_INFO = Symbol("cleverMerge dynamic info"); |
| | |
| | | }; |
| | | |
| | | /** |
| | | * Caches d set property. |
| | | * @template T |
| | | * @param {Partial<T>} obj object |
| | | * @param {string} property property |
| | |
| | | }; |
| | | |
| | | /** |
| | | * Defines the by values type used by this module. |
| | | * @typedef {Map<string, EXPECTED_ANY>} ByValues |
| | | */ |
| | | |
| | | /** |
| | | * Defines the object parsed property entry type used by this module. |
| | | * @template T |
| | | * @typedef {object} ObjectParsedPropertyEntry |
| | | * @property {T[keyof T] | undefined} base base value |
| | |
| | | /** @typedef {(function(...EXPECTED_ANY): object) & { [DYNAMIC_INFO]: [DynamicFunction, object] }} DynamicFunction */ |
| | | |
| | | /** |
| | | * Defines the parsed object static type used by this module. |
| | | * @template {object} T |
| | | * @typedef {Map<keyof T, ObjectParsedPropertyEntry<T>>} ParsedObjectStatic |
| | | */ |
| | | |
| | | /** |
| | | * Defines the parsed object dynamic type used by this module. |
| | | * @template {object} T |
| | | * @typedef {{ byProperty: `by${string}`, fn: DynamicFunction }} ParsedObjectDynamic |
| | | */ |
| | | |
| | | /** |
| | | * Defines the parsed object type used by this module. |
| | | * @template {object} T |
| | | * @typedef {object} ParsedObject |
| | | * @property {ParsedObjectStatic<T>} static static properties (key is property name) |
| | |
| | | const parseCache = new WeakMap(); |
| | | |
| | | /** |
| | | * Caches d parse object. |
| | | * @template {object} T |
| | | * @param {T} obj the object |
| | | * @returns {ParsedObject<T>} parsed object |
| | |
| | | /** @typedef {{ [p: string]: { [p: string]: EXPECTED_ANY } } | DynamicFunction} ByObject */ |
| | | |
| | | /** |
| | | * Returns parsed object. |
| | | * @template {object} T |
| | | * @param {T} obj the object |
| | | * @returns {ParsedObject<T>} parsed object |
| | |
| | | /** @type {ParsedObjectDynamic<T> | undefined} */ |
| | | let dynamicInfo; |
| | | /** |
| | | * Returns object parsed property entry. |
| | | * @param {keyof T} p path |
| | | * @returns {Partial<ObjectParsedPropertyEntry<T>>} object parsed property entry |
| | | */ |
| | |
| | | }; |
| | | |
| | | /** |
| | | * Returns the object. |
| | | * @template {object} T |
| | | * @param {ParsedObjectStatic<T>} info static properties (key is property name) |
| | | * @param {{ byProperty: `by${string}`, fn: DynamicFunction } | undefined} dynamicInfo dynamic part |
| | |
| | | const VALUE_TYPE_DELETE = 4; |
| | | |
| | | /** |
| | | * Returns value type. |
| | | * @template T |
| | | * @param {T} value a single value |
| | | * @returns {VALUE_TYPE_UNDEFINED | VALUE_TYPE_ATOM | VALUE_TYPE_ARRAY_EXTEND | VALUE_TYPE_OBJECT | VALUE_TYPE_DELETE} value type |
| | |
| | | }; |
| | | |
| | | /** |
| | | * Returns merged object of first and second object. |
| | | * @template {object} T |
| | | * @template {object} O |
| | | * Merges two objects. Objects are deeply clever merged. |
| | |
| | | }; |
| | | |
| | | /** |
| | | * Merges the provided values into a single result. |
| | | * @template T, O |
| | | * @param {ObjectParsedPropertyEntry<T>} firstEntry a |
| | | * @param {ObjectParsedPropertyEntry<O>} secondEntry b |
| | |
| | | } else { |
| | | // = first.base + (first.byProperty + second.byProperty) |
| | | // need to merge first and second byValues |
| | | /** @type {Map<string, T & O>} */ |
| | | const newByValues = new Map(firstEntry.byValues); |
| | | for (const [key, value] of /** @type {ByValues} */ ( |
| | | secondEntry.byValues |
| | |
| | | byValues: secondEntry.byValues |
| | | }; |
| | | } |
| | | /** @type {O[keyof O] | T[keyof T] | (T[keyof T] & O[keyof O]) | (T[keyof T] | undefined)[] | (O[keyof O] | undefined)[] | (O[keyof O] | T[keyof T] | undefined)[] | undefined} */ |
| | | let newBase; |
| | | /** @type {Map<string, (T & O) | O[keyof O] | (O[keyof O] | undefined)[] | ((T & O) | undefined)[] | (T & O & O[keyof O]) | ((T & O) | O[keyof O] | undefined)[] | undefined>} */ |
| | | const intermediateByValues = new Map(firstEntry.byValues); |
| | | for (const [key, value] of intermediateByValues) { |
| | | intermediateByValues.set( |
| | |
| | | `${firstEntry.byProperty} and ${secondEntry.byProperty} for a single property is not supported` |
| | | ); |
| | | } |
| | | /** @type {Map<string, (T & O) | O[keyof O] | (O[keyof O] | undefined)[] | (T & O & O[keyof O]) | ((T & O) | undefined)[] | ((T & O) | O[keyof O] | undefined)[] | undefined>} */ |
| | | const newByValues = new Map(intermediateByValues); |
| | | for (const [key, value] of /** @type {ByValues} */ ( |
| | | secondEntry.byValues |
| | |
| | | }; |
| | | |
| | | /** |
| | | * Gets from by values. |
| | | * @template V |
| | | * @param {ByValues} byValues all values |
| | | * @param {string} key value of the selector |
| | |
| | | }; |
| | | |
| | | /** |
| | | * Merges single value. |
| | | * @template A |
| | | * @template B |
| | | * @param {A | A[]} a value |
| | |
| | | }; |
| | | |
| | | /** |
| | | * Removes operations. |
| | | * @template {object} T |
| | | * @param {T} obj the object |
| | | * @param {(keyof T)[]=} keysToKeepOriginalValue keys to keep original value |
| | |
| | | }; |
| | | |
| | | /** |
| | | * Resolves by property. |
| | | * @template T |
| | | * @template {keyof T} P |
| | | * @template V |