import { isEqual } from 'lodash' import { WatchEffect, WatchSource, isReactive, isRef, unref, watch } from 'vue' import { isArray, isFunction, isRecord, mapValues } from '@/utilities' export function getRawValue(value: unknown): unknown { if (typeof value === 'object') { if (isRef(value)) { return unref(value) } if (isArray(value)) { return getRawArrayValue(value) } if (isRecord(value)) { return getRawRecordValue(value) } } return value } function getRawArrayValue(values: unknown[]): unknown[] { return values.map(value => getRawValue(value)) } function getRawRecordValue(value: Record): Record { return mapValues(value, (key, value) => getRawValue(value)) } export function uniqueValueWatcher(...[source, callback, options]: Parameters): ReturnType { let previous = getRawValue(source) return watch(source, (...args) => { const current = getRawValue(source) if (isEqual(previous, current)) { return } previous = current callback(...args) }, options) } export function getValidWatchSource(source: unknown): WatchSource | WatchSource[] | WatchEffect | object { if (isValidWatchValue(source)) { return source } if (isArray(source)) { return source.filter(value => isValidWatchValue(value)) } return [] } function isValidWatchValue(value: unknown): value is WatchSource | WatchEffect { return isRef(value) || isReactive(value) || isFunction(value) }