delete method

Future<bool> delete({
  1. required String id,
  2. required String userId,
  3. DataSource source = DataSource.local,
  4. bool forceRemoteSync = false,
  5. DeleteBehavior? behavior,
})

Deletes an entity by its ID from all local and remote adapters.

The behavior parameter allows overriding the global DatumConfig.deleteBehavior for this specific delete operation. If null, the global config value is used.

Implementation

Future<bool> delete({
  required String id,
  required String userId,
  DataSource source = DataSource.local,
  bool forceRemoteSync = false,
  DeleteBehavior? behavior,
}) async {
  _ensureInitialized();
  // Check for user switch before proceeding.
  await _syncEngineInstance.checkForUserSwitch(userId);

  final existing = await localAdapter.read(id, userId: userId);
  if (existing == null) {
    _logger.debug(
      'Entity $id does not exist for user $userId, skipping delete',
    );
    return false;
  }

  _logger.debug('Notifying observers of onDeleteStart for $id');
  for (final weakObserver in _localObservers) {
    weakObserver.target?.onDeleteStart(id);
  }
  for (final weakObserver in _globalObservers) {
    weakObserver.target?.onDeleteStart(id);
  }
  // Use the provided behavior or fall back to the configured delete behavior
  final effectiveBehavior = behavior ?? config.deleteBehavior;
  T entityForEvent = existing;
  if (effectiveBehavior == DeleteBehavior.softDelete) {
    // Soft delete: mark the entity as deleted
    entityForEvent = await localAdapter.patch(
      id: id,
      delta: {'isDeleted': true, 'modifiedAt': DateTime.now().toIso8601String()},
      userId: userId,
    );
  } else {
    // Hard delete: physically remove the entity
    final deleted = await localAdapter.delete(id, userId: userId);
    if (!deleted) {
      _logger.warn('Local adapter failed to delete entity $id');
      // Notify observers of the failure before returning.
      for (final weakObserver in _localObservers) {
        weakObserver.target?.onDeleteEnd(id, success: false);
      }
      for (final weakObserver in _globalObservers) {
        weakObserver.target?.onDeleteEnd(id, success: false);
      }
      return false;
    }
  }

  _logger.debug('Notifying observers of onDeleteEnd for $id');
  for (final weakObserver in _localObservers) {
    weakObserver.target?.onDeleteEnd(id, success: true);
  }
  for (final weakObserver in _globalObservers) {
    weakObserver.target?.onDeleteEnd(id, success: true);
  }
  if (source == DataSource.local || forceRemoteSync) {
    final operation = _createOperation(
      userId: userId,
      type: DatumOperationType.delete,
      entityId: id,
    );
    // Calculate size for delete operation (it's small, just the ID)
    final payload = {'id': id};
    final size = (await _isolateHelper.computeJsonEncode(payload)).length;

    await _queueManager.enqueue(operation.copyWith(sizeInBytes: size));
  }

  _eventController.add(
    DataChangeEvent<T>(
      userId: userId,
      data: entityForEvent,
      changeType: ChangeType.deleted,
      source: source,
    ),
  );

  // Invalidate caches for the deleted entity
  _invalidateCachesForEntity(entityForEvent);

  return true;
}