call method
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,
);
}
}