| Title: | Mighty Components for ADaM Generation |
|---|---|
| Description: | Reusable code templates ('components') for the 'mighty' framework, used to generate Analysis Data Model (ADaM) programs. Components are 'Mustache' templates documented with 'roxygen2'-like tags. They can be retrieved from local directories, 'GitHub' or URLs, rendered with study-specific parameters, validated, evaluated, and unit tested with code coverage. |
| Authors: | Aksel Thomsen [aut, cre], Matthew Phelps [aut], Novo Nordisk A/S [cph] |
| Maintainer: | Aksel Thomsen <oath@novonordisk.com> |
| License: | Apache License (>= 2) |
| Version: | 0.1.0.9009 |
| Built: | 2026-10-16 12:47:03 UTC |
| Source: | https://github.com/NovoNordisk-OpenSource/mighty.component |
Find a component in one or more repos. Returns NULL if no repo contains
it, while get_component() raises an error. Local repo directories must
exist, otherwise an error is raised.
find_component(component, repos = NULL)find_component(component, repos = NULL)
component |
|
repos |
Where to look. One of:
Character vectors and lists are converted once with |
A mighty_component object, or NULL if no repo contains the
component.
get_component(), list_components()
path <- system.file("examples", package = "mighty.component") find_component("ady", repos = path) find_component("does_not_exist", repos = path)path <- system.file("examples", package = "mighty.component") find_component("ady", repos = path) find_component("does_not_exist", repos = path)
get_component(): Find a component. Raises an error if it is not found.
get_rendered_component(): Find a component and render it with
params.
get_component(component, repos = NULL) get_rendered_component(component, params = list(), repos = NULL)get_component(component, repos = NULL) get_rendered_component(component, params = list(), repos = NULL)
component |
|
repos |
Where to look. One of:
Character vectors and lists are converted once with |
params |
named |
Components are .mustache or .R files. Both use the tags described in
mighty_component.
.mustache files are Mustache templates.
.R files are plain R components. They cannot have @param tags or
Mustache placeholders.
get_component(): A mighty_component object.
get_rendered_component(): A mighty_component_rendered object.
find_component(), mighty_component,
mighty_component_rendered
path <- system.file("examples", "ady.mustache", package = "mighty.component") get_component(path) get_rendered_component( component = path, params = list(domain = "ADAE", variable = "ASTDY", date = "ASTDT") ) # Find by name in a repo repo <- system.file("examples", package = "mighty.component") get_component("ady", repos = repo)path <- system.file("examples", "ady.mustache", package = "mighty.component") get_component(path) get_rendered_component( component = path, params = list(domain = "ADAE", variable = "ASTDY", date = "ASTDT") ) # Find by name in a repo repo <- system.file("examples", package = "mighty.component") get_component("ady", repos = repo)
Retrieve and render a component as a mighty_component_test object, for unit tests with code coverage. See mighty_component_test for the workflow.
Requires the callr and covr packages.
get_test_component( component, params = list(), repos = NULL, check_coverage = TRUE, teardown_env = parent.frame() )get_test_component( component, params = list(), repos = NULL, check_coverage = TRUE, teardown_env = parent.frame() )
component |
|
params |
named |
repos |
Where to look. One of:
Character vectors and lists are converted once with |
check_coverage |
|
teardown_env |
Environment that controls when the coverage check
runs. Defaults to the calling environment, e.g. the |
A mighty_component_test object.
get_rendered_component(), mighty_component_test
path <- system.file("examples", "ady.mustache", package = "mighty.component") x <- get_test_component( component = path, params = list(domain = "adae", variable = "ASTDY", date = "ASTDT"), check_coverage = FALSE ) adae <- data.frame( TRTSDT = as.Date("2024-01-01"), ASTDT = as.Date(c("2024-01-01", "2024-01-10")) ) x$assign("adae", adae)$eval() x$get("adae") x$percent_coverage x$close()path <- system.file("examples", "ady.mustache", package = "mighty.component") x <- get_test_component( component = path, params = list(domain = "adae", variable = "ASTDY", date = "ASTDT"), check_coverage = FALSE ) adae <- data.frame( TRTSDT = as.Date("2024-01-01"), ASTDT = as.Date(c("2024-01-01", "2024-01-10")) ) x$assign("adae", adae)$eval() x$get("adae") x$percent_coverage x$close()
List the components in one or more repos. See
mighty_repo() for the component layout. Files starting with test- are
not listed.
list_components(repos, as = c("character", "list", "tibble"))list_components(repos, as = c("character", "list", "tibble"))
repos |
Where to look. One of:
Character vectors and lists are converted once with |
as |
Format to list the components in:
When a component exists in several repos, the metadata is taken from the
first repo, as in |
Depending on as:
"character": character vector of unique component names.
"list": list with one element per component, each a named list with
id, title, description, type, origin, method, params,
depends, outputs and code.
"tibble": tibble with one row per component and the same columns.
get_component(), find_component()
path <- system.file("examples", package = "mighty.component") list_components(path) list_components(path, as = "list") |> str(max.level = 2)path <- system.file("examples", package = "mighty.component") list_components(path) list_components(path, as = "list") |> str(max.level = 2)
R6 class for a component.
A component is a code template. Its code takes an input data set and returns a modified version with new or changed columns or rows. Components are documented with roxygen-like tags.
Use get_component() to create a component from a file or repo.
A template starts with tags in roxygen comments (#'). All lines below the
@code tag are the R code.
Templates use Mustache
placeholders. $render() fills them in with whisker::whisker.render().
{{{name}}} inserts the value of parameter name. Always use triple
braces. Double braces ({{name}}) HTML-escape the value, e.g. a<b
becomes a<b.
{{#name}}...{{/name}} repeats the enclosed text for each element of
the vector name. Use {{{.}}} to insert the current element.
A tag continues until the next tag. Required tags must appear exactly once.
| Tag | Required | Description | Example |
@title |
Yes | Title of the component. | @title Double a column |
@description |
Yes | Description of the component. | @description Creates a new column. |
@param |
No | Name, then description. One per placeholder. | @param domain `character` Name of the domain |
@type |
Yes | Component type. See Types below. | @type column |
@origin |
Yes | CDISC origin. See allowed values below. | @origin Derived |
@method |
Yes | Free-text method description for define.xml. | @method Two times the input column |
@depends |
No | Input domain, then column. Repeat for each. | @depends {{{domain}}} USUBJID |
@outputs |
No | Column created. Repeat for each. | @outputs {{{output}}} |
@code |
Yes | Last tag. All lines below are the code. | @code
|
@origin must be one of
Assigned, Collected, Derived, Not Available, Other, Predecessor, Protocol.
@depends is split at the first space into domain and column. Do not use
spaces inside its placeholders, e.g. use {{{domain}}}, not
{{{ domain }}}.
column: Adds or modifies columns. The row count is unchanged.
row: Adds, removes or modifies rows.
parameter: Derives a new PARAMCD (BDS parameter).
internal: Helper step with no define.xml output.
The input data set is {{{domain}}}.
The code assigns the result back to {{{domain}}}.
Every placeholder is declared with @param.
Functions are called with explicit namespaces, e.g. dplyr::mutate().
Joins specify by. This is enforced when rendering.
When a component is rendered, the code is parsed and must be valid R.
Joins from dplyr, tidylog and dbplyr without a by argument raise an
error. Column existence is not checked.
This template creates a new column output as two times the existing
column input:
#' @title Double a column
#' @description
#' Creates a new column as two times an existing column.
#'
#' @param domain `character` Name of the domain
#' @param output `character` Name of the new column
#' @param input `character` Name of the existing column
#' @type column
#' @origin Derived
#' @method Two times the input column
#' @depends {{{domain}}} {{{input}}}
#' @outputs {{{output}}}
#' @code
{{{domain}}} <- {{{domain}}} |>
dplyr::mutate(
{{{output}}} = 2 * {{{input}}}
)
Rendered with domain = "ADSL", output = "A" and input = "B", the
code ($code) is:
ADSL <- ADSL |>
dplyr::mutate(
A = 2 * B
)
The tags are rendered too, e.g. $depends has domain ADSL and
column B.
idcharacter(1) Component name without file extension.
titlecharacter(1) Title of the component.
descriptioncharacter(1) Description of the component.
codecharacter Lines below @code.
templatecharacter Full template.
typecharacter(1) Component type. One of
column, row, parameter, internal.
origincharacter(1) CDISC origin. One of
Assigned, Collected, Derived, Not Available, Other, Predecessor, Protocol.
methodcharacter(1) Method description for define.xml.
dependsdata.frame with columns domain and column.
outputscharacter Columns created by the component.
paramsdata.frame with columns name and description.
mighty_component$new()Create a component from a template.
mighty_component$new(template, id)
templatecharacter Template, one element per line. See
Details.
idcharacter(1) Component ID.
mighty_component$print()Print the component.
mighty_component$print()
(invisible) self
mighty_component$render()Render the component with whisker::whisker.render().
mighty_component$render(...)
...Named parameters used to render the template. Supply one
for each @param tag and no others.
For @type row components, domain can be a subset marker:
".mighty_subset(<domain>, '<subset>')", where <subset> is an R
expression in a string, e.g.
domain = ".mighty_subset(ADLB, 'PARAMCD == \"ALB\"')". The code then
only processes the rows where <subset> is TRUE. Other rows are kept
unchanged. The marker is not allowed for other
parameters or types.
Object of class mighty_component_rendered
mighty_component$document()Create documentation in markdown format. Requires the knitr package.
mighty_component$document()
(invisible) character(1) Markdown documentation.
Also printed to the console.
mighty_component$clone()The objects of this class are cloneable with this method.
mighty_component$clone(deep = FALSE)
deepWhether to make a deep clone.
get_component(), mighty_component_rendered,
vignette("mighty-component")
path <- system.file("examples", "ady.mustache", package = "mighty.component") x <- mighty_component$new(template = readLines(path), id = "ady") x x$params x$depends x$render(domain = "ADAE", variable = "ASTDY", date = "ASTDT") x$document()path <- system.file("examples", "ady.mustache", package = "mighty.component") x <- mighty_component$new(template = readLines(path), id = "ady") x x$params x$depends x$render(domain = "ADAE", variable = "ASTDY", date = "ASTDT") x$document()
R6 class for a rendered component, created by
mighty_component$render() or get_rendered_component().
A rendered component can be:
Streamed into an R script with $stream().
Evaluated in an environment with $eval().
mighty_component -> mighty_component_rendered
mighty_component_rendered$new()Create a rendered component from a rendered template. The code is validated. See the Validation section in mighty_component.
mighty_component_rendered$new(template, id)
templatecharacter Rendered template, one element per line.
idcharacter(1) Component ID.
mighty_component_rendered$print()Print the rendered component, including its code.
mighty_component_rendered$print()
(invisible) self
mighty_component_rendered$stream()Write the code to an R script. The code is appended if the file exists.
mighty_component_rendered$stream(path)
pathcharacter(1) Path to the R script.
(invisible) self
mighty_component_rendered$eval()Evaluate the code.
mighty_component_rendered$eval(envir = parent.frame())
envirEnvironment to evaluate the code in. Defaults to the calling environment.
Value of the last evaluated expression of the code.
mighty_component_rendered$clone()The objects of this class are cloneable with this method.
mighty_component_rendered$clone(deep = FALSE)
deepWhether to make a deep clone.
get_rendered_component(), mighty_component
path <- system.file("examples", "ady.mustache", package = "mighty.component") x <- get_component(path)$render( domain = "adae", variable = "ASTDY", date = "ASTDT" ) x$code # Write the code to an R script script <- tempfile(fileext = ".R") x$stream(script) readLines(script) unlink(script) # Evaluate the code in a new environment env <- new.env() env$adae <- data.frame( TRTSDT = as.Date("2024-01-01"), ASTDT = as.Date(c("2024-01-01", "2024-01-10")) ) x$eval(envir = env) env$adaepath <- system.file("examples", "ady.mustache", package = "mighty.component") x <- get_component(path)$render( domain = "adae", variable = "ASTDY", date = "ASTDT" ) x$code # Write the code to an R script script <- tempfile(fileext = ".R") x$stream(script) readLines(script) unlink(script) # Evaluate the code in a new environment env <- new.env() env$adae <- data.frame( TRTSDT = as.Date("2024-01-01"), ASTDT = as.Date(c("2024-01-01", "2024-01-10")) ) x$eval(envir = env) env$adae
R6 class for unit testing a component with code coverage tracking. The code runs in a separate R session, and the lines executed are counted.
Use get_test_component() to create a test component. The workflow is:
Create the test component with get_test_component().
Assign input data with $assign().
Run the code and update coverage with $eval().
Retrieve results with $get().
Test the results with testthat expect_*() functions.
Close the session with $close().
By default, get_test_component() checks coverage with
$check_coverage() when the test ends. Coverage is kept in the current
R session, so it can still be checked after $close().
The code runs inside a function, with <- replaced by <<-, so
assignments are made in the session's global environment.
mighty_component -> mighty_component_rendered -> mighty_component_test
percent_coveragenumeric(1) Percentage of lines covered
(0-100).
line_coveragedata.frame with columns line and value
(number of times the line has run).
mighty_component_test$new()Create a test component from a rendered template. Starts a new R session. Requires the callr and covr packages.
mighty_component_test$new(template, id)
templatecharacter Rendered template, one element per line.
idcharacter(1) Component ID.
mighty_component_test$print()Print the test component with its code coverage.
mighty_component_test$print()
(invisible) self
mighty_component_test$assign()Assign a variable in the test session.
mighty_component_test$assign(x, value)
xcharacter(1) Variable name.
valueValue to assign.
(invisible) self
mighty_component_test$get()Get a variable from the test session.
mighty_component_test$get(x)
xcharacter(1) Variable name.
Value of the variable.
mighty_component_test$ls()List the variables in the test session.
mighty_component_test$ls()
character Variable names.
mighty_component_test$eval()Run the code in the test session and update the coverage.
mighty_component_test$eval()
(invisible) self
mighty_component_test$check_coverage()Check that every line of the code has run at least once. Raises an error otherwise.
mighty_component_test$check_coverage()
(invisible) self
mighty_component_test$close()Close the test session. Called automatically when the object is garbage collected.
mighty_component_test$close()
(invisible) self
mighty_component_test$clone()The objects of this class are cloneable with this method.
mighty_component_test$clone(deep = FALSE)
deepWhether to make a deep clone.
path <- system.file("examples", "ady.mustache", package = "mighty.component") x <- get_test_component( component = path, params = list(domain = "adae", variable = "ADY", date = "ADT"), check_coverage = FALSE ) x$percent_coverage x$assign( "adae", data.frame(TRTSDT = as.Date("2024-01-01"), ADT = as.Date("2024-01-05")) ) x$eval() x$ls() x$get("adae")$ADY x$percent_coverage x$check_coverage() x$close()path <- system.file("examples", "ady.mustache", package = "mighty.component") x <- get_test_component( component = path, params = list(domain = "adae", variable = "ADY", date = "ADT"), check_coverage = FALSE ) x$percent_coverage x$assign( "adae", data.frame(TRTSDT = as.Date("2024-01-01"), ADT = as.Date("2024-01-05")) ) x$eval() x$ls() x$get("adae")$ADY x$percent_coverage x$check_coverage() x$close()
mighty_repo(): Create a component repo from a spec.
mighty_repo_class: Abstract parent class of all component repos. It has
no properties and cannot be created directly.
Specs have the form type::path. Supported types:
local: A local directory, e.g. local::inst/examples.
A spec without a prefix is treated as local.
github: A GitHub repository, e.g. github::owner/repo/subdir@ref.
See mighty_repo_github().
url: Raw files under a base URL, e.g.
url::https://example.com/components. See mighty_repo_url().
All repo types share one layout. A component name is the file
<name>.R or <name>.mustache, either directly in the repo or in a
directory named after the component (<name>/<name>.R). A name with an
extension only matches that file.
mighty_repo(spec)mighty_repo(spec)
spec |
|
mighty_repo(): An object inheriting from mighty_repo_class.
mighty_repo_local(), mighty_repo_github(), mighty_repo_url(),
mighty_repos()
path <- system.file("examples", package = "mighty.component") mighty_repo(path) mighty_repo(paste0("local::", path))path <- system.file("examples", package = "mighty.component") mighty_repo(path) mighty_repo(paste0("local::", path))
A component repo hosted on GitHub. When the object is created, ref is
resolved to a commit SHA and the repository tarball for that commit is
downloaded and extracted to a temporary directory. Resolved SHAs are cached
per ref and tarballs per commit for the session, so all lookups afterwards
are local. Restart the session to pick up new commits on a branch.
spec is a remotes-style repository reference: owner/repo,
owner/repo/subdir, owner/repo@ref or a combination.
Transient API errors (HTTP 5xx and network failures) are retried. The
number of attempts is set by the max_tries option. See
mighty.component-options.
Requires the gh and remotes packages. Private repositories need a GitHub
token. gh reads it from the GITHUB_PAT or GITHUB_TOKEN environment
variable, or the Git credential store. See gh::gh_token().
mighty_repo_github(spec)mighty_repo_github(spec)
spec |
|
A mighty_repo_github object. It inherits from
mighty_repo_local(), with path set to the downloaded repository or
its subdir.
repo <- mighty_repo_github( spec = "NovoNordisk-OpenSource/mighty.standards/components@main" ) find_component(component = "dummy", repos = repo)repo <- mighty_repo_github( spec = "NovoNordisk-OpenSource/mighty.standards/components@main" ) find_component(component = "dummy", repos = repo)
A component repo in a local directory. See mighty_repo() for the
component layout. An error is raised if more than one file matches a
component.
mighty_repo_local(path)mighty_repo_local(path)
path |
|
A mighty_repo_local object.
path <- system.file("examples", package = "mighty.component") mighty_repo_local(path = path)path <- system.file("examples", package = "mighty.component") mighty_repo_local(path = path)
A component repo served as raw files under a base URL. Requires httr2 (>= 1.2.2).
See mighty_repo() for the component layout. .mustache is tried before
.R, and <name>/ before files directly under url. The first found is
used. Status 404 and 410 count as not found; other errors are raised.
name is percent-encoded, and names containing / are not found.
Responses are not cached.
Listing components (see list_components()) requires an HTML directory
index at <url>/, and at <url>/<dir>/ for nested components, e.g. Apache
or nginx autoindex, or python -m http.server. Listing aborts if an index
is unavailable or not HTML.
Transient errors (see httr2::req_retry()) and network failures are
retried. The number of attempts is set by the max_tries option, and
each attempt is limited by the timeout option (see
mighty.component-options).
mighty_repo_url(url)mighty_repo_url(url)
url |
|
A mighty_repo_url object.
repo <- mighty_repo_url( url = paste0( "https://raw.githubusercontent.com/", "NovoNordisk-OpenSource/mighty.standards/main/components" ) ) format(repo) find_component(component = "dummy", repos = repo)repo <- mighty_repo_url( url = paste0( "https://raw.githubusercontent.com/", "NovoNordisk-OpenSource/mighty.standards/main/components" ) ) format(repo) find_component(component = "dummy", repos = repo)
An ordered collection of component repos. Lookups search the repos in order, and the first match wins.
Each element of repos is either a repo spec, passed to mighty_repo(),
or an object inheriting from mighty_repo_class. Repos are created once
when the collection is created.
mighty_repos(repos = character(0))mighty_repos(repos = character(0))
repos |
|
A mighty_repos object: a list of repos.
find_component(), list_components()
path <- system.file("examples", package = "mighty.component") repos <- mighty_repos(repos = c(path, paste0("local::", path))) repos find_component(component = "ady", repos = repos)path <- system.file("examples", package = "mighty.component") repos <- mighty_repos(repos = c(path, paste0("local::", path))) repos find_component(component = "ady", repos = repos)
Verbosity level for functions in mighty.component. See zephyr::verbosity_level for details.
Default: NA_character_
Option: mighty.component.verbosity_level
Environment: R_MIGHTY.COMPONENT_VERBOSITY_LEVEL
Maximum number of attempts for GitHub and URL requests. See mighty_repo_github() and mighty_repo_url() for which errors are retried.
Default: 3L
Option: mighty.component.max_tries
Environment: R_MIGHTY.COMPONENT_MAX_TRIES
Maximum number of seconds per URL request attempt. See mighty_repo_url().
Default: 5
Option: mighty.component.timeout
Environment: R_MIGHTY.COMPONENT_TIMEOUT