From 41f5e5ff29c6a936bf595c449b10a4a6e401c9e3 Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Fri, 2 Jan 2026 21:39:30 -0700 Subject: [PATCH 01/22] update access contstraints API call to be compatible with DataStore v8 API --- R/datastore_interactions.R | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/R/datastore_interactions.R b/R/datastore_interactions.R index 21b3763..5144793 100644 --- a/R/datastore_interactions.R +++ b/R/datastore_interactions.R @@ -383,12 +383,11 @@ create_datastore_script <- function(owner, mylist <- list(internal = FALSE, filesInternal = FALSE, FileRestricted = FALSE, - sensitivity = "Not Sensitive", - distribution = "No Restriction", - quality = "Operational", - additionalUserDefined = "", - noDataMgrEdit = FALSE, - linksRestricted = FALSE) + additionalConstraints = "none", + legalAuthority = list("none"), + otherAuthority = "No Restriction", + justification = "none", + contactEmail = "none") bdy <- jsonlite::toJSON(mylist, pretty = TRUE, auto_unbox = TRUE) if (dev == TRUE) { @@ -399,7 +398,7 @@ create_datastore_script <- function(owner, ds_ref, "/AccessConstraints") } - #create the draft reference: + #set reference to public: req <- httr::PUT(post_url, httr::authenticate(":", "", "ntlm"), httr::add_headers('Content-Type' = 'application/json'), From a593cf5d8da57b92a1762d7a8659f8abe198a59f Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Mon, 5 Jan 2026 08:34:13 -0700 Subject: [PATCH 02/22] fix screenprint formatting to make it easier to read --- R/datastore_interactions.R | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/R/datastore_interactions.R b/R/datastore_interactions.R index 5144793..4922387 100644 --- a/R/datastore_interactions.R +++ b/R/datastore_interactions.R @@ -131,9 +131,9 @@ create_datastore_script <- function(owner, httr::write_disk(download_file_path, overwrite = TRUE)))))) if (force == FALSE) { - cat("Writing: ", + cat("Downloading and Writing: ", crayon::blue$bold(download_file_path), - ".\n", sep = "") + ".\n\n", sep = "") } #generate json body for rest api call to create the reference: @@ -179,7 +179,7 @@ create_datastore_script <- function(owner, } #inform user a new reference has been generated: if (force == FALSE) { - cat("A draft reference has been created on DataStore.\n") + cat("A draft reference has been created on DataStore.\n\n") } #use reference id to put the file: @@ -271,7 +271,7 @@ create_datastore_script <- function(owner, if (force == FALSE) { cat("Your file, ", crayon::blue$bold(file_name), ", has been uploaded to:\n", sep = "") - cat(ds_resource_url, "\n", sep = "") + cat(ds_resource_url, "\n\n", sep = "") } #add a web link: #release url: @@ -312,7 +312,7 @@ create_datastore_script <- function(owner, } if (force == FALSE) { cat("The following web link has been added to your Script Reference: \n") - cat(weblink, "\n", sep = "") + cat(weblink, "\n\n", sep = "") } #add keywords @@ -367,6 +367,7 @@ create_datastore_script <- function(owner, if (force == FALSE) { cat("Your DataStore Reference now has the following keywords:\n") print(rjson_kw) + cat("\n") } } @@ -424,8 +425,7 @@ create_datastore_script <- function(owner, if (force == FALSE) { cat("Your reference has been set to unrestricted with no sensitivity.\n") - cat("Your reference has been set to \"Operational\" quality.\n") - cat("Unless you have a documented reason to do so, please leave the reference public.\n") + cat("Unless you have a documented reason to do so, please leave the reference public.\n\n") cat("Your draft reference can be accessed at:\n") From 532c4e2697f810d29cc617702305c72055dbea72 Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Mon, 5 Jan 2026 08:44:18 -0700 Subject: [PATCH 03/22] make DataStore refernce link clickable --- R/datastore_interactions.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/datastore_interactions.R b/R/datastore_interactions.R index 4922387..1a2358d 100644 --- a/R/datastore_interactions.R +++ b/R/datastore_interactions.R @@ -428,8 +428,8 @@ create_datastore_script <- function(owner, cat("Unless you have a documented reason to do so, please leave the reference public.\n\n") cat("Your draft reference can be accessed at:\n") - - cat(crayon::blue$bold(ds_ref_url)) + ds_ref_url <- utils::URLencode(ds_ref_url) + cli::cli_text("{.url {ds_ref_url}}") } invisible(ds_ref_url) From 323a3e412e5ec3012d148302d9a6e2a65222ccee Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Mon, 5 Jan 2026 08:50:04 -0700 Subject: [PATCH 04/22] fixed bug in create_datastore_reference introduced via new API version; some text formatting improvements --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index 9974084..e4a4993 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,7 @@ # QCkit v1.2.1 +## 2025-01-05 + * Fixed bug in create_datastore_script that occurred when the way the DataStore API handled access constraints changed between V7 and V8. Also improved formatting of screen print and make the DataStore reference link clickable. + ## 2025-12-31 * Updated DataStore APIs to hit v8 API instead of now deprecated v7 API endponts From bc8327a5333eafd0a75fb0b6052b8f59a7b1f39f Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Mon, 5 Jan 2026 08:53:51 -0700 Subject: [PATCH 05/22] updates via pkgdown::buid_site_github_pages --- docs/authors.html | 4 ++-- docs/news/index.html | 8 ++++++-- docs/pkgdown.yml | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/authors.html b/docs/authors.html index 2da1b0e..626a160 100644 --- a/docs/authors.html +++ b/docs/authors.html @@ -74,14 +74,14 @@

Authors

Citation

Source: DESCRIPTION

-

Baker R, Patterson J, DeVivo J, Quevedo I, Wright S (2025). +

Baker R, Patterson J, DeVivo J, Quevedo I, Wright S (2026). QCkit: NPS Inventory and Monitoring Quality Control Toolkit. R package version 1.2.1, https://nationalparkservice.github.io/QCkit/, https://github.com/nationalparkservice/QCkit/.

@Manual{,
   title = {QCkit: NPS Inventory and Monitoring Quality Control Toolkit},
   author = {Robert Baker and Judd Patterson and Joe DeVivo and Issac Quevedo and Sarah Wright},
-  year = {2025},
+  year = {2026},
   note = {R package version 1.2.1, https://nationalparkservice.github.io/QCkit/},
   url = {https://github.com/nationalparkservice/QCkit/},
 }
diff --git a/docs/news/index.html b/docs/news/index.html index be53877..4fc3193 100644 --- a/docs/news/index.html +++ b/docs/news/index.html @@ -41,11 +41,15 @@

Changelog

QCkit v1.2.1

-

2025-12-31

+

2025-01-05

+
  • Fixed bug in create_datastore_script that occurred when the way the DataStore API handled access constraints changed between V7 and V8. Also improved formatting of screen print and make the DataStore reference link clickable.
  • +
+
+

2025-12-31

  • Updated DataStore APIs to hit v8 API instead of now deprecated v7 API endponts
-

2025-05-22

+

2025-05-22

  • fix minor bug in create_datastore_script
diff --git a/docs/pkgdown.yml b/docs/pkgdown.yml index f6c14af..55480de 100644 --- a/docs/pkgdown.yml +++ b/docs/pkgdown.yml @@ -5,7 +5,7 @@ articles: articles/DRR_Purpose_and_Scope: DRR_Purpose_and_Scope.html articles/Starting-a-DRR: Starting-a-DRR.html articles/Using-the-DRR-Template: Using-the-DRR-Template.html -last_built: 2025-12-31T17:55Z +last_built: 2026-01-05T15:50Z urls: reference: https://nationalparkservice.github.io/QCkit/reference article: https://nationalparkservice.github.io/QCkit/articles From 8a6e60fb2f3ac2e350dcb1d39865b0eda716de9b Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Tue, 6 Jan 2026 12:55:56 -0700 Subject: [PATCH 06/22] Add ability to set Origination flag in DataStore via API PATCH --- R/datastore_interactions.R | 46 +++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/R/datastore_interactions.R b/R/datastore_interactions.R index 1a2358d..5f88569 100644 --- a/R/datastore_interactions.R +++ b/R/datastore_interactions.R @@ -1,12 +1,18 @@ #' Turn a GitHub release into a DataStore Script Reference #' -#' @description Given a GitHub owner ("nationalparkservice") and public repo ("EMLeditor"), the function uses the GitHub API to access the latest release version on GitHub and generate a corresponding draft Script reference on DataStore. +#' @description Given a GitHub owner ("nationalparkservice") and public repo ("EMLeditor"), the function uses the GitHub API to access the latest release version on GitHub and generate a corresponding draft public Script reference on DataStore. #' #' WARNING: if you are not an author of the repo on GitHub, you should probably NOT be the one adding it to DataStore unless you have very good reason. If you want to cite a GitHub release/repo and need a DOI, contact the repo maintainer and suggest they use this function to put it on DataStore for you. #' -#' It searches DataStore for references with a similar title (where the title is repo + release tag). If `force = FALSE` and there are similarly titled references, the function will return a list of them and ask if the user really wants a new DataStore reference generated. Assuming yes (or if there are no existing DataStore references with a similar title or `force = TRUE`), the function will: 1) download the .zip of the latest GitHub release for the repo, 2) initiate a draft reference on DataStore, 3) give the draft reference a title (repo + release tag), 4) upload the .zip from GitHub 5) add a web link to the release on GitHub. +#' The function searches DataStore for references with a similar title (where the title is repo + release tag). If `force = FALSE` and there are similarly titled references, the function will return a list of them and ask if the user really wants a new DataStore reference generated. Assuming yes (or if there are no existing DataStore references with a similar title or if `force = TRUE`), the function will: +#' 1) download the .zip of the latest GitHub release for the repo, +#' 2) initiate a draft reference on DataStore, +#' 3) give the draft reference a title (repo + release tag), +#' 4) upload the .zip from GitHub +#' 5) add a web link to the release on GitHub. +#' 6) add the items listed under GitHub repo "Topics" as keywords to the DataStore Script reference #' -#' `create_datastore_script()` will also access the keywords from your GitHub repo ("Topics") and add them to the draft references as keywords. It will automatically set your reference and all the files and links to public, allow data managers to edit the reference, and set the quality to "Operational". Unless you have good reason backed by a policy that specifically includes information from your release, please do not change these settings (and perhaps reconsider using public github repositories). +#' `create_datastore_script()` will also access the keywords from your GitHub repo ("Topics") and add them to the draft references as keywords. It will automatically set your reference and all the files and links to public, allow data managers to edit the reference. #' #' The user will still need to go access the draft Script reference on DataStore to fill in the remaining fields (which are not accessible via API and so cannot be automated through this function) and activate the reference (thereby generating and registering a citeable DOI). #' @@ -17,6 +23,7 @@ #' @param path String. The location where the release .zip from GitHub should be downloaded to (and uploaded from). Defaults to the working directory of the R Project (i.e. `here::here()`). #' @param force Logical. Defaults to FALSE. In the default status the function has a number of interactive components, such as searching DataStore for similarly titled References and asking if a new Reference is really what the user wants. When set to TRUE, all interactive components are turned off and the function will proceed unless it hits an error. Setting force = TRUE may be useful for scripting purposes. #' @param dev Logical. Defaults to FALSE. In the default status, the function generates and populates a new draft Script reference on the DataStore production server. If set to TRUE, the draft Script reference will be generated and populated on the DataStore development server. Setting dev = TRUE may be useful for testing the function without generating excessive references on the DataStore production server. +#' @param for_or_by_NPS Logical. Was the code, script, or software created either for or by NPS? Defaults to TRUE. #' @param chunk_size_mb The "chunk" size to break the file into for upload. If your network is slow and your uploads are failing, try decreasing this number (e.g. 0.5 or 0.25). #' @param retry How many times to retry uploading a file chunk if it fails on the first try. #' @@ -33,6 +40,7 @@ create_datastore_script <- function(owner, path = here::here(), force = FALSE, dev = FALSE, + for_or_by_NPS = TRUE, chunk_size_mb = 1, retry = 1) { gh_url <- paste0("https://api.github.com/repos/", @@ -409,9 +417,35 @@ create_datastore_script <- function(owner, if (!status_code == 200) { stop("ERROR: DataStore connection failed. Are you logged in to the VPN?\n") } - #get newly created reference id: - json <- httr::content(req, "text") - rjson <- jsonlite::fromJSON(json) + + #set bibliography patch URL + if (dev == TRUE) { + patch_url <- paste0(.QC_ds_dev_api(), + "Reference/", + ds_ref, + "/Bibliography") + } else { + patch_url <- paste0(.QC_ds_secure_api(), + "Reference/", + ds_ref, + "/Bibliography") + } + + #Set for or by NPS: + NPS_origination <- list(isAgencyOriginated = for_or_by_NPS) + bdy <- jsonlite::toJSON(NPS_origination, pretty = TRUE, auto_unbox = TRUE) + + NPS_req <- httr::PATCH(patch_url, + httr::authenticate(":", "", "ntlm"), + httr::add_headers('Content-Type' = 'application/json'), + body = bdy) + + #check status code; suggest logging in to VPN if errors occur: + status_code <- httr::stop_for_status(NPS_req)$status_code + if (!status_code == 200) { + stop("ERROR: DataStore connection failed. Are you logged in to the VPN?\n") + } + # make reference URL if (dev == TRUE) { From d869b8df5debd78ad5afe86817d0393359059dc6 Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Tue, 6 Jan 2026 12:56:12 -0700 Subject: [PATCH 07/22] add update about origination flag in create_datastore_script --- NEWS.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index e4a4993..0024216 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,9 @@ # QCkit v1.2.1 +## 2025-01-06 + * Add ability to set the Origination flag in DataStore via the `create_datastore_script` function. Defaults to TRUE. + ## 2025-01-05 - * Fixed bug in create_datastore_script that occurred when the way the DataStore API handled access constraints changed between V7 and V8. Also improved formatting of screen print and make the DataStore reference link clickable. + * Fixed bug in `create_datastore_script` that occurred when the way the DataStore API handled access constraints changed between V7 and V8. Also improved formatting of screen print and make the DataStore reference link clickable. ## 2025-12-31 * Updated DataStore APIs to hit v8 API instead of now deprecated v7 API endponts From a0dbc6f73d11b58ac16037acafffd164f12f0077 Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Tue, 6 Jan 2026 12:56:32 -0700 Subject: [PATCH 08/22] updated via devtools::document and pkgdown::build_site_github_pages --- docs/CONTRIBUTING.html | 2 +- docs/articles/Starting-a-DRR.html | 4 +- docs/index.html | 4 +- docs/news/index.html | 12 ++++-- docs/pkgdown.yml | 2 +- docs/reference/create_datastore_script.html | 48 ++++++++++++++++----- docs/reference/document_missing_values.html | 4 +- docs/reference/get_custom_flags.html | 2 +- docs/reference/get_dc_flags.html | 2 +- docs/reference/get_df_flags.html | 2 +- docs/reference/get_dp_flags.html | 2 +- docs/reference/remove_empty_tables.html | 2 +- docs/reference/replace_blanks.html | 4 +- man/create_datastore_script.Rd | 17 ++++++-- 14 files changed, 74 insertions(+), 33 deletions(-) diff --git a/docs/CONTRIBUTING.html b/docs/CONTRIBUTING.html index 2a11824..c128572 100644 --- a/docs/CONTRIBUTING.html +++ b/docs/CONTRIBUTING.html @@ -133,7 +133,7 @@

How Do I Submit a Good En

Your First Code Contribution

-

If you would like to contribute code please make the adjustments and issue a pull request. The development team will review your code prior to merging and pull request. Before issuing a pull request make sure: 1) You have added a description of any changes made to the changelog in NEWS.md 2) If you have added a function, make sure you also include unit tests that cover the function. If you have changed a function, make sure the unit tests still pass. 3) If you have added or changed a function, make sure that the package loads using devtools::load_all(). 2) You have updated any necessary documentation using devtools::document() 3) You have updated the associated web pages using pkgdown::build_site_github_pages() 4) You have checked that there are no errors or warnings when the package is built using devtools::check().

+

If you would like to contribute code please make the adjustments and issue a pull request. The development team will review your code prior to merging and pull request. Before issuing a pull request make sure: 1) You have added a description of any changes made to the changelog in NEWS.md 2) If you have added a function, make sure you also include unit tests that cover the function. If you have changed a function, make sure the unit tests still pass. 3) If you have added or changed a function, make sure that the package loads using devtools::load_all(). 2) You have updated any necessary documentation using devtools::document() 3) You have updated the associated web pages using pkgdown::build_site_github_pages() 4) You have checked that there are no errors or warnings when the package is built using devtools::check().

diff --git a/docs/articles/Starting-a-DRR.html b/docs/articles/Starting-a-DRR.html index 93f833f..f2d9fb2 100644 --- a/docs/articles/Starting-a-DRR.html +++ b/docs/articles/Starting-a-DRR.html @@ -135,11 +135,11 @@

How to Start a DRRinstall.packages("devtools")

 # Install and load QCkit via NPSdataverse:
-devtools::install_github("nationalparkservice/NPSdataverse")
+devtools::install_github("nationalparkservice/NPSdataverse")
 library(NPSdataverse)
 # Alternatively, install and load just QCkit:
-devtools::install_github("nationalparkservice/QCkit")
+devtools::install_github("nationalparkservice/QCkit")
 library(QCkit)
  1. diff --git a/docs/index.html b/docs/index.html index e4a4bba..187a588 100644 --- a/docs/index.html +++ b/docs/index.html @@ -69,12 +69,12 @@

    Installation
     # install.packages("devtools")
    -devtools::install_github("nationalparkservice/QCkit")
    +devtools::install_github("nationalparkservice/QCkit")
     library(QCkit)

    QCkit is also part of the NPSdataverse and can be installed along with the other components of NPSdataverse:

     # install.packages("devtools")
    -devtools::install_github("nationalparkservice/NPSdataverse")
    +devtools::install_github("nationalparkservice/NPSdataverse")
     library(NPSdataverse)
    diff --git a/docs/news/index.html b/docs/news/index.html index 4fc3193..59ff20c 100644 --- a/docs/news/index.html +++ b/docs/news/index.html @@ -41,15 +41,19 @@

    Changelog

    QCkit v1.2.1

    -

    2025-01-05

    -
    • Fixed bug in create_datastore_script that occurred when the way the DataStore API handled access constraints changed between V7 and V8. Also improved formatting of screen print and make the DataStore reference link clickable.
    • +

      2025-01-06

      +
      • Add ability to set the Origination flag in DataStore via the create_datastore_script function. Defaults to TRUE.
    -

    2025-12-31

    +

    2025-01-05

    +
    • Fixed bug in create_datastore_script that occurred when the way the DataStore API handled access constraints changed between V7 and V8. Also improved formatting of screen print and make the DataStore reference link clickable.
    • +
    +
    +

    2025-12-31

    • Updated DataStore APIs to hit v8 API instead of now deprecated v7 API endponts
    -

    2025-05-22

    +

    2025-05-22

    • fix minor bug in create_datastore_script
    diff --git a/docs/pkgdown.yml b/docs/pkgdown.yml index 55480de..2273b3f 100644 --- a/docs/pkgdown.yml +++ b/docs/pkgdown.yml @@ -5,7 +5,7 @@ articles: articles/DRR_Purpose_and_Scope: DRR_Purpose_and_Scope.html articles/Starting-a-DRR: Starting-a-DRR.html articles/Using-the-DRR-Template: Using-the-DRR-Template.html -last_built: 2026-01-05T15:50Z +last_built: 2026-01-06T19:53Z urls: reference: https://nationalparkservice.github.io/QCkit/reference article: https://nationalparkservice.github.io/QCkit/articles diff --git a/docs/reference/create_datastore_script.html b/docs/reference/create_datastore_script.html index 477fced..ee5ac86 100644 --- a/docs/reference/create_datastore_script.html +++ b/docs/reference/create_datastore_script.html @@ -1,13 +1,29 @@ -Turn a GitHub release into a DataStore Script Reference — create_datastore_script • QCkit Skip to contents @@ -50,10 +66,15 @@

    Turn a GitHub release into a DataStore Script Reference

    -

    Given a GitHub owner ("nationalparkservice") and public repo ("EMLeditor"), the function uses the GitHub API to access the latest release version on GitHub and generate a corresponding draft Script reference on DataStore.

    +

    Given a GitHub owner ("nationalparkservice") and public repo ("EMLeditor"), the function uses the GitHub API to access the latest release version on GitHub and generate a corresponding draft public Script reference on DataStore.

    WARNING: if you are not an author of the repo on GitHub, you should probably NOT be the one adding it to DataStore unless you have very good reason. If you want to cite a GitHub release/repo and need a DOI, contact the repo maintainer and suggest they use this function to put it on DataStore for you.

    -

    It searches DataStore for references with a similar title (where the title is repo + release tag). If force = FALSE and there are similarly titled references, the function will return a list of them and ask if the user really wants a new DataStore reference generated. Assuming yes (or if there are no existing DataStore references with a similar title or force = TRUE), the function will: 1) download the .zip of the latest GitHub release for the repo, 2) initiate a draft reference on DataStore, 3) give the draft reference a title (repo + release tag), 4) upload the .zip from GitHub 5) add a web link to the release on GitHub.

    -

    create_datastore_script() will also access the keywords from your GitHub repo ("Topics") and add them to the draft references as keywords. It will automatically set your reference and all the files and links to public, allow data managers to edit the reference, and set the quality to "Operational". Unless you have good reason backed by a policy that specifically includes information from your release, please do not change these settings (and perhaps reconsider using public github repositories).

    +

    The function searches DataStore for references with a similar title (where the title is repo + release tag). If force = FALSE and there are similarly titled references, the function will return a list of them and ask if the user really wants a new DataStore reference generated. Assuming yes (or if there are no existing DataStore references with a similar title or if force = TRUE), the function will:

    1. download the .zip of the latest GitHub release for the repo,

    2. +
    3. initiate a draft reference on DataStore,

    4. +
    5. give the draft reference a title (repo + release tag),

    6. +
    7. upload the .zip from GitHub

    8. +
    9. add a web link to the release on GitHub.

    10. +
    11. add the items listed under GitHub repo "Topics" as keywords to the DataStore Script reference

    12. +

    create_datastore_script() will also access the keywords from your GitHub repo ("Topics") and add them to the draft references as keywords. It will automatically set your reference and all the files and links to public, allow data managers to edit the reference.

    The user will still need to go access the draft Script reference on DataStore to fill in the remaining fields (which are not accessible via API and so cannot be automated through this function) and activate the reference (thereby generating and registering a citeable DOI).

    If the Reference is a version of an older reference, the user will have to access the older version and indicate that it is an older version of the current Reference. The user will also have to manually add the new Reference to a Project for the repo, if desired.

    @@ -63,9 +84,10 @@

    Usage
    create_datastore_script(
       owner,
       repo,
    -  path = here::here(),
    +  path = here::here(),
       force = FALSE,
       dev = FALSE,
    +  for_or_by_NPS = TRUE,
       chunk_size_mb = 1,
       retry = 1
     )
    @@ -84,7 +106,7 @@

    Argumentspath -

    String. The location where the release .zip from GitHub should be downloaded to (and uploaded from). Defaults to the working directory of the R Project (i.e. here::here()).

    +

    String. The location where the release .zip from GitHub should be downloaded to (and uploaded from). Defaults to the working directory of the R Project (i.e. here::here()).

    force
    @@ -95,6 +117,10 @@

    Argumentsfor_or_by_NPS +

    Logical. Was the code, script, or software created either for or by NPS? Defaults to TRUE.

    + +
    chunk_size_mb

    The "chunk" size to break the file into for upload. If your network is slow and your uploads are failing, try decreasing this number (e.g. 0.5 or 0.25).

    diff --git a/docs/reference/document_missing_values.html b/docs/reference/document_missing_values.html index 06c91a6..a6b568e 100644 --- a/docs/reference/document_missing_values.html +++ b/docs/reference/document_missing_values.html @@ -86,7 +86,7 @@

    Handles multiple missing values

    Usage

    document_missing_values(
       file_name,
    -  directory = here::here(),
    +  directory = here::here(),
       colname = NA,
       missing_val_codes = NA,
       replace_value = NA
    @@ -130,7 +130,7 @@ 

    DetailsExamples

    if (FALSE) { # \dontrun{
     document_missing_values(file_name = "mydata.csv",
    -                        directory = here::here(),
    +                        directory = here::here(),
                             colname = NA, #do not change during function development
                             missing_val_codes = c("missing", "blank", "no data"),
                             replace_value = NA)
    diff --git a/docs/reference/get_custom_flags.html b/docs/reference/get_custom_flags.html
    index 3e31552..2b40c44 100644
    --- a/docs/reference/get_custom_flags.html
    +++ b/docs/reference/get_custom_flags.html
    @@ -91,7 +91,7 @@ 

    Creates dataframe(s) summarizing data quality

    Usage

    get_custom_flags(
    -  directory = here::here(),
    +  directory = here::here(),
       cols = (""),
       output = c("all", "files", "columns")
     )
    diff --git a/docs/reference/get_dc_flags.html b/docs/reference/get_dc_flags.html index 8d1be1f..a6b110d 100644 --- a/docs/reference/get_dc_flags.html +++ b/docs/reference/get_dc_flags.html @@ -63,7 +63,7 @@

    Create Table of Data Quality Flags in Flagging Columns within individual dat

    Usage

    -
    get_dc_flags(directory = here::here())
    +
    get_dc_flags(directory = here::here())
    diff --git a/docs/reference/get_df_flags.html b/docs/reference/get_df_flags.html index fff9e1a..539229d 100644 --- a/docs/reference/get_df_flags.html +++ b/docs/reference/get_df_flags.html @@ -63,7 +63,7 @@

    Create Table of Data Quality Flags Found in Data Files within a Data Package

    Usage

    -
    get_df_flags(directory = here::here())
    +
    get_df_flags(directory = here::here())
    diff --git a/docs/reference/get_dp_flags.html b/docs/reference/get_dp_flags.html index b608844..3104ffe 100644 --- a/docs/reference/get_dp_flags.html +++ b/docs/reference/get_dp_flags.html @@ -63,7 +63,7 @@

    Create Table of Data Quality Flags Found in a Data Package

    Usage

    -
    get_dp_flags(directory = here::here())
    +
    get_dp_flags(directory = here::here())
    diff --git a/docs/reference/remove_empty_tables.html b/docs/reference/remove_empty_tables.html index 7f78346..14dfdc1 100644 --- a/docs/reference/remove_empty_tables.html +++ b/docs/reference/remove_empty_tables.html @@ -64,7 +64,7 @@

    Value

    Examples

    
    -test_list <- list(item_a = tibble::tibble,
    +test_list <- list(item_a = tibble::tibble,
                       item_b = mtcars,
                       item_c = iris)
     
    diff --git a/docs/reference/replace_blanks.html b/docs/reference/replace_blanks.html
    index e6e7120..1d072a7 100644
    --- a/docs/reference/replace_blanks.html
    +++ b/docs/reference/replace_blanks.html
    @@ -105,7 +105,7 @@ 

    Replaces all blank cells a missing value code of your choice

    Usage

    -
    replace_blanks(directory = here::here(), missing_val_code = NA)
    +
    replace_blanks(directory = here::here(), missing_val_code = NA)
    @@ -139,7 +139,7 @@

    Examples replace_blanks() #replace all blank cells in .csvs in the directory ./test_data with "NODATA" - dir <- here::here("test_data") + dir <- here::here("test_data") replace_blanks(directory = dir, missing_val_code = "NODATA") #replace all blank cells in .csvs in the current directory with -99999 diff --git a/man/create_datastore_script.Rd b/man/create_datastore_script.Rd index 1503204..79820fa 100644 --- a/man/create_datastore_script.Rd +++ b/man/create_datastore_script.Rd @@ -10,6 +10,7 @@ create_datastore_script( path = here::here(), force = FALSE, dev = FALSE, + for_or_by_NPS = TRUE, chunk_size_mb = 1, retry = 1 ) @@ -25,6 +26,8 @@ create_datastore_script( \item{dev}{Logical. Defaults to FALSE. In the default status, the function generates and populates a new draft Script reference on the DataStore production server. If set to TRUE, the draft Script reference will be generated and populated on the DataStore development server. Setting dev = TRUE may be useful for testing the function without generating excessive references on the DataStore production server.} +\item{for_or_by_NPS}{Logical. Was the code, script, or software created either for or by NPS? Defaults to TRUE.} + \item{chunk_size_mb}{The "chunk" size to break the file into for upload. If your network is slow and your uploads are failing, try decreasing this number (e.g. 0.5 or 0.25).} \item{retry}{How many times to retry uploading a file chunk if it fails on the first try.} @@ -33,13 +36,21 @@ create_datastore_script( Invisibly returns the URL to the DataStore draft reference that was created. } \description{ -Given a GitHub owner ("nationalparkservice") and public repo ("EMLeditor"), the function uses the GitHub API to access the latest release version on GitHub and generate a corresponding draft Script reference on DataStore. +Given a GitHub owner ("nationalparkservice") and public repo ("EMLeditor"), the function uses the GitHub API to access the latest release version on GitHub and generate a corresponding draft public Script reference on DataStore. WARNING: if you are not an author of the repo on GitHub, you should probably NOT be the one adding it to DataStore unless you have very good reason. If you want to cite a GitHub release/repo and need a DOI, contact the repo maintainer and suggest they use this function to put it on DataStore for you. -It searches DataStore for references with a similar title (where the title is repo + release tag). If \code{force = FALSE} and there are similarly titled references, the function will return a list of them and ask if the user really wants a new DataStore reference generated. Assuming yes (or if there are no existing DataStore references with a similar title or \code{force = TRUE}), the function will: 1) download the .zip of the latest GitHub release for the repo, 2) initiate a draft reference on DataStore, 3) give the draft reference a title (repo + release tag), 4) upload the .zip from GitHub 5) add a web link to the release on GitHub. +The function searches DataStore for references with a similar title (where the title is repo + release tag). If \code{force = FALSE} and there are similarly titled references, the function will return a list of them and ask if the user really wants a new DataStore reference generated. Assuming yes (or if there are no existing DataStore references with a similar title or if \code{force = TRUE}), the function will: +\enumerate{ +\item download the .zip of the latest GitHub release for the repo, +\item initiate a draft reference on DataStore, +\item give the draft reference a title (repo + release tag), +\item upload the .zip from GitHub +\item add a web link to the release on GitHub. +\item add the items listed under GitHub repo "Topics" as keywords to the DataStore Script reference +} -\code{create_datastore_script()} will also access the keywords from your GitHub repo ("Topics") and add them to the draft references as keywords. It will automatically set your reference and all the files and links to public, allow data managers to edit the reference, and set the quality to "Operational". Unless you have good reason backed by a policy that specifically includes information from your release, please do not change these settings (and perhaps reconsider using public github repositories). +\code{create_datastore_script()} will also access the keywords from your GitHub repo ("Topics") and add them to the draft references as keywords. It will automatically set your reference and all the files and links to public, allow data managers to edit the reference. The user will still need to go access the draft Script reference on DataStore to fill in the remaining fields (which are not accessible via API and so cannot be automated through this function) and activate the reference (thereby generating and registering a citeable DOI). From 4d131b24039e3aedfd121665cc1f7c451b7ebc14 Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Wed, 7 Jan 2026 11:25:20 -0700 Subject: [PATCH 09/22] in create_datastore_script, for R packages download the "DESCRIPTION" file. --- R/datastore_interactions.R | 57 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/R/datastore_interactions.R b/R/datastore_interactions.R index 5f88569..1d705cd 100644 --- a/R/datastore_interactions.R +++ b/R/datastore_interactions.R @@ -37,12 +37,19 @@ #' } create_datastore_script <- function(owner, repo, + library = c(NULL, "R", "python"), path = here::here(), force = FALSE, dev = FALSE, for_or_by_NPS = TRUE, chunk_size_mb = 1, retry = 1) { + + + + #check "library" for valid values: + library <- match.arg(library) + gh_url <- paste0("https://api.github.com/repos/", owner, "/", @@ -418,6 +425,56 @@ create_datastore_script <- function(owner, stop("ERROR: DataStore connection failed. Are you logged in to the VPN?\n") } + # get and use R DESCRIPTION file: + if (library == "R") { + + descript_url <- paste0("https://raw.githubusercontent.com/", + owner, "/", + repo, "/", + "main/DESCRIPTION") + + #create file name: + file_name <- paste0(repo, "_", gh_req_rjson$tag_name, "_DESCRIPTION") + #create file path + download_file_path <- paste0("releases/", file_name) + + #download the file (.zip) from github: + invisible(capture.output( + suppressMessages( + httr::content( + httr::GET(descript_url, + httr::progress(), + httr::write_disk(download_file_path, + overwrite = TRUE)))))) + + } + + + descript_url <- paste0("https://api.github.com/repos/", + owner, "/", + repo, "/", + "contents/", + "DESCRIPTION") + + req_descript <- httr::GET(descript_url, + httr::add_headers('Accept' = 'application/vnd.github+json')) + + status_code <- httr::stop_for_status(req_descript)$status_code + + #if API call fails, alert user and remind them to log on to VPN: + if (!status_code == 200) { + stop("ERROR: GitHub connection failed. Are you connected to the internet?") + } + + #Make the json R friendly: + descript_req_json <- httr::content(req_descript, "text") + descript_req_rjson <- jsonlite::fromJSON(descript_req_json) + + + repos/{owner}/{repo}/contents/{path} + + } + #set bibliography patch URL if (dev == TRUE) { patch_url <- paste0(.QC_ds_dev_api(), From fa00d30d200c463d7a17dff8ae56d14227c65cd2 Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Wed, 7 Jan 2026 12:05:33 -0700 Subject: [PATCH 10/22] add tryCatch for missing or malformatted DESCRIPTION files --- R/datastore_interactions.R | 40 +++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/R/datastore_interactions.R b/R/datastore_interactions.R index 1d705cd..f4423c8 100644 --- a/R/datastore_interactions.R +++ b/R/datastore_interactions.R @@ -446,35 +446,31 @@ create_datastore_script <- function(owner, httr::progress(), httr::write_disk(download_file_path, overwrite = TRUE)))))) + #read in the DESCRIPTION file - add a trycatch for 404notfound: + #Warning message: + # In readLines(file) : + # incomplete final line found on 'releases/test_DESCRIPTION2' + desc2 <- tryCatch(description$new(file = paste0("releases/", file_name)), + error = function(e){}, + warning = function(w){ + msg <- paste0("Warning: your DESCRIPTION file is ", + "missing or malformatted. Some ", + "DataStore fields could not be ", + "automatically entered. Are you sure ", + "the repo contains a valid R package?") + cat(msg) - } + }) + desc2 <- description$new(file = paste0("releases/", file_name)) - descript_url <- paste0("https://api.github.com/repos/", - owner, "/", - repo, "/", - "contents/", - "DESCRIPTION") + #get authors: + authors <- desc2$get_author("aut") - req_descript <- httr::GET(descript_url, - httr::add_headers('Accept' = 'application/vnd.github+json')) + # - status_code <- httr::stop_for_status(req_descript)$status_code - - #if API call fails, alert user and remind them to log on to VPN: - if (!status_code == 200) { - stop("ERROR: GitHub connection failed. Are you connected to the internet?") } - #Make the json R friendly: - descript_req_json <- httr::content(req_descript, "text") - descript_req_rjson <- jsonlite::fromJSON(descript_req_json) - - - repos/{owner}/{repo}/contents/{path} - - } - #set bibliography patch URL if (dev == TRUE) { patch_url <- paste0(.QC_ds_dev_api(), From 1e82a2476497ff7553f42a165c5b1733bf7e535d Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Wed, 7 Jan 2026 20:19:57 -0700 Subject: [PATCH 11/22] clean up some code documentation --- R/datastore_interactions.R | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/R/datastore_interactions.R b/R/datastore_interactions.R index f4423c8..277ae7e 100644 --- a/R/datastore_interactions.R +++ b/R/datastore_interactions.R @@ -446,12 +446,11 @@ create_datastore_script <- function(owner, httr::progress(), httr::write_disk(download_file_path, overwrite = TRUE)))))) - #read in the DESCRIPTION file - add a trycatch for 404notfound: - #Warning message: - # In readLines(file) : - # incomplete final line found on 'releases/test_DESCRIPTION2' + #read in the DESCRIPTION file + # missing or desc2 <- tryCatch(description$new(file = paste0("releases/", file_name)), error = function(e){}, + #warnings for bad or missing DESCRIPTION files warning = function(w){ msg <- paste0("Warning: your DESCRIPTION file is ", "missing or malformatted. Some ", @@ -459,13 +458,11 @@ create_datastore_script <- function(owner, "automatically entered. Are you sure ", "the repo contains a valid R package?") cat(msg) - }) - desc2 <- description$new(file = paste0("releases/", file_name)) + if (!is.null(desc2)) { + authors <- desc2$get_author("aut") - #get authors: - authors <- desc2$get_author("aut") # From 61fc7b95ff74c9a82866d7663cb3f19c2f22f59a Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Wed, 7 Jan 2026 21:15:16 -0700 Subject: [PATCH 12/22] create json body for contacts 1 (authors) and contacts2 (contacts) from DESCRIPTION file --- R/datastore_interactions.R | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/R/datastore_interactions.R b/R/datastore_interactions.R index 277ae7e..3a4a874 100644 --- a/R/datastore_interactions.R +++ b/R/datastore_interactions.R @@ -431,7 +431,7 @@ create_datastore_script <- function(owner, descript_url <- paste0("https://raw.githubusercontent.com/", owner, "/", repo, "/", - "main/DESCRIPTION") + "master/DESCRIPTION") #create file name: file_name <- paste0(repo, "_", gh_req_rjson$tag_name, "_DESCRIPTION") @@ -461,7 +461,40 @@ create_datastore_script <- function(owner, }) if (!is.null(desc2)) { + + #create authors (contact1) authors <- desc2$get_author("aut") + mylist <- list() + for (i in 1:length(authors)) { + aut <- list(title = NULL, + primaryName = authors[i]$family, + firstName = authors[i]$given, + middleName = NULL, + suffix = NULL, + affiliation = NULL, + isCorporate = NULL, + ORCID = authors[i]$comment[[1]]) + mylist <- append(mylist, list(aut)) + } + + contact1 <- jsonlite::toJSON(mylist, pretty = TRUE, auto_unbox = TRUE) + + #create contacts (contact2) + contacts <- desc2$get_author("cre") + mylist <- list() + for (i in 1:length(contacts)) { + con <- list(title = NULL, + primaryName = contacts[i]$family, + firstName = contacts[i]$given, + middleName = NULL, + suffix = NULL, + affiliation = NULL, + isCorporate = NULL, + ORCID = contacts[i]$comment[[1]]) + mylist <- append(mylist, list(con)) + } + + contact2 <- jsonlite::toJSON(mylist, pretty = TRUE, auto_unbox = TRUE) # From c9c36fb5262ea6b2159447db271baa90deab8bac Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Fri, 9 Jan 2026 08:41:05 -0700 Subject: [PATCH 13/22] automate getting authors (aut) and stewards (cre) from R package DESCRIPTION file and adding them to the Script reference. --- R/datastore_interactions.R | 90 ++++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/R/datastore_interactions.R b/R/datastore_interactions.R index 3a4a874..d19efb8 100644 --- a/R/datastore_interactions.R +++ b/R/datastore_interactions.R @@ -425,6 +425,34 @@ create_datastore_script <- function(owner, stop("ERROR: DataStore connection failed. Are you logged in to the VPN?\n") } + #set bibliography patch URL + if (dev == TRUE) { + patch_url <- paste0(.QC_ds_dev_api(), + "Reference/", + ds_ref, + "/Bibliography") + } else { + patch_url <- paste0(.QC_ds_secure_api(), + "Reference/", + ds_ref, + "/Bibliography") + } + + #Set for or by NPS: + NPS_origination <- list(isAgencyOriginated = for_or_by_NPS) + bdy <- jsonlite::toJSON(NPS_origination, pretty = TRUE, auto_unbox = TRUE) + + NPS_req <- httr::PATCH(patch_url, + httr::authenticate(":", "", "ntlm"), + httr::add_headers('Content-Type' = 'application/json'), + body = bdy) + + #check status code; suggest logging in to VPN if errors occur: + status_code <- httr::stop_for_status(NPS_req)$status_code + if (!status_code == 200) { + stop("ERROR: DataStore connection failed. Are you logged in to the VPN?\n") + } + # get and use R DESCRIPTION file: if (library == "R") { @@ -467,17 +495,18 @@ create_datastore_script <- function(owner, mylist <- list() for (i in 1:length(authors)) { aut <- list(title = NULL, - primaryName = authors[i]$family, - firstName = authors[i]$given, - middleName = NULL, - suffix = NULL, - affiliation = NULL, - isCorporate = NULL, - ORCID = authors[i]$comment[[1]]) + primaryName = authors[i]$family, + firstName = authors[i]$given, + middleName = NULL, + suffix = NULL, + affiliation = NULL, + isCorporate = FALSE, + ORCID = authors[i]$comment[[1]]) mylist <- append(mylist, list(aut)) } + contact1 <- mylist - contact1 <- jsonlite::toJSON(mylist, pretty = TRUE, auto_unbox = TRUE) + #contact1 <- jsonlite::toJSON(mylist, pretty = TRUE, auto_unbox = TRUE) #create contacts (contact2) contacts <- desc2$get_author("cre") @@ -489,44 +518,29 @@ create_datastore_script <- function(owner, middleName = NULL, suffix = NULL, affiliation = NULL, - isCorporate = NULL, + isCorporate = FALSE, ORCID = contacts[i]$comment[[1]]) mylist <- append(mylist, list(con)) } + contact2 <- mylist + #contact2 <- jsonlite::toJSON(mylist, pretty = TRUE, auto_unbox = TRUE) - contact2 <- jsonlite::toJSON(mylist, pretty = TRUE, auto_unbox = TRUE) + bdy <- list(contacts1 = contact1, + contacts2 = contact2) + bdy <- jsonlite::toJSON(bdy, pretty = TRUE, null = "null", auto_unbox = TRUE) - # + contacts_req <- httr::PATCH(patch_url, + httr::authenticate(":", "", "ntlm"), + httr::add_headers('Content-Type' = 'application/json'), + body = bdy) + #check status code; suggest logging in to VPN if errors occur: + status_code <- httr::stop_for_status(contacts_req)$status_code + if (!status_code == 200) { + stop("ERROR: DataStore connection failed. Are you logged in to the VPN?\n") + } } - - #set bibliography patch URL - if (dev == TRUE) { - patch_url <- paste0(.QC_ds_dev_api(), - "Reference/", - ds_ref, - "/Bibliography") - } else { - patch_url <- paste0(.QC_ds_secure_api(), - "Reference/", - ds_ref, - "/Bibliography") - } - - #Set for or by NPS: - NPS_origination <- list(isAgencyOriginated = for_or_by_NPS) - bdy <- jsonlite::toJSON(NPS_origination, pretty = TRUE, auto_unbox = TRUE) - - NPS_req <- httr::PATCH(patch_url, - httr::authenticate(":", "", "ntlm"), - httr::add_headers('Content-Type' = 'application/json'), - body = bdy) - - #check status code; suggest logging in to VPN if errors occur: - status_code <- httr::stop_for_status(NPS_req)$status_code - if (!status_code == 200) { - stop("ERROR: DataStore connection failed. Are you logged in to the VPN?\n") } From b5ba67c8a3a5eb3596e345f083fbe9d78235b0c4 Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Fri, 9 Jan 2026 13:13:57 -0700 Subject: [PATCH 14/22] automate abstract in DataStore reference from R package --- R/datastore_interactions.R | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/R/datastore_interactions.R b/R/datastore_interactions.R index d19efb8..bc3049f 100644 --- a/R/datastore_interactions.R +++ b/R/datastore_interactions.R @@ -476,7 +476,8 @@ create_datastore_script <- function(owner, overwrite = TRUE)))))) #read in the DESCRIPTION file # missing or - desc2 <- tryCatch(description$new(file = paste0("releases/", file_name)), + desc2 <- tryCatch(desc::description$new(file = paste0("releases/", + file_name)), error = function(e){}, #warnings for bad or missing DESCRIPTION files warning = function(w){ @@ -492,7 +493,7 @@ create_datastore_script <- function(owner, #create authors (contact1) authors <- desc2$get_author("aut") - mylist <- list() + contact1 <- list() for (i in 1:length(authors)) { aut <- list(title = NULL, primaryName = authors[i]$family, @@ -502,15 +503,12 @@ create_datastore_script <- function(owner, affiliation = NULL, isCorporate = FALSE, ORCID = authors[i]$comment[[1]]) - mylist <- append(mylist, list(aut)) + contact1 <- append(contact1, list(aut)) } - contact1 <- mylist - - #contact1 <- jsonlite::toJSON(mylist, pretty = TRUE, auto_unbox = TRUE) #create contacts (contact2) contacts <- desc2$get_author("cre") - mylist <- list() + contact2 <- list() for (i in 1:length(contacts)) { con <- list(title = NULL, primaryName = contacts[i]$family, @@ -520,12 +518,14 @@ create_datastore_script <- function(owner, affiliation = NULL, isCorporate = FALSE, ORCID = contacts[i]$comment[[1]]) - mylist <- append(mylist, list(con)) + contact2 <- append(contact2, list(con)) } - contact2 <- mylist - #contact2 <- jsonlite::toJSON(mylist, pretty = TRUE, auto_unbox = TRUE) - bdy <- list(contacts1 = contact1, + package_descript <- desc2$get("Description")[[1]] + abstract <- list(abstract = package_descript) + + bdy <- list(abstract = abstract, + contacts1 = contact1, contacts2 = contact2) bdy <- jsonlite::toJSON(bdy, pretty = TRUE, null = "null", auto_unbox = TRUE) From 22ce92d87d1b4646cec52e7505d1020a0a972894 Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Fri, 9 Jan 2026 14:22:26 -0700 Subject: [PATCH 15/22] so much debugging --- R/datastore_interactions.R | 83 ++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 39 deletions(-) diff --git a/R/datastore_interactions.R b/R/datastore_interactions.R index bc3049f..5c99df8 100644 --- a/R/datastore_interactions.R +++ b/R/datastore_interactions.R @@ -79,18 +79,18 @@ create_datastore_script <- function(owner, #quick search of DataStore for the string "dynamic title" post_url <- paste0(.QC_ds_secure_api(), "QuickSearch?q=", dynamic_title) - req <- httr::GET(post_url, + req_search <- httr::GET(post_url, httr::authenticate(":", "", "ntlm"), httr::add_headers('accept' = 'application/json')) #check status code; suggest logging in to VPN if errors occur: - status_code <- httr::stop_for_status(req)$status_code + status_code <- httr::stop_for_status(req_search)$status_code if (!status_code == 200) { stop("ERROR: DataStore connection failed. Are you logged in to the VPN?\n") } #get search results and turn into a dataframe: - json <- httr::content(req, "text") + json <- httr::content(req_search, "text") rjson <- jsonlite::fromJSON(json) items <- as.data.frame(rjson$items) @@ -101,11 +101,12 @@ create_datastore_script <- function(owner, if (length(seq_along(matches$title) > 0)) { cat("One or more DataStore references with title containing: ", new_ref_title, - " already exists:", sep = "") + " already exists:\n", sep = "") cat("Reference ID: ", matches$referenceId, "; Title: ", - matches$title, sep = "") + matches$title, + "\n\n", sep = "") cat("Are you sure you want to create a new draft reference for ", new_ref_title, "?", sep = "") var1 <- readline(prompt = cat("\n\n1: Yes\n2: No\n\n")) @@ -169,17 +170,17 @@ create_datastore_script <- function(owner, } #create the draft reference: - req <- httr::POST(post_url, + req_draft <- httr::POST(post_url, httr::authenticate(":", "", "ntlm"), httr::add_headers('Content-Type' = 'application/json'), body = bdy) #check status code; suggest logging in to VPN if errors occur: - status_code <- httr::stop_for_status(req)$status_code + status_code <- httr::stop_for_status(req_draft)$status_code if (!status_code == 200) { stop("ERROR: DataStore connection failed. Are you logged in to the VPN?\n") } #get newly created reference id: - json <- httr::content(req, "text") + json <- httr::content(req_draft, "text") rjson <- jsonlite::fromJSON(json) ds_ref <- rjson$referenceCode @@ -315,13 +316,13 @@ create_datastore_script <- function(owner, } #upload the weblink: - req <- httr::POST( + req_weblink <- httr::POST( url = api_url, httr::add_headers('Content-Type' = 'application/json'), httr::authenticate(":", "", "ntlm"), body = bdy) - status_code <- httr::stop_for_status(req)$status_code + status_code <- httr::stop_for_status(req_weblink)$status_code if (status_code != 200) { stop("ERROR: DataStore connection failed. Your web link was not added.") } @@ -415,12 +416,12 @@ create_datastore_script <- function(owner, } #set reference to public: - req <- httr::PUT(post_url, + req_public <- httr::PUT(post_url, httr::authenticate(":", "", "ntlm"), httr::add_headers('Content-Type' = 'application/json'), body = bdy) #check status code; suggest logging in to VPN if errors occur: - status_code <- httr::stop_for_status(req)$status_code + status_code <- httr::stop_for_status(req_public)$status_code if (!status_code == 200) { stop("ERROR: DataStore connection failed. Are you logged in to the VPN?\n") } @@ -474,8 +475,7 @@ create_datastore_script <- function(owner, httr::progress(), httr::write_disk(download_file_path, overwrite = TRUE)))))) - #read in the DESCRIPTION file - # missing or + # read in the DESCRIPTION file desc2 <- tryCatch(desc::description$new(file = paste0("releases/", file_name)), error = function(e){}, @@ -492,39 +492,44 @@ create_datastore_script <- function(owner, if (!is.null(desc2)) { #create authors (contact1) + #authors <- desc::desc_get_author("aut", + # file = paste0("releases/", file_name)) authors <- desc2$get_author("aut") - contact1 <- list() - for (i in 1:length(authors)) { - aut <- list(title = NULL, - primaryName = authors[i]$family, - firstName = authors[i]$given, - middleName = NULL, - suffix = NULL, - affiliation = NULL, - isCorporate = FALSE, - ORCID = authors[i]$comment[[1]]) - contact1 <- append(contact1, list(aut)) - } - - #create contacts (contact2) - contacts <- desc2$get_author("cre") - contact2 <- list() - for (i in 1:length(contacts)) { - con <- list(title = NULL, - primaryName = contacts[i]$family, - firstName = contacts[i]$given, + #if(!is.null(authors)) { + aut_list <- list() + for (i in 1:length(seq_along(authors))) { + aut <- list(title = NULL, + primaryName = authors[[i]]$family, + firstName = authors[[i]]$given, + middleName = NULL, + suffix = NULL, + affiliation = NULL, + isCorporate = FALSE, + ORCID = authors[[i]]$comment[[1]]) + aut_list <- append(aut_list, list(aut)) + } + contact1 <- aut_list + + #create contacts (contact2) + contacts <- desc2$get_author("cre") + contact2 <- list() + for (i in 1:length(contacts)) { + con <- list(title = NULL, + primaryName = contacts[[i]]$family, + firstName = contacts[[i]]$given, middleName = NULL, suffix = NULL, affiliation = NULL, isCorporate = FALSE, - ORCID = contacts[i]$comment[[1]]) - contact2 <- append(contact2, list(con)) + ORCID = contacts[[i]]$comment[[1]]) + contact2 <- append(contact2, list(con)) + } } package_descript <- desc2$get("Description")[[1]] - abstract <- list(abstract = package_descript) + #abstract <- list(abstract = package_descript) - bdy <- list(abstract = abstract, + bdy <- list(abstract = package_descript, contacts1 = contact1, contacts2 = contact2) @@ -541,7 +546,7 @@ create_datastore_script <- function(owner, stop("ERROR: DataStore connection failed. Are you logged in to the VPN?\n") } } - } + # make reference URL From 24d8351afe85ac587887d282a79b5916b8759f2f Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Fri, 9 Jan 2026 14:34:37 -0700 Subject: [PATCH 16/22] add ability to put in issuedDate. --- R/datastore_interactions.R | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/R/datastore_interactions.R b/R/datastore_interactions.R index 5c99df8..d1f3716 100644 --- a/R/datastore_interactions.R +++ b/R/datastore_interactions.R @@ -529,7 +529,12 @@ create_datastore_script <- function(owner, package_descript <- desc2$get("Description")[[1]] #abstract <- list(abstract = package_descript) - bdy <- list(abstract = package_descript, + date <- list(year = format(Sys.time(), "%Y"), + month = format(Sys.time(), "%m"), + day = format(Sys.time(), "%d")) + + bdy <- list(issuedDate = date, + abstract = package_descript, contacts1 = contact1, contacts2 = contact2) From 865a82f6be6f0e277f00d627d265734fc5b15241 Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Fri, 9 Jan 2026 15:00:07 -0700 Subject: [PATCH 17/22] fix match.arg errors/bugs --- R/datastore_interactions.R | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/R/datastore_interactions.R b/R/datastore_interactions.R index d1f3716..d5d1bbc 100644 --- a/R/datastore_interactions.R +++ b/R/datastore_interactions.R @@ -37,7 +37,9 @@ #' } create_datastore_script <- function(owner, repo, - library = c(NULL, "R", "python"), + lib_type = c("generic_script", + "R", + "python"), path = here::here(), force = FALSE, dev = FALSE, @@ -45,10 +47,8 @@ create_datastore_script <- function(owner, chunk_size_mb = 1, retry = 1) { - - - #check "library" for valid values: - library <- match.arg(library) + #check "lib_type" for valid values; if no value supplied defaults to "generic_script": + lib_type <- match.arg(lib_type) gh_url <- paste0("https://api.github.com/repos/", owner, @@ -112,7 +112,7 @@ create_datastore_script <- function(owner, var1 <- readline(prompt = cat("\n\n1: Yes\n2: No\n\n")) if (var1 == 2) { cat("You have not generated a new DataStore reference.") - return() + return(invisible(NULL)) } } } @@ -439,9 +439,14 @@ create_datastore_script <- function(owner, "/Bibliography") } - #Set for or by NPS: - NPS_origination <- list(isAgencyOriginated = for_or_by_NPS) - bdy <- jsonlite::toJSON(NPS_origination, pretty = TRUE, auto_unbox = TRUE) + #Set issuedDate & Agency originated: + date <- list(year = format(Sys.time(), "%Y"), + month = format(Sys.time(), "%m"), + day = format(Sys.time(), "%d")) + bdy <- list(issuedDate = date, + isAgencyOriginated = for_or_by_NPS) + + bdy <- jsonlite::toJSON(bdy, pretty = TRUE, auto_unbox = TRUE) NPS_req <- httr::PATCH(patch_url, httr::authenticate(":", "", "ntlm"), @@ -455,7 +460,7 @@ create_datastore_script <- function(owner, } # get and use R DESCRIPTION file: - if (library == "R") { + if (lib_type == "R") { descript_url <- paste0("https://raw.githubusercontent.com/", owner, "/", @@ -527,14 +532,8 @@ create_datastore_script <- function(owner, } package_descript <- desc2$get("Description")[[1]] - #abstract <- list(abstract = package_descript) - - date <- list(year = format(Sys.time(), "%Y"), - month = format(Sys.time(), "%m"), - day = format(Sys.time(), "%d")) - bdy <- list(issuedDate = date, - abstract = package_descript, + bdy <- list(abstract = package_descript, contacts1 = contact1, contacts2 = contact2) From 3888081538dcaca1bd9b03f2e935c5b8df639546 Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Fri, 9 Jan 2026 15:01:18 -0700 Subject: [PATCH 18/22] update documentation --- R/datastore_interactions.R | 1 + 1 file changed, 1 insertion(+) diff --git a/R/datastore_interactions.R b/R/datastore_interactions.R index d5d1bbc..6c97970 100644 --- a/R/datastore_interactions.R +++ b/R/datastore_interactions.R @@ -20,6 +20,7 @@ #' #' @param owner String. The owner of the account where the GitHub repo resides. For example, "nationalparkservice" #' @param repo String. The repo with a release that should be turned into a DataStore Script reference. For example, "EMLeditor" +#' @param lib_type String. Can be one of three values: generic_script, R, or python. Defaults to "generic_script". #' @param path String. The location where the release .zip from GitHub should be downloaded to (and uploaded from). Defaults to the working directory of the R Project (i.e. `here::here()`). #' @param force Logical. Defaults to FALSE. In the default status the function has a number of interactive components, such as searching DataStore for similarly titled References and asking if a new Reference is really what the user wants. When set to TRUE, all interactive components are turned off and the function will proceed unless it hits an error. Setting force = TRUE may be useful for scripting purposes. #' @param dev Logical. Defaults to FALSE. In the default status, the function generates and populates a new draft Script reference on the DataStore production server. If set to TRUE, the draft Script reference will be generated and populated on the DataStore development server. Setting dev = TRUE may be useful for testing the function without generating excessive references on the DataStore production server. From 5e769671507036d5c0d052b2dcb9ae7a5f1485ac Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Fri, 9 Jan 2026 15:33:49 -0700 Subject: [PATCH 19/22] usethis::use_package to add package desc --- DESCRIPTION | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index fcd6189..bb6a373 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -62,7 +62,8 @@ Imports: cli, purrr, lifecycle, - httr2 + httr2, + desc RoxygenNote: 7.3.2 Suggests: knitr, From d5e6b8cf4314f6cadf2287a38b2b23ce00c82027 Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Fri, 9 Jan 2026 15:34:09 -0700 Subject: [PATCH 20/22] updates on create_datastore_script enhancements --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index 0024216..9b5efb0 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,7 @@ # QCkit v1.2.1 +## 2025-01-09 + * `create_datastore_script` now has a new parameter, lib_type. If "R" is specified it will pull as much info as it can from the DESCRIPTION file of an R package and use that info to fill out the Core Bibliography tab on the reference landing page. + ## 2025-01-06 * Add ability to set the Origination flag in DataStore via the `create_datastore_script` function. Defaults to TRUE. From a7c1670601717cfb4f10614253777cbecad18186 Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Fri, 9 Jan 2026 15:34:23 -0700 Subject: [PATCH 21/22] update documentation --- R/datastore_interactions.R | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/R/datastore_interactions.R b/R/datastore_interactions.R index 6c97970..c7b3954 100644 --- a/R/datastore_interactions.R +++ b/R/datastore_interactions.R @@ -11,9 +11,10 @@ #' 4) upload the .zip from GitHub #' 5) add a web link to the release on GitHub. #' 6) add the items listed under GitHub repo "Topics" as keywords to the DataStore Script reference -#' -#' `create_datastore_script()` will also access the keywords from your GitHub repo ("Topics") and add them to the draft references as keywords. It will automatically set your reference and all the files and links to public, allow data managers to edit the reference. -#' +#' 7) Set for or by NPS flag +#' 8) Set the issued date +#' 9) If you indicate it is an R package, the authors, steward, description, and other fields will be filled out on the Core tab +#'#' #' The user will still need to go access the draft Script reference on DataStore to fill in the remaining fields (which are not accessible via API and so cannot be automated through this function) and activate the reference (thereby generating and registering a citeable DOI). #' #' If the Reference is a version of an older reference, the user will have to access the older version and indicate that it is an older version of the current Reference. The user will also have to manually add the new Reference to a Project for the repo, if desired. @@ -534,7 +535,8 @@ create_datastore_script <- function(owner, package_descript <- desc2$get("Description")[[1]] - bdy <- list(abstract = package_descript, + bdy <- list(miscellaneousCode = "R", + abstract = package_descript, contacts1 = contact1, contacts2 = contact2) From 9e6763043c811da358e85be5efd9885dba7d88ff Mon Sep 17 00:00:00 2001 From: Robert Baker Date: Fri, 9 Jan 2026 15:34:48 -0700 Subject: [PATCH 22/22] updated via devtools::document and pkgdown::build_site_github_pages --- docs/news/index.html | 13 ++++--- docs/pkgdown.yml | 2 +- docs/reference/create_datastore_script.html | 38 ++++++++++++++------- man/create_datastore_script.Rd | 12 ++++--- 4 files changed, 44 insertions(+), 21 deletions(-) diff --git a/docs/news/index.html b/docs/news/index.html index 59ff20c..4282321 100644 --- a/docs/news/index.html +++ b/docs/news/index.html @@ -41,19 +41,24 @@

    Changelog

    QCkit v1.2.1

    -

    2025-01-06

    +

    2025-01-09

    +
    • +create_datastore_script now has a new parameter, lib_type. If “R” is specified it will pull as much info as it can from the DESCRIPTION file of an R package and use that info to fill out the Core Bibliography tab on the reference landing page.
    • +
    +
    +

    2025-01-06

    • Add ability to set the Origination flag in DataStore via the create_datastore_script function. Defaults to TRUE.
    -

    2025-01-05

    +

    2025-01-05

    • Fixed bug in create_datastore_script that occurred when the way the DataStore API handled access constraints changed between V7 and V8. Also improved formatting of screen print and make the DataStore reference link clickable.
    -

    2025-12-31

    +

    2025-12-31

    • Updated DataStore APIs to hit v8 API instead of now deprecated v7 API endponts
    -

    2025-05-22

    +

    2025-05-22

    • fix minor bug in create_datastore_script
    diff --git a/docs/pkgdown.yml b/docs/pkgdown.yml index 2273b3f..206bccf 100644 --- a/docs/pkgdown.yml +++ b/docs/pkgdown.yml @@ -5,7 +5,7 @@ articles: articles/DRR_Purpose_and_Scope: DRR_Purpose_and_Scope.html articles/Starting-a-DRR: Starting-a-DRR.html articles/Using-the-DRR-Template: Using-the-DRR-Template.html -last_built: 2026-01-06T19:53Z +last_built: 2026-01-09T22:30Z urls: reference: https://nationalparkservice.github.io/QCkit/reference article: https://nationalparkservice.github.io/QCkit/articles diff --git a/docs/reference/create_datastore_script.html b/docs/reference/create_datastore_script.html index ee5ac86..4c266e5 100644 --- a/docs/reference/create_datastore_script.html +++ b/docs/reference/create_datastore_script.html @@ -1,5 +1,5 @@ -Turn a GitHub release into a DataStore Script Reference — create_datastore_script • QCkit +If the Reference is a version of an older reference, the user will have to access the older version and indicate that it is an older version of the current Reference. The user will also have to manually add the new Reference to a Project for the repo, if desired."> Skip to contents @@ -74,9 +80,12 @@

    Turn a GitHub release into a DataStore Script Reference

  2. upload the .zip from GitHub

  3. add a web link to the release on GitHub.

  4. add the items listed under GitHub repo "Topics" as keywords to the DataStore Script reference

  5. -

create_datastore_script() will also access the keywords from your GitHub repo ("Topics") and add them to the draft references as keywords. It will automatically set your reference and all the files and links to public, allow data managers to edit the reference.

-

The user will still need to go access the draft Script reference on DataStore to fill in the remaining fields (which are not accessible via API and so cannot be automated through this function) and activate the reference (thereby generating and registering a citeable DOI).

-

If the Reference is a version of an older reference, the user will have to access the older version and indicate that it is an older version of the current Reference. The user will also have to manually add the new Reference to a Project for the repo, if desired.

+
  • Set for or by NPS flag

  • +
  • Set the issued date

  • +
  • If you indicate it is an R package, the authors, steward, description, and other fields will be filled out on the Core tab +#' +The user will still need to go access the draft Script reference on DataStore to fill in the remaining fields (which are not accessible via API and so cannot be automated through this function) and activate the reference (thereby generating and registering a citeable DOI).

  • +

    If the Reference is a version of an older reference, the user will have to access the older version and indicate that it is an older version of the current Reference. The user will also have to manually add the new Reference to a Project for the repo, if desired.

    @@ -84,6 +93,7 @@

    Usage
    create_datastore_script(
       owner,
       repo,
    +  lib_type = c("generic_script", "R", "python"),
       path = here::here(),
       force = FALSE,
       dev = FALSE,
    @@ -105,6 +115,10 @@ 

    Arguments +
    lib_type
    +

    String. Can be one of three values: generic_script, R, or python. Defaults to "generic_script".

    + +
    path

    String. The location where the release .zip from GitHub should be downloaded to (and uploaded from). Defaults to the working directory of the R Project (i.e. here::here()).

    diff --git a/man/create_datastore_script.Rd b/man/create_datastore_script.Rd index 79820fa..b1d9ac4 100644 --- a/man/create_datastore_script.Rd +++ b/man/create_datastore_script.Rd @@ -7,6 +7,7 @@ create_datastore_script( owner, repo, + lib_type = c("generic_script", "R", "python"), path = here::here(), force = FALSE, dev = FALSE, @@ -20,6 +21,8 @@ create_datastore_script( \item{repo}{String. The repo with a release that should be turned into a DataStore Script reference. For example, "EMLeditor"} +\item{lib_type}{String. Can be one of three values: generic_script, R, or python. Defaults to "generic_script".} + \item{path}{String. The location where the release .zip from GitHub should be downloaded to (and uploaded from). Defaults to the working directory of the R Project (i.e. \code{here::here()}).} \item{force}{Logical. Defaults to FALSE. In the default status the function has a number of interactive components, such as searching DataStore for similarly titled References and asking if a new Reference is really what the user wants. When set to TRUE, all interactive components are turned off and the function will proceed unless it hits an error. Setting force = TRUE may be useful for scripting purposes.} @@ -48,11 +51,12 @@ The function searches DataStore for references with a similar title (where the t \item upload the .zip from GitHub \item add a web link to the release on GitHub. \item add the items listed under GitHub repo "Topics" as keywords to the DataStore Script reference -} - -\code{create_datastore_script()} will also access the keywords from your GitHub repo ("Topics") and add them to the draft references as keywords. It will automatically set your reference and all the files and links to public, allow data managers to edit the reference. - +\item Set for or by NPS flag +\item Set the issued date +\item If you indicate it is an R package, the authors, steward, description, and other fields will be filled out on the Core tab +#' The user will still need to go access the draft Script reference on DataStore to fill in the remaining fields (which are not accessible via API and so cannot be automated through this function) and activate the reference (thereby generating and registering a citeable DOI). +} If the Reference is a version of an older reference, the user will have to access the older version and indicate that it is an older version of the current Reference. The user will also have to manually add the new Reference to a Project for the repo, if desired. }