Nothing
#' Configure Lifebit Platform Profile
#'
#' Stores API credentials and workspace context for a named profile.
#' This is the required first step before any API wrapper call.
#'
#' @param profilename Character. Name of the profile to create or update.
#' @param apikey Character. API key for authentication.
#' @param workspace_id Character. Workspace/team ID for API requests.
#' @param base_url Character. Base URL for Lifebit Platform API (default: "https://cloudos.lifebit.ai").
#' @param set_default Logical. If TRUE, sets this profile as the default (default: FALSE).
#'
#' @return Invisible NULL. Prints a success message.
#' @export
#'
#' @examples
#' \dontrun{
#' cloudos.configure(
#' profilename = "production",
#' apikey = "your-api-key",
#' workspace_id = "5c6d3e9bd954e800b23f8c62",
#' set_default = TRUE
#' )
#' }
cloudos.configure <- function(profilename = "",
apikey = "",
workspace_id = "",
base_url = "https://cloudos.lifebit.ai",
set_default = FALSE) {
# Validate required inputs
if (profilename == "" || is.null(profilename)) {
stop("Error: profilename is required and cannot be empty.", call. = FALSE)
}
if (apikey == "" || is.null(apikey)) {
stop("Error: apikey is required and cannot be empty.", call. = FALSE)
}
if (workspace_id == "" || is.null(workspace_id)) {
stop("Error: workspace_id is required and cannot be empty.", call. = FALSE)
}
# Get config directory path
config_dir <- get_config_dir()
# Ensure config directory exists
if (!dir.exists(config_dir)) {
dir.create(config_dir, recursive = TRUE, mode = "0700")
}
# Get config file path
config_file <- get_config_file()
# Read existing config or create new
if (file.exists(config_file)) {
config_json <- tryCatch({
jsonlite::fromJSON(config_file, simplifyVector = FALSE)
}, error = function(e) {
list()
})
} else {
config_json <- list()
}
# If setting as default, unset default flag from other profiles
if (set_default) {
for (pname in names(config_json)) {
if (!is.null(config_json[[pname]]$default)) {
config_json[[pname]]$default <- FALSE
}
}
}
# Add or update profile
config_json[[profilename]] <- list(
apikey = apikey,
workspace_id = workspace_id,
base_url = base_url,
default = set_default,
created_at = format(Sys.time(), "%Y-%m-%d %H:%M:%S"),
updated_at = format(Sys.time(), "%Y-%m-%d %H:%M:%S")
)
# Write config file
tryCatch({
jsonlite::write_json(
config_json,
config_file,
pretty = TRUE,
auto_unbox = TRUE
)
# Set restrictive permissions on config file (user read/write only)
Sys.chmod(config_file, mode = "0600")
if (set_default) {
message(sprintf("Profile '%s' configured successfully and set as default.", profilename))
} else {
message(sprintf("Profile '%s' configured successfully.", profilename))
}
message(sprintf("Config stored at: %s", config_file))
invisible(NULL)
}, error = function(e) {
stop(sprintf("Error writing config file: %s", e$message), call. = FALSE)
})
}
#' List Lifebit Platform Profiles
#'
#' Lists configured profiles so users can confirm available environments.
#'
#' @return Data frame with profile names and metadata (workspace_id, default, created_at, updated_at).
#' Returns empty data frame if no profiles are configured.
#' @export
#'
#' @examples
#' \dontrun{
#' profiles <- cloudos.profile_list()
#' print(profiles)
#' }
cloudos.profile_list <- function() {
config_file <- get_config_file()
# Check if config file exists
if (!file.exists(config_file)) {
message("No profiles configured. Use cloudos.configure() to create a profile.")
return(data.frame(
profile_name = character(0),
workspace_id = character(0),
base_url = character(0),
default = logical(0),
created_at = character(0),
updated_at = character(0),
stringsAsFactors = FALSE
))
}
# Read config
config_json <- tryCatch({
jsonlite::fromJSON(config_file, simplifyVector = FALSE)
}, error = function(e) {
stop(sprintf("Error reading config file: %s", e$message), call. = FALSE)
})
# Check if config is empty
if (length(config_json) == 0) {
message("No profiles configured. Use cloudos.configure() to create a profile.")
return(data.frame(
profile_name = character(0),
workspace_id = character(0),
base_url = character(0),
default = logical(0),
created_at = character(0),
updated_at = character(0),
stringsAsFactors = FALSE
))
}
# Extract profile metadata
profiles <- lapply(names(config_json), function(profile_name) {
profile <- config_json[[profile_name]]
data.frame(
profile_name = profile_name,
workspace_id = profile$workspace_id %||% "",
base_url = profile$base_url %||% "https://cloudos.lifebit.ai",
default = profile$default %||% FALSE,
created_at = profile$created_at %||% "",
updated_at = profile$updated_at %||% "",
stringsAsFactors = FALSE
)
})
# Combine into single data frame
profiles_df <- do.call(rbind, profiles)
return(profiles_df)
}
#' Get Config Directory Path
#'
#' Internal function to get the Lifebit Platform config directory path.
#' Uses tools::R_user_dir() for CRAN-compliant persistent storage.
#' Can be overridden with CLOUDOS_CONFIG_DIR environment variable.
#'
#' @return Character. Path to config directory.
#' @keywords internal
get_config_dir <- function() {
config_dir <- Sys.getenv("CLOUDOS_CONFIG_DIR", "")
if (config_dir == "") {
# Use R's user config directory (CRAN-compliant)
config_dir <- tools::R_user_dir("cloudosR", which = "config")
}
return(config_dir)
}
#' Get Config File Path
#'
#' Internal function to get the Lifebit Platform config file path.
#' Config file is stored in the user's R config directory as .cloudos_config.json
#' using tools::R_user_dir() for CRAN compliance.
#'
#' @return Character. Path to config file.
#' @keywords internal
get_config_file <- function() {
return(file.path(get_config_dir(), ".cloudos_config.json"))
}
#' Load Profile Configuration
#'
#' Internal function to load a specific profile's configuration.
#' If profilename is empty or NULL, loads the default profile.
#'
#' @param profilename Character. Name of the profile to load. If empty, loads default profile.
#'
#' @return List with profile configuration (apikey, workspace_id, base_url).
#' @keywords internal
load_profile <- function(profilename = "") {
# If no profile specified, try to load default
load_default <- (profilename == "" || is.null(profilename))
config_file <- get_config_file()
if (!file.exists(config_file)) {
stop(sprintf(
"No configuration file found. Use cloudos.configure() to create a profile first.\nExpected location: %s",
config_file
), call. = FALSE)
}
# Read config
config_json <- tryCatch({
jsonlite::fromJSON(config_file, simplifyVector = FALSE)
}, error = function(e) {
stop(sprintf("Error reading config file: %s", e$message), call. = FALSE)
})
# If loading default profile, find it
if (load_default) {
default_profile <- NULL
for (pname in names(config_json)) {
if (isTRUE(config_json[[pname]]$default)) {
default_profile <- pname
profilename <- pname
break
}
}
if (is.null(default_profile)) {
available_profiles <- paste(names(config_json), collapse = ", ")
stop(sprintf(
"No default profile configured.\nAvailable profiles: %s\nSpecify profilename or set a default with cloudos.configure(..., set_default = TRUE)",
available_profiles
), call. = FALSE)
}
} else {
# Check if specified profile exists
if (!profilename %in% names(config_json)) {
available_profiles <- paste(names(config_json), collapse = ", ")
stop(sprintf(
"Profile '%s' not found.\nAvailable profiles: %s\nUse cloudos.configure() to create this profile.",
profilename,
available_profiles
), call. = FALSE)
}
}
profile <- config_json[[profilename]]
# Validate profile has required fields
if (is.null(profile$apikey) || profile$apikey == "") {
stop(sprintf("Profile '%s' is missing apikey.", profilename), call. = FALSE)
}
if (is.null(profile$workspace_id) || profile$workspace_id == "") {
stop(sprintf("Profile '%s' is missing workspace_id.", profilename), call. = FALSE)
}
# Set default base_url if not present
if (is.null(profile$base_url) || profile$base_url == "") {
profile$base_url <- "https://cloudos.lifebit.ai"
}
return(profile)
}
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.