diff --git a/DESCRIPTION b/DESCRIPTION index b259ebe..e1217c8 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -13,6 +13,8 @@ Description: Automatically generate R package skeletons from 'application License: MIT + file LICENSE URL: https://beekeeper.api2r.org, https://github.com/jonthegeek/beekeeper BugReports: https://github.com/jonthegeek/beekeeper/issues +Depends: + R (>= 3.5.0) Imports: cli, desc, @@ -27,6 +29,7 @@ Imports: rprojroot, S7, snakecase, + stringr, styler, testthat, usethis, @@ -36,7 +39,6 @@ Suggests: covr, knitr, rmarkdown, - stringr, withr VignetteBuilder: knitr @@ -46,4 +48,4 @@ Remotes: Config/testthat/edition: 3 Encoding: UTF-8 Roxygen: list(markdown = TRUE) -RoxygenNote: 7.2.3 +RoxygenNote: 7.3.1 diff --git a/NAMESPACE b/NAMESPACE index a4e2a02..75a52a5 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -4,11 +4,46 @@ export(generate_pkg) export(generate_pkg_agent) export(use_beekeeper) if (getRversion() < "4.3.0") importFrom("S7", "@") +importFrom(S7,class_any) +importFrom(cli,cli_abort) +importFrom(cli,cli_warn) +importFrom(desc,desc) +importFrom(fs,is_dir) +importFrom(fs,path) +importFrom(fs,path_dir) +importFrom(fs,path_file) +importFrom(fs,path_rel) importFrom(glue,glue) +importFrom(glue,glue_collapse) importFrom(httptest2,use_httptest2) +importFrom(lubridate,now) +importFrom(lubridate,parse_date_time) importFrom(nectar,call_api) +importFrom(nectar,stabilize_string) +importFrom(purrr,map) +importFrom(purrr,map2) +importFrom(purrr,map_chr) +importFrom(purrr,pmap) +importFrom(purrr,quietly) importFrom(rapid,as_rapid) +importFrom(rapid,class_api_key_security_scheme) +importFrom(rapid,class_security_scheme_details) +importFrom(rapid,class_security_schemes) importFrom(rlang,.data) +importFrom(rlang,set_names) +importFrom(rlang,try_fetch) +importFrom(rprojroot,find_package_root_file) +importFrom(snakecase,to_snake_case) +importFrom(stringr,str_remove) +importFrom(styler,style_file) importFrom(testthat,test_that) +importFrom(usethis,proj_get) +importFrom(usethis,proj_path) importFrom(usethis,use_build_ignore) +importFrom(usethis,use_directory) importFrom(usethis,use_package) +importFrom(usethis,use_template) +importFrom(usethis,use_testthat) +importFrom(utils,capture.output) +importFrom(yaml,read_yaml) +importFrom(yaml,write_yaml) diff --git a/R/as_bk_data.R b/R/as_bk_data.R index 90ee64a..f730e88 100644 --- a/R/as_bk_data.R +++ b/R/as_bk_data.R @@ -13,7 +13,7 @@ as_bk_data <- S7::new_generic( dispatch_args = "x" ) -S7::method(as_bk_data, rapid::class_security_schemes) <- function(x) { +S7::method(as_bk_data, class_security_schemes) <- function(x) { if (!length(x)) { return(list()) } @@ -22,7 +22,7 @@ S7::method(as_bk_data, rapid::class_security_schemes) <- function(x) { } .security_schemes_collect <- function(x) { - purrr::pmap( + pmap( list( x@name, x@details, @@ -35,7 +35,7 @@ S7::method(as_bk_data, rapid::class_security_schemes) <- function(x) { .security_scheme_rotate <- function(name, details, description) { security_scheme <- c( list( - name = snakecase::to_snake_case(name), + name = to_snake_case(name), description = description ), as_bk_data(details) @@ -51,7 +51,7 @@ S7::method(as_bk_data, rapid::class_security_schemes) <- function(x) { if (is.na(description)) { return( switch(type, - api_key = .security_scheme_description_api_key(), + api_key = .security_scheme_description_api_key, NA_character_ ) ) @@ -59,13 +59,11 @@ S7::method(as_bk_data, rapid::class_security_schemes) <- function(x) { return(description) # nocov } -.security_scheme_description_api_key <- function() { - paste( - "An API key provided by the API provider.", - "This key is not clearly documented in the API description.", - "Check the API documentation for details." - ) -} +.security_scheme_description_api_key <- paste( + "An API key provided by the API provider.", + "This key is not clearly documented in the API description.", + "Check the API documentation for details." +) .security_scheme_collection_finalize <- function(security_schemes) { security_scheme_data <- c( @@ -79,49 +77,48 @@ S7::method(as_bk_data, rapid::class_security_schemes) <- function(x) { } .security_args_compile <- function(security_schemes) { - security_args <- sort(unique(purrr::map_chr(security_schemes, "arg_name"))) + security_args <- sort(unique(map_chr(security_schemes, "arg_name"))) return(list( security_arg_names = security_args, security_arg_list = .collapse_comma( - glue::glue("{security_args} = {security_args}") + glue("{security_args} = {security_args}") ), - security_arg_helps = .security_arg_help_generate( + security_arg_helps = .generate_security_arg_help( security_schemes, security_args ) )) } -.security_arg_help_generate <- function(security_schemes, security_args) { - security_arg_description <- rlang::set_names( - purrr::map_chr(security_schemes, "description"), - purrr::map_chr(security_schemes, "arg_name") +.generate_security_arg_help <- function(security_schemes, security_args) { + security_arg_description <- set_names( + map_chr(security_schemes, "description"), + map_chr(security_schemes, "arg_name") ) security_arg_description <- unname(security_arg_description[security_args]) return( - purrr::map2( + map2( security_arg_description, security_args, - function(arg_description, arg_name) { - list(name = arg_name, description = arg_description) - } + .security_arg_description_clean ) ) } -S7::method(as_bk_data, rapid::class_security_scheme_details) <- function(x) { - purrr::map(x, as_bk_data) +.security_arg_description_clean <- function(arg_description, arg_name) { + list(name = arg_name, description = arg_description) +} + +S7::method(as_bk_data, class_security_scheme_details) <- function(x) { + map(x, as_bk_data) } -S7::method(as_bk_data, rapid::class_api_key_security_scheme) <- function(x) { +S7::method(as_bk_data, class_api_key_security_scheme) <- function(x) { if (length(x)) { return( list( parameter_name = x@parameter_name, - arg_name = stringr::str_remove( - snakecase::to_snake_case(x@parameter_name), - "^x_" - ), + arg_name = str_remove(to_snake_case(x@parameter_name), "^x_"), location = x@location, type = "api_key", api_key = TRUE @@ -131,8 +128,8 @@ S7::method(as_bk_data, rapid::class_api_key_security_scheme) <- function(x) { return(list()) } -S7::method(as_bk_data, S7::class_any) <- function(x) { - cli::cli_warn( +S7::method(as_bk_data, class_any) <- function(x) { + cli_warn( "No method for as_bk_data() for class {.cls {class(x)}}." ) return(list()) diff --git a/R/beekeeper-package.R b/R/beekeeper-package.R index ef2d4cd..450d807 100644 --- a/R/beekeeper-package.R +++ b/R/beekeeper-package.R @@ -2,12 +2,48 @@ "_PACKAGE" ## usethis namespace: start +#' @importFrom cli cli_abort +#' @importFrom cli cli_warn +#' @importFrom desc desc +#' @importFrom fs is_dir +#' @importFrom fs path +#' @importFrom fs path_dir +#' @importFrom fs path_file +#' @importFrom fs path_rel #' @importFrom glue glue +#' @importFrom glue glue_collapse #' @importFrom httptest2 use_httptest2 +#' @importFrom lubridate now +#' @importFrom lubridate parse_date_time #' @importFrom nectar call_api +#' @importFrom nectar stabilize_string +#' @importFrom purrr map +#' @importFrom purrr map_chr +#' @importFrom purrr map2 +#' @importFrom purrr pmap +#' @importFrom purrr quietly #' @importFrom rapid as_rapid +#' @importFrom rapid class_api_key_security_scheme +#' @importFrom rapid class_security_scheme_details +#' @importFrom rapid class_security_schemes #' @importFrom rlang .data +#' @importFrom rlang set_names +#' @importFrom rlang try_fetch +#' @importFrom rprojroot find_package_root_file +#' @importFrom S7 class_any +#' @importFrom snakecase to_snake_case +#' @importFrom stringr str_remove +#' @importFrom styler style_file #' @importFrom testthat test_that +#' @importFrom usethis proj_get +#' @importFrom usethis proj_path +#' @importFrom usethis use_build_ignore +#' @importFrom usethis use_directory #' @importFrom usethis use_package +#' @importFrom usethis use_template +#' @importFrom usethis use_testthat +#' @importFrom utils capture.output +#' @importFrom yaml read_yaml +#' @importFrom yaml write_yaml ## usethis namespace: end NULL diff --git a/R/generate.R b/R/generate.R deleted file mode 100644 index 1b7213d..0000000 --- a/R/generate.R +++ /dev/null @@ -1,92 +0,0 @@ -#' Use a beekeeper config file to generate code -#' -#' Creates or updates package files based on the information in a beekeeper -#' config file (generated by [use_beekeeper()] or manually). The files enforce -#' an opinionated framework for API packages. -#' -#' @param config_file The path to a beekeeper yaml file. -#' @param pkg_agent A string to identify this package, for use in the -#' `user_agent` argument of [nectar::call_api()]. -#' -#' @return A character vector of paths to files that were added or updated, -#' invisibly. -#' @export -generate_pkg <- function(config_file = "_beekeeper.yml", - pkg_agent = generate_pkg_agent(config_file)) { - .assert_is_pkg() - config <- .read_config(config_file) - api_definition <- .read_api_definition(config_file, config$rapid_file) - .prepare_r() - touched_files <- .generate_basics(config, api_definition, pkg_agent) - return(invisible(touched_files)) -} - -.read_api_definition <- function(config_file, rapid_file) { - readRDS( - fs::path(fs::path_dir(config_file), rapid_file) - ) -} - -.generate_basics <- function(config, api_definition, pkg_agent) { - security_data <- .generate_security( - config$api_abbr, - api_definition@components@security_schemes - ) - - data <- list( - api_title = nectar::stabilize_string(config$api_title), - api_abbr = nectar::stabilize_string(config$api_abbr), - base_url = nectar::stabilize_string(api_definition@servers@url), - pkg_agent = nectar::stabilize_string(pkg_agent) - ) - data <- c(data, security_data) - - touched_files <- c( - .bk_use_template( - template = "010-call.R", - data = data - ), - .bk_use_template( - template = "test-010-call.R", - dir = "tests/testthat", - data = list(api_abbr = config$api_abbr) - ) - ) - return(invisible(touched_files)) -} - -.prepare_r <- function() { - usethis::use_directory("R") - usethis::use_testthat() - purrr::quietly(httptest2::use_httptest2)() - usethis::use_package("nectar") - usethis::use_package("beekeeper", type = "Suggests") -} - -#' Use a template in this package -#' -#' @param template The name of the template. -#' @param dir The directory where the file should be created. -#' @param data A list of variables to apply to the template. -#' -#' @return The path to the generated or updated file, invisibly. -#' @keywords internal -.bk_use_template <- function(template, - dir = c("R", "tests/testthat"), - data) { - dir <- match.arg(dir) - target <- usethis::proj_path(dir, template) - save_as <- fs::path_rel(target, usethis::proj_path()) - - usethis::use_template( - template = template, - save_as = save_as, - data = data, - package = "beekeeper" - ) - utils::capture.output({ - styler::style_file(target) - }) - - return(invisible(target)) -} diff --git a/R/generate_pkg_agent.R b/R/generate_pkg-agent.R similarity index 63% rename from R/generate_pkg_agent.R rename to R/generate_pkg-agent.R index 6afdb79..56fbf19 100644 --- a/R/generate_pkg_agent.R +++ b/R/generate_pkg-agent.R @@ -8,19 +8,24 @@ #' #' @export generate_pkg_agent <- function(path = ".") { - if (!fs::is_dir(path) && fs::path_file(path) != "DESCRIPTION") { - path <- fs::path_dir(path) # nocov + if (!is_dir(path) && path_file(path) != "DESCRIPTION") { + path <- path_dir(path) # nocov } - pkg_desc <- desc::desc(file = path) + pkg_desc <- desc(file = path) pkg_name <- pkg_desc$get_field("Package") + pkg_url <- .get_pkg_url(pkg_desc) + return( + glue("{pkg_name}{pkg_url}") + ) +} + +.get_pkg_url <- function(pkg_desc) { pkg_url_glue <- "" pkg_url <- pkg_desc$get_urls() if (length(pkg_url)) { - pkg_url_glue <- glue::glue( + pkg_url_glue <- glue( " ({pkg_url[[1]]})" ) } - return( - glue::glue("{pkg_name}{pkg_url_glue}") - ) + return(pkg_url_glue) } diff --git a/R/generate_pkg-call.R b/R/generate_pkg-call.R new file mode 100644 index 0000000..8e0e04e --- /dev/null +++ b/R/generate_pkg-call.R @@ -0,0 +1,31 @@ +.generate_call <- function(config, api_definition, pkg_agent, security_data) { + touched_files <- c( + .generate_call_r(config, api_definition, pkg_agent, security_data), + .generate_call_test(config$api_abbr) + ) + return(touched_files) +} + +.generate_call_r <- function(config, api_definition, pkg_agent, security_data) { + .bk_use_template( + template = "010-call.R", + data = list( + api_title = config$api_title, + api_abbr = config$api_abbr, + base_url = api_definition@servers@url, + pkg_agent = pkg_agent, + has_security = security_data$has_security, + security_arg_helps = security_data$security_arg_helps, + security_signature = security_data$security_signature, + security_arg_list = security_data$security_arg_list + ) + ) +} + +.generate_call_test <- function(api_abbr) { + .bk_use_template( + template = "test-010-call.R", + dir = "tests/testthat", + data = list(api_abbr = api_abbr) + ) +} diff --git a/R/generate_pkg-prepare.R b/R/generate_pkg-prepare.R new file mode 100644 index 0000000..92c147d --- /dev/null +++ b/R/generate_pkg-prepare.R @@ -0,0 +1,63 @@ +#' Error if not in package +#' +#' @inheritParams .is_pkg +#' +#' @return `NULL`, invisibly. +#' @keywords internal +.assert_is_pkg <- function(base_path = usethis::proj_get()) { + if (.is_pkg(base_path)) { + return(invisible(NULL)) + } + cli::cli_abort(c( + "Can't generate package files outside of a package.", + x = "{.path {base_path}} is not inside a package." + )) +} + +#' Check whether we're in a package +#' +#' Inspired by usethis:::is_package. +#' +#' @param base_path The root URL of the current project. +#' +#' @return `TRUE` if the project is a package, `FALSE` if not. +#' @keywords internal +.is_pkg <- function(base_path = usethis::proj_get()) { + root_file <- rlang::try_fetch( + rprojroot::find_package_root_file(path = base_path), + error = function(cnd) NULL + ) + !is.null(root_file) +} + +.read_config <- function(config_file = "_beekeeper.yml") { + config <- yaml::read_yaml(config_file) + config <- .stabilize_config(config) + return(config) +} + +.stabilize_config <- function(config) { + config$api_title <- stabilize_string(config$api_title) + config$api_abbr <- stabilize_string(config$api_abbr) + config$api_version <- stabilize_string(config$api_version) + config$rapid_file <- stabilize_string(config$rapid_file) + config$updated_on <- parse_date_time( + config$updated_on, + orders = c("ymd HMS", "ymd H", "ymd") + ) + return(config) +} + +.read_api_definition <- function(config_file, rapid_file) { + readRDS( + path(path_dir(config_file), rapid_file) + ) +} + +.prepare_r <- function() { + use_directory("R") + use_testthat() + quietly(use_httptest2)() + use_package("nectar") + use_package("beekeeper", type = "Suggests") +} diff --git a/R/security.R b/R/generate_pkg-security.R similarity index 58% rename from R/security.R rename to R/generate_pkg-security.R index ae980b6..aa6fd35 100644 --- a/R/security.R +++ b/R/generate_pkg-security.R @@ -1,21 +1,21 @@ .generate_security <- function(api_abbr, security_schemes) { security_data <- as_bk_data(security_schemes) if (length(security_data)) { - .bk_use_template( + security_data$security_file_path <- .bk_use_template( template = "020-security.R", data = c(security_data, api_abbr = api_abbr) ) - security_data$security_signature <- .security_signature_generate( + security_data$security_signature <- .generate_security_signature( security_data$security_arg_names, api_abbr ) } return(security_data) } -.security_signature_generate <- function(security_arg_names, api_abbr) { - env_vars <- toupper(glue::glue("{api_abbr}_{security_arg_names}")) +.generate_security_signature <- function(security_arg_names, api_abbr) { + env_vars <- toupper(glue("{api_abbr}_{security_arg_names}")) return( - .collapse_comma_newline(c("", glue::glue( + .collapse_comma_newline(c("", glue( "{security_arg_names} = Sys.getenv(\"{env_vars}\")" ))) ) diff --git a/R/generate_pkg-template.R b/R/generate_pkg-template.R new file mode 100644 index 0000000..e780299 --- /dev/null +++ b/R/generate_pkg-template.R @@ -0,0 +1,27 @@ +#' Use a template in this package +#' +#' @param template The name of the template. +#' @param dir The directory where the file should be created. +#' @param data A list of variables to apply to the template. +#' +#' @return The path to the generated or updated file, invisibly. +#' @keywords internal +.bk_use_template <- function(template, + dir = c("R", "tests/testthat"), + data) { + dir <- match.arg(dir) + target <- proj_path(dir, template) + save_as <- path_rel(target, proj_path()) + + use_template( + template = template, + save_as = save_as, + data = data, + package = "beekeeper" + ) + capture.output({ + style_file(target) + }) + + return(invisible(target)) +} diff --git a/R/generate_pkg_main.R b/R/generate_pkg_main.R new file mode 100644 index 0000000..2daf28f --- /dev/null +++ b/R/generate_pkg_main.R @@ -0,0 +1,32 @@ +#' Use a beekeeper config file to generate code +#' +#' Creates or updates package files based on the information in a beekeeper +#' config file (generated by [use_beekeeper()] or manually). The files enforce +#' an opinionated framework for API packages. +#' +#' @param config_file The path to a beekeeper yaml file. +#' @param pkg_agent A string to identify this package, for use in the +#' `user_agent` argument of [nectar::call_api()]. +#' +#' @return A character vector of paths to files that were added or updated, +#' invisibly. +#' @export +generate_pkg <- function(config_file = "_beekeeper.yml", + pkg_agent = generate_pkg_agent(config_file)) { + .assert_is_pkg() + config <- .read_config(config_file) + api_definition <- .read_api_definition(config_file, config$rapid_file) + .prepare_r() + touched_files <- .generate_pkg_impl(config, api_definition, pkg_agent) + return(invisible(touched_files)) +} + +.generate_pkg_impl <- function(config, api_definition, pkg_agent) { + security_data <- .generate_security( + config$api_abbr, + api_definition@components@security_schemes + ) + call_files <- .generate_call(config, api_definition, pkg_agent, security_data) + touched_files <- c(call_files, security_data$security_file_path) + return(invisible(touched_files)) +} diff --git a/R/use_beekeeper.R b/R/use_beekeeper.R index 99571bd..58fcee4 100644 --- a/R/use_beekeeper.R +++ b/R/use_beekeeper.R @@ -5,78 +5,51 @@ #' and the timestamp when the configuration was last updated or used. #' #' @inheritParams rlang::args_dots_empty -#' @param x An object to use to define the configuration, such as a -#' [rapid::class_rapid()] or a url to an OpenAPI document. +#' @param x An object to use to define the configuration. It must be +#' translatable to a [rapid::class_rapid()] object by [rapid::as_rapid()]. Usually +#' this will be a url pointing to an OpenAPI document, or a list generated by +#' reading such a document. #' @param api_abbr A short (about 2-5 letter) abbreviation for the API, for use #' in function names and environment variables. -#' @param config_file The path to the configuration file to write. -#' @param rapid_file The path to the rapid rds file to write. +#' @param config_file The path to which the configuration should be written. +#' @param rapid_file The path to which the R API definition (rapid) object +#' should be written. #' #' @return The path to the configuration file, invisibly. The config file is #' written as a side effect of this function. The rapid object is also #' written, and the path to that file is saved in the config file. #' @export -use_beekeeper <- S7::new_generic( - "use_beekeeper", - "x", - function(x, - api_abbr, - ..., - config_file = "_beekeeper.yml", - rapid_file = "_beekeeper_rapid.rds") { - rlang::check_dots_empty() - S7::S7_dispatch() - } -) +use_beekeeper <- function(x, + api_abbr, + ..., + config_file = "_beekeeper.yml", + rapid_file = "_beekeeper_rapid.rds") { + x <- as_rapid(x) + rapid_file <- .write_rapid(x, rapid_file) + config_file <- .write_config(x, api_abbr, rapid_file, config_file) -#' @importFrom usethis use_build_ignore -S7::method(use_beekeeper, rapid::class_rapid) <- - function(x, - api_abbr, - ..., - config_file = "_beekeeper.yml", - rapid_file = "_beekeeper_rapid.rds") { - api_abbr <- nectar::stabilize_string(api_abbr) - config_file <- nectar::stabilize_string(config_file) - rapid_file <- nectar::stabilize_string(rapid_file) - saveRDS(x, rapid_file) - - use_build_ignore(c(config_file, rapid_file)) - - yaml::write_yaml( - list( - api_title = x@info@title, - api_abbr = api_abbr, - api_version = x@info@version, - rapid_file = fs::path_rel(rapid_file, fs::path_dir(config_file)), - updated_on = as.character(lubridate::now(tzone = "UTC")) - ), - file = config_file - ) - return(invisible(config_file)) - } + return(invisible(config_file)) +} -S7::method(use_beekeeper, S7::class_any) <- - function(x, - api_abbr, - ..., - config_file = "_beekeeper.yml", - rapid_file = "_beekeeper_rapid.rds") { - x <- as_rapid(x) - use_beekeeper( - x, - api_abbr, - ..., - config_file = config_file, - rapid_file = rapid_file - ) - } +.write_rapid <- function(x, rapid_file) { + rapid_file <- stabilize_string(rapid_file) + saveRDS(x, rapid_file) + use_build_ignore(rapid_file) + return(rapid_file) +} -.read_config <- function(config_file = "_beekeeper.yml") { - config <- yaml::read_yaml(config_file) - config$updated_on <- lubridate::parse_date_time( - config$updated_on, - orders = c("ymd HMS", "ymd H", "ymd") +.write_config <- function(x, api_abbr, rapid_file, config_file) { + config_file <- stabilize_string(config_file) + write_yaml( + list( + api_title = x@info@title, + api_abbr = stabilize_string(api_abbr), + api_version = x@info@version, + rapid_file = path_rel(rapid_file, path_dir(config_file)), + updated_on = as.character(now(tzone = "UTC")) + ), + file = config_file ) - return(config) + use_build_ignore(config_file) + return(config_file) } diff --git a/R/utils.R b/R/utils.R index 7ffc685..326b0ac 100644 --- a/R/utils.R +++ b/R/utils.R @@ -1,35 +1,3 @@ -#' Check whether we're in a package -#' -#' Inspired by usethis:::is_package. -#' -#' @param base_path The root URL of the current project. -#' -#' @return `TRUE` if the project is a package, `FALSE` if not. -#' @keywords internal -.is_pkg <- function(base_path = usethis::proj_get()) { - root_file <- rlang::try_fetch( - rprojroot::find_package_root_file(path = base_path), - error = function(cnd) NULL - ) - !is.null(root_file) -} - -#' Error if not in package -#' -#' @inheritParams .is_pkg -#' -#' @return `NULL`, invisibly. -#' @keywords internal -.assert_is_pkg <- function(base_path = usethis::proj_get()) { - if (.is_pkg(base_path)) { - return(invisible(NULL)) - } - cli::cli_abort(c( - "Can't generate package files outside of a package.", - x = "{.path {base_path}} is not inside a package." - )) -} - `%|0|%` <- function(x, y) { if (!length(x)) { y @@ -39,9 +7,9 @@ } .collapse_comma <- function(x) { - glue::glue_collapse(x, sep = ", ") + glue_collapse(x, sep = ", ") } .collapse_comma_newline <- function(x) { - glue::glue_collapse(x, sep = ",\n") + glue_collapse(x, sep = ",\n") } diff --git a/man/dot-assert_is_pkg.Rd b/man/dot-assert_is_pkg.Rd index 2557f31..a486924 100644 --- a/man/dot-assert_is_pkg.Rd +++ b/man/dot-assert_is_pkg.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils.R +% Please edit documentation in R/generate_pkg-prepare.R \name{.assert_is_pkg} \alias{.assert_is_pkg} \title{Error if not in package} diff --git a/man/dot-bk_use_template.Rd b/man/dot-bk_use_template.Rd index 1e28ba2..fb97b67 100644 --- a/man/dot-bk_use_template.Rd +++ b/man/dot-bk_use_template.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/generate.R +% Please edit documentation in R/generate_pkg-template.R \name{.bk_use_template} \alias{.bk_use_template} \title{Use a template in this package} diff --git a/man/dot-is_pkg.Rd b/man/dot-is_pkg.Rd index d0126e8..04ff632 100644 --- a/man/dot-is_pkg.Rd +++ b/man/dot-is_pkg.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils.R +% Please edit documentation in R/generate_pkg-prepare.R \name{.is_pkg} \alias{.is_pkg} \title{Check whether we're in a package} diff --git a/man/generate_pkg.Rd b/man/generate_pkg.Rd index 83ec626..52ea2c5 100644 --- a/man/generate_pkg.Rd +++ b/man/generate_pkg.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/generate.R +% Please edit documentation in R/generate_pkg_main.R \name{generate_pkg} \alias{generate_pkg} \title{Use a beekeeper config file to generate code} diff --git a/man/generate_pkg_agent.Rd b/man/generate_pkg_agent.Rd index e0560cb..1ed369d 100644 --- a/man/generate_pkg_agent.Rd +++ b/man/generate_pkg_agent.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/generate_pkg_agent.R +% Please edit documentation in R/generate_pkg-agent.R \name{generate_pkg_agent} \alias{generate_pkg_agent} \title{Create a user agent for the active package} diff --git a/man/use_beekeeper.Rd b/man/use_beekeeper.Rd index 3ac059d..d292c7d 100644 --- a/man/use_beekeeper.Rd +++ b/man/use_beekeeper.Rd @@ -13,17 +13,20 @@ use_beekeeper( ) } \arguments{ -\item{x}{An object to use to define the configuration, such as a -\code{\link[rapid:class_rapid]{rapid::class_rapid()}} or a url to an OpenAPI document.} +\item{x}{An object to use to define the configuration. It must be +translatable to a \code{\link[rapid:class_rapid]{rapid::class_rapid()}} object by \code{\link[rapid:as_rapid]{rapid::as_rapid()}}. Usually +this will be a url pointing to an OpenAPI document, or a list generated by +reading such a document.} \item{api_abbr}{A short (about 2-5 letter) abbreviation for the API, for use in function names and environment variables.} \item{...}{These dots are for future extensions and must be empty.} -\item{config_file}{The path to the configuration file to write.} +\item{config_file}{The path to which the configuration should be written.} -\item{rapid_file}{The path to the rapid rds file to write.} +\item{rapid_file}{The path to which the R API definition (rapid) object +should be written.} } \value{ The path to the configuration file, invisibly. The config file is diff --git a/tests/testthat/_snaps/utils.md b/tests/testthat/_snaps/generate_pkg-prepare.md similarity index 100% rename from tests/testthat/_snaps/utils.md rename to tests/testthat/_snaps/generate_pkg-prepare.md diff --git a/tests/testthat/helper.R b/tests/testthat/helper.R index 37a906f..f0a3738 100644 --- a/tests/testthat/helper.R +++ b/tests/testthat/helper.R @@ -5,6 +5,7 @@ create_local_package <- function(pkgname = "testpkg", withr::local_options(usethis.quiet = TRUE, .local_envir = env) dir <- withr::local_tempdir(pattern = pkgname, .local_envir = env) + dir <- unclass(fs::path_norm(dir)) usethis::create_package( dir, diff --git a/tests/testthat/test-generate_pkg_agent.R b/tests/testthat/test-generate_pkg-agent.R similarity index 100% rename from tests/testthat/test-generate_pkg_agent.R rename to tests/testthat/test-generate_pkg-agent.R diff --git a/tests/testthat/test-generate_pkg-call.R b/tests/testthat/test-generate_pkg-call.R new file mode 100644 index 0000000..2295186 --- /dev/null +++ b/tests/testthat/test-generate_pkg-call.R @@ -0,0 +1,31 @@ +test_that("generate_pkg() generates call function.", { + skip_on_cran() + config <- readLines(test_path("_fixtures", "guru_beekeeper.yml")) + guru_rapid <- readRDS(test_path("_fixtures", "guru_rapid.rds")) + call_expected <- readLines(test_path("_fixtures", "guru-010-call.R")) + + create_local_package() + writeLines(config, "_beekeeper.yml") + saveRDS(guru_rapid, "guru_rapid.rds") + + generate_pkg(pkg_agent = "TESTPKG (https://example.com)") + + call_result <- scrub_testpkg(readLines("R/010-call.R")) + expect_identical(call_result, call_expected) +}) + +test_that("generate_pkg() generates call function test.", { + skip_on_cran() + config <- readLines(test_path("_fixtures", "guru_beekeeper.yml")) + guru_rapid <- readRDS(test_path("_fixtures", "guru_rapid.rds")) + t_call_expected <- readLines(test_path("_fixtures", "guru-test-010-call.R")) + + create_local_package() + writeLines(config, "_beekeeper.yml") + saveRDS(guru_rapid, "guru_rapid.rds") + + generate_pkg(pkg_agent = "TESTPKG (https://example.com)") + + t_call_result <- readLines("tests/testthat/test-010-call.R") + expect_identical(t_call_result, t_call_expected) +}) diff --git a/tests/testthat/test-generate.R b/tests/testthat/test-generate_pkg-prepare.R similarity index 63% rename from tests/testthat/test-generate.R rename to tests/testthat/test-generate_pkg-prepare.R index 94348c9..06e3851 100644 --- a/tests/testthat/test-generate.R +++ b/tests/testthat/test-generate_pkg-prepare.R @@ -1,38 +1,12 @@ -test_that("generate_pkg() adds beekeeper to suggests.", { - skip_on_cran() - config <- readLines(test_path("_fixtures", "guru_beekeeper.yml")) - guru_rapid <- readRDS(test_path("_fixtures", "guru_rapid.rds")) - - create_local_package() - writeLines(config, "_beekeeper.yml") - saveRDS(guru_rapid, "guru_rapid.rds") - - generate_pkg(pkg_agent = "TESTPKG (https://example.com)") - - dependencies <- desc::desc()$get_deps() - expect_contains( - dependencies$package[dependencies$type == "Suggests"], - "beekeeper" +test_that(".assert_is_pkg() errors informatively for non-packages", { + expect_snapshot( + .assert_is_pkg(tempdir()), + error = TRUE, + transform = scrub_tempdir ) }) -test_that("generate_pkg() generates call function.", { - skip_on_cran() - config <- readLines(test_path("_fixtures", "guru_beekeeper.yml")) - guru_rapid <- readRDS(test_path("_fixtures", "guru_rapid.rds")) - call_expected <- readLines(test_path("_fixtures", "guru-010-call.R")) - - create_local_package() - writeLines(config, "_beekeeper.yml") - saveRDS(guru_rapid, "guru_rapid.rds") - - generate_pkg(pkg_agent = "TESTPKG (https://example.com)") - - call_result <- scrub_testpkg(readLines("R/010-call.R")) - expect_identical(call_result, call_expected) -}) - -test_that("generate_pkg() adds nectar import.", { +test_that("generate_pkg() adds nectar to import.", { skip_on_cran() config <- readLines(test_path("_fixtures", "guru_beekeeper.yml")) guru_rapid <- readRDS(test_path("_fixtures", "guru_rapid.rds")) @@ -50,11 +24,10 @@ test_that("generate_pkg() adds nectar import.", { ) }) -test_that("generate_pkg() generates call function test.", { +test_that("generate_pkg() adds beekeeper to suggests.", { skip_on_cran() config <- readLines(test_path("_fixtures", "guru_beekeeper.yml")) guru_rapid <- readRDS(test_path("_fixtures", "guru_rapid.rds")) - t_call_expected <- readLines(test_path("_fixtures", "guru-test-010-call.R")) create_local_package() writeLines(config, "_beekeeper.yml") @@ -62,11 +35,14 @@ test_that("generate_pkg() generates call function test.", { generate_pkg(pkg_agent = "TESTPKG (https://example.com)") - t_call_result <- readLines("tests/testthat/test-010-call.R") - expect_identical(t_call_result, t_call_expected) + dependencies <- desc::desc()$get_deps() + expect_contains( + dependencies$package[dependencies$type == "Suggests"], + "beekeeper" + ) }) -test_that("generate_pkg() adds testthat to suggests.", { +test_that("generate_pkg() adds httptest2 to suggests.", { skip_on_cran() config <- readLines(test_path("_fixtures", "guru_beekeeper.yml")) guru_rapid <- readRDS(test_path("_fixtures", "guru_rapid.rds")) @@ -80,11 +56,11 @@ test_that("generate_pkg() adds testthat to suggests.", { dependencies <- desc::desc()$get_deps() expect_contains( dependencies$package[dependencies$type == "Suggests"], - "testthat" + "httptest2" ) }) -test_that("generate_pkg() adds httptest2 to suggests.", { +test_that("generate_pkg() adds testthat to suggests.", { skip_on_cran() config <- readLines(test_path("_fixtures", "guru_beekeeper.yml")) guru_rapid <- readRDS(test_path("_fixtures", "guru_rapid.rds")) @@ -98,6 +74,6 @@ test_that("generate_pkg() adds httptest2 to suggests.", { dependencies <- desc::desc()$get_deps() expect_contains( dependencies$package[dependencies$type == "Suggests"], - "httptest2" + "testthat" ) }) diff --git a/tests/testthat/test-security.R b/tests/testthat/test-generate_pkg-security.R similarity index 100% rename from tests/testthat/test-security.R rename to tests/testthat/test-generate_pkg-security.R diff --git a/tests/testthat/test-generate_pkg_main.R b/tests/testthat/test-generate_pkg_main.R new file mode 100644 index 0000000..01c35fe --- /dev/null +++ b/tests/testthat/test-generate_pkg_main.R @@ -0,0 +1,20 @@ +test_that("generate_pkg() returns a vector of created files", { + skip_on_cran() + config <- readLines(test_path("_fixtures", "guru_beekeeper.yml")) + guru_rapid <- readRDS(test_path("_fixtures", "guru_rapid.rds")) + + test_dir <- create_local_package() + writeLines(config, "_beekeeper.yml") + saveRDS(guru_rapid, "guru_rapid.rds") + + test_result <- generate_pkg(pkg_agent = "TESTPKG (https://example.com)") + expected_result <- paste0( + test_dir, + c( + "/R/010-call.R", + "/tests/testthat/test-010-call.R" + ) + ) + + expect_identical(test_result, expected_result) +}) diff --git a/tests/testthat/test-utils.R b/tests/testthat/test-utils.R index 589527a..385fbe9 100644 --- a/tests/testthat/test-utils.R +++ b/tests/testthat/test-utils.R @@ -1,11 +1,3 @@ -test_that(".assert_is_pkg() errors informatively for non-packages", { - expect_snapshot( - .assert_is_pkg(tempdir()), - error = TRUE, - transform = scrub_tempdir - ) -}) - test_that("%|0|% works", { expect_identical( character() %|0|% "foo",