call method

Future call(
  1. String rpcName, {
  2. Map<String, dynamic>? params,
  3. bool storeResult = true,
  4. bool maybeSingle = false,
})

Call an RPC function. rpcName: the PostgREST function name to invoke. params: function params. storeResult: when true, deserializes and upserts into _targetLocalTableName. maybeSingle: when true, expects a single JSON object instead of a list.

Implementation

Future<dynamic> call(
  String rpcName, {
  Map<String, dynamic>? params,
  bool storeResult = true,
  bool maybeSingle = false,
}) async {
  _logger.info('Calling RPC: $rpcName with params: $params');
  try {
    final dynamic rpcResponse = await _supabaseClient.rpc(
      rpcName,
      params: params,
    );

    if (!storeResult) {
      _logger.info('RPC "$rpcName" call successful. Result not stored locally.');
      return rpcResponse;
    }

    if (rpcResponse == null) {
      _logger.warning('RPC "$rpcName" returned null. No data to store.');
      return <TModel>[];
    }

    List<Map<String, dynamic>> responseDataList;

    if (maybeSingle) {
      if (rpcResponse is Map<String, dynamic>) {
        responseDataList = [rpcResponse];
      } else {
        _logger.severe(
          'RPC "$rpcName" expected a single object, got: ${rpcResponse.runtimeType}',
        );
        throw RpcResponseFormatException(
          rpcName,
          'Expected a single JSON object (Map).',
          rpcResponse,
        );
      }
    } else {
      if (rpcResponse is List) {
        if (rpcResponse.every((item) => item is Map<String, dynamic>)) {
          responseDataList = rpcResponse.cast<Map<String, dynamic>>();
        } else {
          _logger.severe(
            'RPC "$rpcName" returned a list, but items are not Map<String, dynamic>.',
          );
          throw RpcResponseFormatException(
            rpcName,
            'Expected a List of JSON objects (Map).',
            rpcResponse,
          );
        }
      } else {
        _logger.severe(
          'RPC "$rpcName" did not return a List as expected. Got: ${rpcResponse.runtimeType}',
        );
        throw RpcResponseFormatException(
          rpcName,
          'Expected a List of JSON objects (Map).',
          rpcResponse,
        );
      }
    }

    if (responseDataList.isEmpty) {
      _logger.info('RPC "$rpcName" returned empty list. Nothing to store.');
      return <TModel>[];
    }

    final List<TModel> models =
        responseDataList.map((data) => _fromJsonFactory(data)).toList();

    await _upsertDataToLocalDb(rpcName, models);

    _logger.info(
      'RPC "$rpcName" stored ${models.length} rows into "$_targetLocalTableName".',
    );
    return models;
  } catch (e, s) {
    _logger.severe('Error in RPC "$rpcName": $e\n$s');
    if (e is PostgrestException || e is RpcResponseFormatException) {
      rethrow;
    }
    throw RpcCallException(
      rpcName,
      e.toString(),
      originalException: e,
      stackTrace: s,
    );
  }
}