diff static method

Map<String, Object?> diff({
  1. required Map<String, dynamic>? before,
  2. required Map<String, dynamic> after,
  3. bool includeDeletes = false,
})

Returns a Firestore update()-ready map of dot-notation field paths representing the difference between before and after.

Behavior:

  • When before is null, returns a shallow copy of after (top-level keys emitted as-is, no flattening).
  • When before is deeply equal to after, returns an empty map so callers can skip the write entirely.
  • For each key in after:
    • If before does not contain the key, emits {key: afterValue} at the current dot-notation path (no recursion when one side is absent).
    • If both beforeValue and afterValue are Map<String, dynamic>, recurses with prefix ${currentPath}.${key}.
    • Else if DeepCollectionEquality().equals(beforeValue, afterValue), skips the entry.
    • Else emits {path: afterValue}.
  • When includeDeletes is true, also walks keys present in before but missing from after and emits {path: FieldValue.delete()}.
  • Lists are not recursed into; they are compared atomically by DeepCollectionEquality and replaced wholesale if not equal.

Implementation

static Map<String, Object?> diff({
  required Map<String, dynamic>? before,
  required Map<String, dynamic> after,
  bool includeDeletes = false,
}) {
  if (before == null) {
    return Map<String, Object?>.from(after);
  }
  const equality = DeepCollectionEquality();
  if (equality.equals(before, after)) {
    return <String, Object?>{};
  }
  final result = <String, Object?>{};
  _collect(
    before: before,
    after: after,
    prefix: '',
    includeDeletes: includeDeletes,
    result: result,
    equality: equality,
  );
  return result;
}