Skip to contents

sbom_shiny() describes a Shiny app folder: the app is the root component, an application, the R packages it needs come from the strongest source in the folder, and the JavaScript and CSS libraries the app ships are recorded under it. It runs no code from the app unless you ask for evaluate_ui = TRUE, and it makes no network requests, except that, with Nix installed, a default.nix is read by running nix-instantiate (see sbom_nix()), which may download nixpkgs, and that snapshot and advisories = TRUE, passed through ..., look up a CRAN snapshot and download OSV's advisory data.

Usage

sbom_shiny(path = ".", evaluate_ui = FALSE, ...)

Arguments

path

A Shiny app folder.

evaluate_ui

Whether to run the app's code to find the html dependencies (JavaScript and CSS) its UI holds. FALSE by default.

evaluate_ui = TRUE runs the app's code in a separate R process, which is stopped after 60 seconds. It works for app.R and ui.R apps. For an app.R app the whole of app.R runs, not only its UI code; for a ui.R app, ui.R runs. global.R and the app's R/ folder are not sourced, so an app that relies on them fails, with the issue below. The process starts R with --vanilla and inherits this session's environment variables, except that R_LIBS is set to the library given by lib, or else .libPaths(); R also adds the user and site libraries after it. It needs the htmltools package in those libraries. What it finds are observed components, nested under the R package that ships each one. A dependency whose name, version or package sbom does not accept is left out, and one issue counts them. If the UI cannot be evaluated, an issue says so and the SBOM keeps the static result.

It finds only the dependencies the UI holds when it is built, and misses any that renderUI() or other server code inserts later.

...

The named arguments of sbom().

Value

An <sbom> object. See sbom_components() to read it.

Details

The layouts it recognizes, checked in this order:

  1. rhino: the folder has rhino.yml. Its static files are in app/static.

  2. golem: a DESCRIPTION with a Package field, and either inst/golem-config.yml or both R/app_ui.R and R/app_server.R. The root is the app, named and versioned by its DESCRIPTION, which also gives its license and maintainer whatever source the packages come from. Its static files are in inst/app/www.

  3. app.R: the folder has an app.R. Its static files are in www.

  4. ui-server: the folder has both ui.R and server.R. Its static files are in www.

The R packages come from the strongest source, as for sbom(): renv.lock, then a Posit Connect manifest.json, then default.nix, then a package DESCRIPTION (a golem app's declared Imports are stronger than a code scan), then a scan of the code. Every other source present cross-checks it. When the folder holds a Posit Connect manifest, a note says the app was deployed there.

The libraries in the static folder are found by the header comments of their files, as for the JavaScript in a package, with the same bounds: six levels, no symlinked folders, a fixed number of files. They are inferred components under the root. A rhino app's npm dependencies are not read, and an issue says so when the app has a package.json or package-lock.json.

Examples

app <- file.path(tempdir(), "app")
dir.create(app)
writeLines("shiny::shinyApp(shiny::fluidPage(), function(input, output) {})",
  file.path(app, "app.R"))
sbom_shiny(app, system = FALSE, lib = character())
#> <sbom> app
#> Components: 3
#> Relationships: 1
#> Issues: 3 (see sbom_issues())
#> Advisories: not requested.