Nothing
#' Null-coalescing Operator
#'
#' Returns the left-hand side if it's not NULL, otherwise returns the right-hand side.
#'
#' @param x First value to check.
#' @param y Default value if x is NULL.
#'
#' @return x if not NULL, otherwise y.
#' @name null-coalesce
#' @keywords internal
`%||%` <- function(x, y) {
if (is.null(x)) y else x
}
#' Validate Required String Parameter
#'
#' Internal function to validate that a string parameter is not empty or NULL.
#'
#' @param value Character. Value to validate.
#' @param param_name Character. Name of the parameter (for error messages).
#'
#' @return NULL (throws error if validation fails).
#' @keywords internal
validate_required_string <- function(value, param_name) {
if (is.null(value) || length(value) == 0 || value == "") {
stop(sprintf("Error: %s is required and cannot be empty.", param_name), call. = FALSE)
}
invisible(NULL)
}
#' Handle API Error Response
#'
#' Internal function to handle API error responses and generate user-friendly error messages.
#'
#' @param response HTTP response object from httr.
#' @param endpoint Character. Endpoint that was called (for error context).
#'
#' @return NULL (throws error with formatted message).
#' @keywords internal
handle_api_error <- function(response, endpoint) {
status <- httr2::resp_status(response)
# Try to extract error message from response body
error_msg <- tryCatch({
body <- httr2::resp_body_json(response)
body$message %||% body$error %||% "Unknown error"
}, error = function(e) {
"Unable to parse error response"
})
# Format error based on status code
if (status == 401) {
stop(sprintf(
"Authentication failed (401).\nEndpoint: %s\nPlease check your API key and workspace ID.",
endpoint
), call. = FALSE)
} else if (status == 403) {
stop(sprintf(
"Access denied (403).\nEndpoint: %s\nYou do not have permission to access this resource.\nDetails: %s",
endpoint,
error_msg
), call. = FALSE)
} else if (status == 404) {
stop(sprintf(
"Resource not found (404).\nEndpoint: %s\nThis resource does not exist or you do not have access.\nDetails: %s",
endpoint,
error_msg
), call. = FALSE)
} else if (status >= 500) {
stop(sprintf(
"Server error (%d).\nEndpoint: %s\nThe server encountered an error. Please try again later.\nDetails: %s",
status,
endpoint,
error_msg
), call. = FALSE)
} else {
stop(sprintf(
"API request failed (%d).\nEndpoint: %s\nDetails: %s",
status,
endpoint,
error_msg
), call. = FALSE)
}
}
#' Parse JSON Response
#'
#' Internal function to safely parse JSON response from API.
#'
#' @param response HTTP response object from httr2.
#'
#' @return Parsed JSON object.
#' @keywords internal
parse_json_response <- function(response) {
tryCatch({
httr2::resp_body_json(response, simplifyVector = FALSE)
}, error = function(e) {
stop(sprintf("Error parsing JSON response: %s", e$message), call. = FALSE)
})
}
#' Format Error Message with Generic Access Denial
#'
#' Returns a generic error message that doesn't leak information about resource existence.
#' Used for schema/table access errors in accordance with security policy.
#'
#' @param resource_type Character. Type of resource (e.g., "schema", "table").
#' @param resource_name Character. Name of the resource (optional).
#'
#' @return Character. Generic error message.
#' @keywords internal
format_generic_access_error <- function(resource_type, resource_name = NULL) {
if (!is.null(resource_name) && resource_name != "") {
sprintf("This %s does not exist or you do not have access.", resource_type)
} else {
sprintf("This %s does not exist or you do not have access.", resource_type)
}
}
#' Check if Response Indicates Access Denial
#'
#' Internal function to check if API response indicates access denial
#' (could be either non-existent or unauthorized).
#'
#' @param response HTTP response object from httr2.
#'
#' @return Logical. TRUE if access is denied.
#' @keywords internal
is_access_denied <- function(response) {
status <- httr2::resp_status(response)
return(status == 403 || status == 404)
}
#' Paginate Results
#'
#' Internal function to handle pagination of large result sets.
#'
#' @param data List. Full result set.
#' @param page Integer. Page number (0-indexed).
#' @param page_size Integer. Number of items per page.
#'
#' @return List with paginated data and metadata.
#' @keywords internal
paginate_results <- function(data, page = 0, page_size = 20) {
total <- length(data)
start_idx <- page * page_size + 1
end_idx <- min((page + 1) * page_size, total)
if (start_idx > total) {
return(list(
data = list(),
page = page,
page_size = page_size,
total = total,
pages = ceiling(total / page_size)
))
}
list(
data = data[start_idx:end_idx],
page = page,
page_size = page_size,
total = total,
pages = ceiling(total / page_size)
)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.