Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
# Generated by roxygen2: do not edit by hand

export(generate_pkg)
export(generate_pkg_auth)
export(generate_pkg_paths)
export(generate_pkg_req_prepare)
export(generate_pkg_shared_params)
export(read_api_abbr)
export(read_api_definition)
export(read_api_title)
export(read_config)
export(read_rapid_filename)
export(read_security_data)
export(read_security_data_filename)
export(read_security_schemes)
export(use_beekeeper)
if (getRversion() < "4.3.0") importFrom("S7", "@")
importFrom(S7,class_any)
Expand Down
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# beekeeper 0.4.0.9000

* `generate_pkg_auth()`, `generate_pkg_req_prepare()`, `generate_pkg_paths()`, and `generate_pkg_shared_params()` can now be run one step at a time, with `read_security_schemes()` supporting auth generation (#101).
4 changes: 4 additions & 0 deletions R/aaa-shared_params.R
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
#' @param rapid_filename (`character(1)` or `fs_path`) The path to the R API
#' definition (rapid) file (relative to the package root).
#' @param required (`logical`) Whether each parameter is required.
#' @param save_security_data (`logical(1)`) Whether to save generated security
#' metadata to a file and record that file in the beekeeper config.
#' @param security_arg_description (`character(1)`) The argument description.
#' @param security_arg_name (`character(1)`) The argument name.
#' @param security_arg_names (`character`) Security argument names to exclude
Expand All @@ -71,6 +73,8 @@
#' @param security_scheme_type (`character(1)`) The security scheme type.
#' @param security_schemes (`rapid::class_security_schemes`) Security schemes
#' from the API definition.
#' @param security_data_filename (`character(1)` or `fs_path`) The path to the
#' saved security metadata file (relative to the package root).
#' @param tag_operations (`list`) Operations grouped under one tag.
#' @param tag_name (`character(1)`) The tag name.
#' @param tags (`character` or `list`) Tags for all operations.
Expand Down
44 changes: 0 additions & 44 deletions R/generate_pkg-prepare.R

This file was deleted.

68 changes: 61 additions & 7 deletions R/generate_pkg-setup.R
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,53 @@
#' @returns (`NULL`, invisibly) Called for setup side effects.
#' @keywords internal
.setup_r <- function(pkg_dir) {
.use_r_directory(pkg_dir)
.use_testthat(pkg_dir)
.use_httptest2(pkg_dir)
.use_nectar(pkg_dir)
.use_pkg_beekeeper(pkg_dir)
}

#' Ensure the R directory exists
#'
#' @inheritParams .shared-params
#' @returns (`NULL`, invisibly) Called for setup side effects.
#' @keywords internal
.use_r_directory <- function(pkg_dir) {
usethis::with_project(
pkg_dir,
{
usethis::use_directory("R")
withr::with_options(list(usethis.quiet = TRUE), usethis::use_testthat())
purrr::quietly(httptest2::use_httptest2)()
},
usethis::use_directory("R"),
quiet = TRUE
)
.use_package("nectar", "Imports", pkg_dir)
.use_package("beekeeper", "Suggests", pkg_dir)
invisible(NULL)
}

#' Ensure testthat is configured
#'
#' @inheritParams .shared-params
#' @returns (`NULL`, invisibly) Called for setup side effects.
#' @keywords internal
.use_testthat <- function(pkg_dir) {
usethis::with_project(
pkg_dir,
withr::with_options(list(usethis.quiet = TRUE), usethis::use_testthat()),
quiet = TRUE
)
invisible(NULL)
}

#' Ensure httptest2 is configured
#'
#' @inheritParams .shared-params
#' @returns (`NULL`, invisibly) Called for setup side effects.
#' @keywords internal
.use_httptest2 <- function(pkg_dir) {
usethis::with_project(
pkg_dir,
purrr::quietly(httptest2::use_httptest2)(),
quiet = TRUE
)
invisible(NULL)
}

#' Add a package dependency to the DESCRIPTION file
Expand All @@ -66,6 +102,24 @@
invisible(pkg)
}

#' Add nectar to imports
#'
#' @inheritParams .shared-params
#' @returns (`character(1)`, invisibly) The package name.
#' @keywords internal
.use_nectar <- function(pkg_dir = ".") {
.use_package("nectar", "Imports", pkg_dir)
}

#' Add beekeeper to suggests
#'
#' @inheritParams .shared-params
#' @returns (`character(1)`, invisibly) The package name.
#' @keywords internal
.use_pkg_beekeeper <- function(pkg_dir = ".") {
.use_package("beekeeper", "Suggests", pkg_dir)
}

#' Add stbl to dependencies if needed
#'
#' @inheritParams .shared-params
Expand Down
15 changes: 0 additions & 15 deletions R/generate_pkg-shared.R

This file was deleted.

52 changes: 24 additions & 28 deletions R/generate_pkg.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,41 +22,37 @@ generate_pkg <- function(
# if not, letting them know that this can be destructive. Skip this check in
# tests.
.assert_is_pkg(pkg_dir)
api_abbr <- stbl::stabilize_character_scalar(api_abbr)
api_title <- stbl::stabilize_character_scalar(api_title)
config <- list(api_abbr = api_abbr, api_title = api_title)
security_data <- .generate_security(
api_abbr,
api_definition@components@security_schemes
api_abbr <- stbl::stabilize_chr_scalar(api_abbr)
api_title <- stbl::stabilize_chr_scalar(api_title)
save_security_data <- fs::file_exists(fs::path(pkg_dir, config_filename))
security_data <- generate_pkg_auth(
api_abbr = api_abbr,
security_schemes = api_definition@components@security_schemes,
save_security_data = save_security_data,
config_filename = config_filename,
pkg_dir = pkg_dir
)
security_arg_names <- security_data$security_arg_names %|0|% character()
.setup_r(pkg_dir)
.maybe_use_stbl(pkg_dir, api_definition@paths, security_arg_names)
touched_files <- .generate_pkg_impl(config, api_definition, security_data)
return(invisible(touched_files))
}

#' Generate package files from prepared inputs
#'
#' @inheritParams .shared-params
#' @returns (`character`, invisibly) Generated file paths.
#' @keywords internal
.generate_pkg_impl <- function(config, api_definition, security_data) {
prep_files <- .generate_prepare(config, api_definition, security_data)
pagination_data <- .generate_pagination()
path_files <- .generate_paths(
paths = api_definition@paths,
api_abbr = config$api_abbr,
shared_file_path <- generate_pkg_shared_params(
security_data = security_data,
pkg_dir = pkg_dir
)
prep_files <- generate_pkg_req_prepare(
api_abbr = api_abbr,
api_definition = api_definition,
api_title = api_title,
security_data = security_data,
pkg_dir = pkg_dir
)
path_files <- generate_pkg_paths(
api_abbr = api_abbr,
api_definition = api_definition,
security_data = security_data,
pagination_data = pagination_data,
base_url = api_definition@servers@url
pkg_dir = pkg_dir
)
shared_file_path <- .generate_shared_params(security_data)
touched_files <- c(
shared_file_path,
prep_files,
security_data$security_file_path,
pagination_data$pagination_file_path,
path_files
)
return(invisible(touched_files))
Expand Down
97 changes: 97 additions & 0 deletions R/generate_pkg-security.R → R/generate_pkg_auth.R
Original file line number Diff line number Diff line change
@@ -1,3 +1,47 @@
#' Generate authentication helpers
#'
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is now an exported function, add a full description.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a fuller roxygen description for generate_pkg_auth() in 57bebb2.

#' Generate the authentication helper file for a package under development from
#' the API security schemes stored in the OpenAPI definition. This supports
#' incremental package scaffolding when you want to review or customize auth
#' handling before generating the rest of the package files.
#'
#' When `save_security_data` is `TRUE`, the generated security metadata is saved
#' to `security_data_filename` and that filename is recorded in the beekeeper
#' config so later generation steps can reuse it.
#'
#' @inheritParams .shared-params
#' @returns (`list`) Generated security metadata.
#' @export
generate_pkg_auth <- function(
api_abbr = read_api_abbr(pkg_dir, config_filename),
security_schemes = read_security_schemes(
pkg_dir,
read_rapid_filename(pkg_dir, config_filename)
),
save_security_data = TRUE,
security_data_filename = "_beekeeper_security.yml",
config_filename = "_beekeeper.yml",
pkg_dir = "."
) {
.assert_is_pkg(pkg_dir)
api_abbr <- stbl::stabilize_chr_scalar(api_abbr)
save_security_data <- stbl::to_lgl_scalar(save_security_data)
security_data_filename <- stbl::stabilize_chr_scalar(security_data_filename)
.use_r_directory(pkg_dir)
.use_nectar(pkg_dir)
.use_pkg_beekeeper(pkg_dir)
security_data <- .generate_security(api_abbr, security_schemes)
if (save_security_data) {
.write_security_data(
.without_security_file_path(security_data),
security_data_filename,
config_filename,
pkg_dir
)
}
return(security_data)
}

#' Generate security files and metadata
#'
#' @inheritParams .shared-params
Expand All @@ -18,6 +62,59 @@
return(security_data)
}

#' Write saved security metadata and update the config
#'
#' @inheritParams .shared-params
#' @returns (`character(1)`) The saved security metadata filename.
#' @keywords internal
.write_security_data <- function(
security_data,
security_data_filename,
config_filename,
pkg_dir
) {
yaml::write_yaml(
security_data,
file = fs::path(pkg_dir, security_data_filename)
)
usethis::with_project(
pkg_dir,
usethis::use_build_ignore(security_data_filename)
)
.write_config_field(
field = "security_data_filename",
value = security_data_filename,
config_filename = config_filename,
pkg_dir = pkg_dir
)
return(security_data_filename)
}

#' Update one config field
#'
#' @inheritParams .shared-params
#' @param field (`character(1)`) The config field to write.
#' @param value (`character(1)`) The value to write.
#' @returns (`character(1)`) The written config filename.
#' @keywords internal
.write_config_field <- function(field, value, config_filename, pkg_dir) {
config <- yaml::read_yaml(fs::path(pkg_dir, config_filename))
config[[field]] <- value
yaml::write_yaml(config, file = fs::path(pkg_dir, config_filename))
memoise::forget(read_config)
usethis::with_project(pkg_dir, usethis::use_build_ignore(config_filename))
return(config_filename)
}

#' Remove generated file paths from saved security metadata
#'
#' @inheritParams .shared-params
#' @returns (`list`) Security metadata suitable for serialization.
#' @keywords internal
.without_security_file_path <- function(security_data) {
security_data[names(security_data) != "security_file_path"]
}

#' Generate a security argument signature
#'
#' @inheritParams .shared-params
Expand Down
Loading