diff --git a/DESCRIPTION b/DESCRIPTION index e3376804..06b67d8c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -70,4 +70,4 @@ ByteCompile: true Encoding: UTF-8 Language: en-US Roxygen: list(markdown = TRUE) -RoxygenNote: 7.1.2 +RoxygenNote: 7.3.2 diff --git a/cran-comments.md b/cran-comments.md index de1bfb3b..a6cd5244 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -2,45 +2,42 @@ ## Test environments -* Local Mac OS install, R-release 4.0.2 -* Ubuntu 16.04 (on GitHub Actions), R-release, R 4.1.2 -* Mac OS 10.15.5 (on GitHub Actions) R-release, R 4.1.2 -* Microsoft Windows Server 2019 10.0.17763 (on GitHub Actions) R-release, R 4.1.2 -* win-builder (R-release 4.1.2) +* Local Mac OS install, R-release 4.4.1 +* Ubuntu 18.04 (on GitHub Actions), R-release, R 4.4.2 +* Mac OS 10.15.5 (on GitHub Actions) R-release, R 4.4.2 +* Microsoft Windows Server 2019 10.0.17763 (on GitHub Actions) R-release, R 4.4.2 +* win-builder (R-release 4.4.2) ## R CMD check results -* checking CRAN incoming feasibility ... Note_to_CRAN_maintainers +* checking CRAN incoming feasibility ... NOTE Maintainer: 'Steven M. Mortimer ' -Possibly mis-spelled words in DESCRIPTION: - APIs (2:42, 5:64, 9:16) - JSON (9:59) - -0 errors ✓ | 0 warnings ✓ | 0 notes ✓ +0 errors ✓ | 0 warnings ✓ | 1 notes ✖ ## revdepcheck results -### Platform - -|field |value | -|:--------|:----------------------------------------| -|version |R version 4.0.2 (2020-06-22) | -|os |OS X 12.2.1 | -|system |x86_64, darwin17.0 | -|ui |RStudio | -|language |(EN) | -|collate |en_US.UTF-8 | -|ctype |en_US.UTF-8 | -|tz |America/Chicago | -|date |2022-02-27 | -|rstudio |2021.09.1+372 Ghost Orchid (desktop) | -|pandoc |2.16.2 @ /usr/local/bin/ (via rmarkdown) | - -### Dependencies - -|package |old |new |Δ | -|:-----------|:-----|:-----|:--| -|salesforcer |1.0.0 |1.0.1 |* | +# Platform + +|field |value | +|:--------|:-----------------------------------------------------------------------------------------------| +|version |R version 4.4.1 (2024-06-14) | +|os |macOS Monterey 12.7.6 | +|system |x86_64, darwin20 | +|ui |RStudio | +|language |(EN) | +|collate |en_US.UTF-8 | +|ctype |en_US.UTF-8 | +|tz |America/Chicago | +|date |2024-11-04 | +|rstudio |2024.09.0+375 Cranberry Hibiscus (desktop) | +|pandoc |3.2 @ /Applications/RStudio.app/Contents/Resources/app/quarto/bin/tools/x86_64/ (via rmarkdown) | + +# Dependencies + +|package |old |new |Δ | +|:-----------|:-----|:----------|:--| +|salesforcer |1.0.1 |1.0.1.9999 |* | +|withr |NA |3.0.2 |* | ### Revdeps diff --git a/man/format_report_row.Rd b/man/format_report_row.Rd index 9be65fec..df5492f4 100644 --- a/man/format_report_row.Rd +++ b/man/format_report_row.Rd @@ -26,10 +26,11 @@ may be \code{"Account B"} and the value \code{0016A0000035mJEQAY}. The former \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{bind_using_character_cols}{\code{logical}; an indicator of whether to cast the data to all character columns to ensure that \code{\link[dplyr:bind]{bind_rows}} diff --git a/man/parse_report_detail_rows.Rd b/man/parse_report_detail_rows.Rd index 6bc51588..60dd53e8 100644 --- a/man/parse_report_detail_rows.Rd +++ b/man/parse_report_detail_rows.Rd @@ -31,10 +31,11 @@ may be \code{"Account B"} and the value \code{0016A0000035mJEQAY}. The former \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{bind_using_character_cols}{\code{logical}; an indicator of whether to cast the data to all character columns to ensure that \code{\link[dplyr:bind]{bind_rows}} diff --git a/man/sf_batch_status_bulk.Rd b/man/sf_batch_status_bulk.Rd index f6f48840..b4ecacf4 100644 --- a/man/sf_batch_status_bulk.Rd +++ b/man/sf_batch_status_bulk.Rd @@ -45,7 +45,7 @@ batch_query_info <- sf_submit_query_bulk(job_id = job_info$id, soql = soql) batch_status <- sf_batch_status_bulk(job_id = batch_query_info$jobId, batch_id = batch_query_info$id) job_close_ind <- sf_close_job_bulk(job_info$id) -sf_get_job_bulk(job_info$id) +sf_get_job_bulk(job_info$id) } } \references{ diff --git a/man/sf_control.Rd b/man/sf_control.Rd index 8a2c6b63..54fc4867 100644 --- a/man/sf_control.Rd +++ b/man/sf_control.Rd @@ -21,7 +21,8 @@ sf_control( "KeepSalesTeamGrantCurrentOwnerReadWriteAccess"), list(execute = FALSE, type = "SendEmail"), list(execute = FALSE, type = "TransferAllOwnedCases"), list(execute = TRUE, type = "TransferContacts"), list(execute = TRUE, type = "TransferContracts"), - list(execute = FALSE, type = "TransferNotesAndAttachments"), list(execute = + list(execute = FALSE, type = "TransferNotesAndAttachments"), + list(execute = TRUE, type = "TransferOpenActivities"), list(execute = TRUE, type = "TransferOrders"), list(execute = FALSE, type = "TransferOtherOpenOpportunities"), list(execute = FALSE, type = "TransferOwnedClosedOpportunities"), list(execute = diff --git a/man/sf_convert_lead.Rd b/man/sf_convert_lead.Rd index 73385b16..b78730e3 100644 --- a/man/sf_convert_lead.Rd +++ b/man/sf_convert_lead.Rd @@ -21,10 +21,11 @@ will be created, an email will be sent to the new owner, and other control optio \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{api_type}{\code{character}; one of \code{"REST"}, \code{"SOAP"}, \code{"Bulk 1.0"}, or \code{"Bulk 2.0"} indicating which API to use when diff --git a/man/sf_copy_report.Rd b/man/sf_copy_report.Rd index f8fee54d..ccb876d8 100644 --- a/man/sf_copy_report.Rd +++ b/man/sf_copy_report.Rd @@ -66,8 +66,8 @@ report_details <- sf_copy_report(this_report_id, "My New Copy of Report ABC") Other Report functions: \code{\link{sf_create_report}()}, \code{\link{sf_delete_report}()}, -\code{\link{sf_describe_report_type}()}, \code{\link{sf_describe_report}()}, +\code{\link{sf_describe_report_type}()}, \code{\link{sf_execute_report}()}, \code{\link{sf_list_report_fields}()}, \code{\link{sf_list_report_filter_operators}()}, diff --git a/man/sf_create.Rd b/man/sf_create.Rd index 5348ffa7..95bfcf6b 100644 --- a/man/sf_create.Rd +++ b/man/sf_create.Rd @@ -30,10 +30,11 @@ making the request.} \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{control}{\code{list}; a list of parameters for controlling the behavior of the API call being used. For more information of what parameters are available diff --git a/man/sf_create_batches_bulk.Rd b/man/sf_create_batches_bulk.Rd index 94898ffc..0ef5ed27 100644 --- a/man/sf_create_batches_bulk.Rd +++ b/man/sf_create_batches_bulk.Rd @@ -40,7 +40,7 @@ an already existing Bulk API Job by chunking into temp files } \examples{ \dontrun{ -# NOTE THAT YOU MUST FIRST CREATE AN EXTERNAL ID FIELD CALLED My_External_Id +# NOTE THAT YOU MUST FIRST CREATE AN EXTERNAL ID FIELD CALLED My_External_Id # BEFORE RUNNING THIS EXAMPLE # inserting 2 records my_data <- tibble(Name=c('New Record 1', 'New Record 2'), @@ -50,14 +50,14 @@ job_info <- sf_create_job_bulk(operation='insert', batches_ind <- sf_create_batches_bulk(job_id = job_info$id, input_data = my_data) # upserting 3 records -my_data2 <- tibble(My_External_Id__c=c('11111','22222', '99999'), - Name=c('Updated_Name1', 'Updated_Name2', 'Upserted_Record')) +my_data2 <- tibble(My_External_Id__c=c('11111','22222', '99999'), + Name=c('Updated_Name1', 'Updated_Name2', 'Upserted_Record')) job_info <- sf_create_job_bulk(operation='upsert', externalIdFieldName='My_External_Id__c', object='Account') batches_ind <- sf_create_batches_bulk(job_id = job_info$id, input_data = my_data2) -sf_get_job_bulk(job_info$id) +sf_get_job_bulk(job_info$id) } } \references{ diff --git a/man/sf_create_report.Rd b/man/sf_create_report.Rd index d756095c..93638f25 100644 --- a/man/sf_create_report.Rd +++ b/man/sf_create_report.Rd @@ -84,8 +84,8 @@ my_new_report <- sf_create_report(report_metadata=report_describe_list) Other Report functions: \code{\link{sf_copy_report}()}, \code{\link{sf_delete_report}()}, -\code{\link{sf_describe_report_type}()}, \code{\link{sf_describe_report}()}, +\code{\link{sf_describe_report_type}()}, \code{\link{sf_execute_report}()}, \code{\link{sf_list_report_fields}()}, \code{\link{sf_list_report_filter_operators}()}, diff --git a/man/sf_delete.Rd b/man/sf_delete.Rd index 3d64ba8d..c888dcfb 100644 --- a/man/sf_delete.Rd +++ b/man/sf_delete.Rd @@ -29,10 +29,11 @@ making the request.} \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{control}{\code{list}; a list of parameters for controlling the behavior of the API call being used. For more information of what parameters are available diff --git a/man/sf_delete_report.Rd b/man/sf_delete_report.Rd index aaa2e6e0..db594e3c 100644 --- a/man/sf_delete_report.Rd +++ b/man/sf_delete_report.Rd @@ -48,8 +48,8 @@ success <- sf_delete_report(this_report_id) Other Report functions: \code{\link{sf_copy_report}()}, \code{\link{sf_create_report}()}, -\code{\link{sf_describe_report_type}()}, \code{\link{sf_describe_report}()}, +\code{\link{sf_describe_report_type}()}, \code{\link{sf_execute_report}()}, \code{\link{sf_list_report_fields}()}, \code{\link{sf_list_report_filter_operators}()}, diff --git a/man/sf_execute_report.Rd b/man/sf_execute_report.Rd index 1aaa6ef6..9f01690b 100644 --- a/man/sf_execute_report.Rd +++ b/man/sf_execute_report.Rd @@ -39,10 +39,11 @@ may be \code{"Account B"} and the value \code{0016A0000035mJEQAY}. The former \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{bind_using_character_cols}{\code{logical}; an indicator of whether to cast the data to all character columns to ensure that \code{\link[dplyr:bind]{bind_rows}} @@ -170,8 +171,8 @@ Other Report functions: \code{\link{sf_copy_report}()}, \code{\link{sf_create_report}()}, \code{\link{sf_delete_report}()}, -\code{\link{sf_describe_report_type}()}, \code{\link{sf_describe_report}()}, +\code{\link{sf_describe_report_type}()}, \code{\link{sf_list_report_fields}()}, \code{\link{sf_list_report_filter_operators}()}, \code{\link{sf_list_report_types}()}, diff --git a/man/sf_find_duplicates.Rd b/man/sf_find_duplicates.Rd index fb62865d..54a19553 100644 --- a/man/sf_find_duplicates.Rd +++ b/man/sf_find_duplicates.Rd @@ -26,10 +26,11 @@ record IDs for records detected as duplicates by setting this property to \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{verbose}{\code{logical}; an indicator of whether to print additional detail for each API call, which is useful for debugging. More specifically, when diff --git a/man/sf_find_duplicates_by_id.Rd b/man/sf_find_duplicates_by_id.Rd index 6453eac6..408c6690 100644 --- a/man/sf_find_duplicates_by_id.Rd +++ b/man/sf_find_duplicates_by_id.Rd @@ -22,10 +22,11 @@ record IDs for records detected as duplicates by setting this property to \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{verbose}{\code{logical}; an indicator of whether to print additional detail for each API call, which is useful for debugging. More specifically, when diff --git a/man/sf_get_all_jobs_bulk.Rd b/man/sf_get_all_jobs_bulk.Rd index 60aba280..15dbe0ff 100644 --- a/man/sf_get_all_jobs_bulk.Rd +++ b/man/sf_get_all_jobs_bulk.Rd @@ -38,7 +38,7 @@ This function retrieves details about all Bulk jobs in the org. } \note{ parameterized_search_list elements that can be set to filter the results: -\itemize{ +\describe{ \item{isPkChunkingEnabled}{A logical either TRUE or FALSE. TRUE only returns information about jobs where PK Chunking has been enabled.} \item{jobType}{A character string to return jobs matching the specified type. diff --git a/man/sf_get_all_query_jobs_bulk.Rd b/man/sf_get_all_query_jobs_bulk.Rd index 19ef8751..9571fd03 100644 --- a/man/sf_get_all_query_jobs_bulk.Rd +++ b/man/sf_get_all_query_jobs_bulk.Rd @@ -39,7 +39,7 @@ This function retrieves details about all Bulk query jobs in the org. } \note{ parameterized_search_list elements that can be set to filter the results: -\itemize{ +\describe{ \item{isPkChunkingEnabled}{A logical either TRUE or FALSE. TRUE only returns information about jobs where PK Chunking has been enabled.} \item{jobType}{A character string to return jobs matching the specified type. diff --git a/man/sf_get_report_instance_results.Rd b/man/sf_get_report_instance_results.Rd index cc620578..44c5c6f0 100644 --- a/man/sf_get_report_instance_results.Rd +++ b/man/sf_get_report_instance_results.Rd @@ -31,10 +31,11 @@ may be \code{"Account B"} and the value \code{0016A0000035mJEQAY}. The former \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{bind_using_character_cols}{\code{logical}; an indicator of whether to cast the data to all character columns to ensure that \code{\link[dplyr:bind]{bind_rows}} diff --git a/man/sf_job_batches_bulk.Rd b/man/sf_job_batches_bulk.Rd index 8463011e..1af80c86 100644 --- a/man/sf_job_batches_bulk.Rd +++ b/man/sf_job_batches_bulk.Rd @@ -36,7 +36,7 @@ soql <- "SELECT Id, Name FROM Account LIMIT 10" batch_query_info <- sf_submit_query_bulk(job_id = job_info$id, soql = soql) submitted_batches <- sf_job_batches_bulk(job_id=batch_query_info$jobId) job_close_ind <- sf_close_job_bulk(job_info$id) -sf_get_job_bulk(job_info$id) +sf_get_job_bulk(job_info$id) } } \references{ diff --git a/man/sf_list_report_fields.Rd b/man/sf_list_report_fields.Rd index 111b0dc9..f206cb17 100644 --- a/man/sf_list_report_fields.Rd +++ b/man/sf_list_report_fields.Rd @@ -66,8 +66,8 @@ Other Report functions: \code{\link{sf_copy_report}()}, \code{\link{sf_create_report}()}, \code{\link{sf_delete_report}()}, -\code{\link{sf_describe_report_type}()}, \code{\link{sf_describe_report}()}, +\code{\link{sf_describe_report_type}()}, \code{\link{sf_execute_report}()}, \code{\link{sf_list_report_filter_operators}()}, \code{\link{sf_list_report_types}()}, diff --git a/man/sf_list_report_filter_operators.Rd b/man/sf_list_report_filter_operators.Rd index e8921f69..dd1de57d 100644 --- a/man/sf_list_report_filter_operators.Rd +++ b/man/sf_list_report_filter_operators.Rd @@ -48,8 +48,8 @@ Other Report functions: \code{\link{sf_copy_report}()}, \code{\link{sf_create_report}()}, \code{\link{sf_delete_report}()}, -\code{\link{sf_describe_report_type}()}, \code{\link{sf_describe_report}()}, +\code{\link{sf_describe_report_type}()}, \code{\link{sf_execute_report}()}, \code{\link{sf_list_report_fields}()}, \code{\link{sf_list_report_types}()}, diff --git a/man/sf_list_report_types.Rd b/man/sf_list_report_types.Rd index 1f0bf9d0..058c9a97 100644 --- a/man/sf_list_report_types.Rd +++ b/man/sf_list_report_types.Rd @@ -45,8 +45,8 @@ Other Report functions: \code{\link{sf_copy_report}()}, \code{\link{sf_create_report}()}, \code{\link{sf_delete_report}()}, -\code{\link{sf_describe_report_type}()}, \code{\link{sf_describe_report}()}, +\code{\link{sf_describe_report_type}()}, \code{\link{sf_execute_report}()}, \code{\link{sf_list_report_fields}()}, \code{\link{sf_list_report_filter_operators}()}, diff --git a/man/sf_list_reports.Rd b/man/sf_list_reports.Rd index 1d85a29e..f0484868 100644 --- a/man/sf_list_reports.Rd +++ b/man/sf_list_reports.Rd @@ -65,8 +65,8 @@ Other Report functions: \code{\link{sf_copy_report}()}, \code{\link{sf_create_report}()}, \code{\link{sf_delete_report}()}, -\code{\link{sf_describe_report_type}()}, \code{\link{sf_describe_report}()}, +\code{\link{sf_describe_report_type}()}, \code{\link{sf_execute_report}()}, \code{\link{sf_list_report_fields}()}, \code{\link{sf_list_report_filter_operators}()}, diff --git a/man/sf_query.Rd b/man/sf_query.Rd index ba8bb2f0..db447bb8 100644 --- a/man/sf_query.Rd +++ b/man/sf_query.Rd @@ -34,10 +34,11 @@ It is available in API versions 29.0 and later.} \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{api_type}{\code{character}; one of \code{"REST"}, \code{"SOAP"}, \code{"Bulk 1.0"}, or \code{"Bulk 2.0"} indicating which API to use when diff --git a/man/sf_query_bulk_v1.Rd b/man/sf_query_bulk_v1.Rd index 95773c2a..5cd43465 100644 --- a/man/sf_query_bulk_v1.Rd +++ b/man/sf_query_bulk_v1.Rd @@ -32,10 +32,11 @@ It is available in API versions 29.0 and later.} \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{bind_using_character_cols}{\code{logical}; an indicator of whether to cast the data to all character columns to ensure that \code{\link[dplyr:bind]{bind_rows}} diff --git a/man/sf_query_bulk_v2.Rd b/man/sf_query_bulk_v2.Rd index 885f1f46..909683ef 100644 --- a/man/sf_query_bulk_v2.Rd +++ b/man/sf_query_bulk_v2.Rd @@ -32,10 +32,11 @@ It is available in API versions 29.0 and later.} \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{bind_using_character_cols}{\code{logical}; an indicator of whether to cast the data to all character columns to ensure that \code{\link[dplyr:bind]{bind_rows}} diff --git a/man/sf_query_report.Rd b/man/sf_query_report.Rd index 2dbf7701..3383fcdf 100644 --- a/man/sf_query_report.Rd +++ b/man/sf_query_report.Rd @@ -68,8 +68,8 @@ Other Report functions: \code{\link{sf_copy_report}()}, \code{\link{sf_create_report}()}, \code{\link{sf_delete_report}()}, -\code{\link{sf_describe_report_type}()}, \code{\link{sf_describe_report}()}, +\code{\link{sf_describe_report_type}()}, \code{\link{sf_execute_report}()}, \code{\link{sf_list_report_fields}()}, \code{\link{sf_list_report_filter_operators}()}, diff --git a/man/sf_query_result_bulk.Rd b/man/sf_query_result_bulk.Rd index 5e14b313..99eeeeb0 100644 --- a/man/sf_query_result_bulk.Rd +++ b/man/sf_query_result_bulk.Rd @@ -28,10 +28,11 @@ get the recordset} \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{bind_using_character_cols}{\code{logical}; an indicator of whether to cast the data to all character columns to ensure that \code{\link[dplyr:bind]{bind_rows}} diff --git a/man/sf_query_result_bulk_v1.Rd b/man/sf_query_result_bulk_v1.Rd index d6f6d8eb..1417e4c6 100644 --- a/man/sf_query_result_bulk_v1.Rd +++ b/man/sf_query_result_bulk_v1.Rd @@ -27,10 +27,11 @@ get the recordset} \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{bind_using_character_cols}{\code{logical}; an indicator of whether to cast the data to all character columns to ensure that \code{\link[dplyr:bind]{bind_rows}} diff --git a/man/sf_query_result_bulk_v2.Rd b/man/sf_query_result_bulk_v2.Rd index 0ed5b9db..7dc6c0e8 100644 --- a/man/sf_query_result_bulk_v2.Rd +++ b/man/sf_query_result_bulk_v2.Rd @@ -20,10 +20,11 @@ returned by \link{sf_create_job_bulk}. It will start with \code{"750"}.} \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{bind_using_character_cols}{\code{logical}; an indicator of whether to cast the data to all character columns to ensure that \code{\link[dplyr:bind]{bind_rows}} diff --git a/man/sf_retrieve.Rd b/man/sf_retrieve.Rd index 6367c437..5f8dfbde 100644 --- a/man/sf_retrieve.Rd +++ b/man/sf_retrieve.Rd @@ -32,10 +32,11 @@ making the request.} \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{control}{\code{list}; a list of parameters for controlling the behavior of the API call being used. For more information of what parameters are available diff --git a/man/sf_run_bulk_operation.Rd b/man/sf_run_bulk_operation.Rd index 39194dcd..566fbe88 100644 --- a/man/sf_run_bulk_operation.Rd +++ b/man/sf_run_bulk_operation.Rd @@ -56,10 +56,11 @@ objects during upserts to determine if the record already exists in Salesforce o \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{api_type}{\code{character}; one of \code{"REST"}, \code{"SOAP"}, \code{"Bulk 1.0"}, or \code{"Bulk 2.0"} indicating which API to use when @@ -111,11 +112,11 @@ match the ordering of records in the original job data. \examples{ \dontrun{ n <- 20 -new_contacts <- tibble(FirstName = rep("Test", n), +new_contacts <- tibble(FirstName = rep("Test", n), LastName = paste0("Contact", 1:n)) # insert new records into the Contact object -inserts <- sf_bulk_operation(input_data = new_contacts, - object_name = "Contact", +inserts <- sf_bulk_operation(input_data = new_contacts, + object_name = "Contact", operation = "insert") } } diff --git a/man/sf_run_bulk_query.Rd b/man/sf_run_bulk_query.Rd index 0e99a7c4..3016eae7 100644 --- a/man/sf_run_bulk_query.Rd +++ b/man/sf_run_bulk_query.Rd @@ -47,10 +47,11 @@ It is available in API versions 29.0 and later.} \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{bind_using_character_cols}{\code{logical}; an indicator of whether to cast the data to all character columns to ensure that \code{\link[dplyr:bind]{bind_rows}} diff --git a/man/sf_run_report.Rd b/man/sf_run_report.Rd index 3bd0b44a..8ba9b8bd 100644 --- a/man/sf_run_report.Rd +++ b/man/sf_run_report.Rd @@ -68,10 +68,11 @@ async report has finished.} \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{bind_using_character_cols}{\code{logical}; an indicator of whether to cast the data to all character columns to ensure that \code{\link[dplyr:bind]{bind_rows}} @@ -184,8 +185,8 @@ Other Report functions: \code{\link{sf_copy_report}()}, \code{\link{sf_create_report}()}, \code{\link{sf_delete_report}()}, -\code{\link{sf_describe_report_type}()}, \code{\link{sf_describe_report}()}, +\code{\link{sf_describe_report_type}()}, \code{\link{sf_execute_report}()}, \code{\link{sf_list_report_fields}()}, \code{\link{sf_list_report_filter_operators}()}, diff --git a/man/sf_search.Rd b/man/sf_search.Rd index 4803a83d..ce0e2df8 100644 --- a/man/sf_search.Rd +++ b/man/sf_search.Rd @@ -23,10 +23,11 @@ to perform a search using SOSL.} \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{api_type}{\code{character}; one of \code{"REST"}, \code{"SOAP"}, \code{"Bulk 1.0"}, or \code{"Bulk 2.0"} indicating which API to use when diff --git a/man/sf_update.Rd b/man/sf_update.Rd index cc7f9d8d..bbe0a07f 100644 --- a/man/sf_update.Rd +++ b/man/sf_update.Rd @@ -30,10 +30,11 @@ making the request.} \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{control}{\code{list}; a list of parameters for controlling the behavior of the API call being used. For more information of what parameters are available diff --git a/man/sf_update_report.Rd b/man/sf_update_report.Rd index 2ae7751e..a9e1b429 100644 --- a/man/sf_update_report.Rd +++ b/man/sf_update_report.Rd @@ -73,8 +73,8 @@ Other Report functions: \code{\link{sf_copy_report}()}, \code{\link{sf_create_report}()}, \code{\link{sf_delete_report}()}, -\code{\link{sf_describe_report_type}()}, \code{\link{sf_describe_report}()}, +\code{\link{sf_describe_report_type}()}, \code{\link{sf_execute_report}()}, \code{\link{sf_list_report_fields}()}, \code{\link{sf_list_report_filter_operators}()}, diff --git a/man/sf_upsert.Rd b/man/sf_upsert.Rd index f48bbf54..e7dfbc74 100644 --- a/man/sf_upsert.Rd +++ b/man/sf_upsert.Rd @@ -35,10 +35,11 @@ making the request.} \item{guess_types}{\code{logical}; indicating whether or not to use \code{col_guess()} to try and cast the data returned in the recordset. If \code{TRUE} then -\code{col_guess()} is used, if \code{FALSE} then all fields will be returned -as character. This is helpful when \code{col_guess()} will mangle field values -in Salesforce that you'd like to preserve during translation into a \code{tbl_df}, -like numeric looking values that must be preserved as strings ("48.0").} +\code{col_guess()} is used along with \code{anytime()} and \code{anydate()}. +If \code{FALSE} then all fields will be returned as character. Specifying +\code{FALSE} helpful when guessing the column data type will result in NA +values and you would like to return the results as strings and then cast in +your script according to your unique specifications.} \item{control}{\code{list}; a list of parameters for controlling the behavior of the API call being used. For more information of what parameters are available diff --git a/man/valid_metadata_list.Rd b/man/valid_metadata_list.Rd index b4ff7162..73ddcb24 100644 --- a/man/valid_metadata_list.Rd +++ b/man/valid_metadata_list.Rd @@ -7,7 +7,7 @@ valid_metadata_list() } \value{ -code{list}; contains name and valid inputs for data types +\code{list}; contains name and valid inputs for data types } \description{ A list of data types that are valid for the Metadata API service. diff --git a/revdep/.gitignore b/revdep/.gitignore deleted file mode 100644 index d3ac4e16..00000000 --- a/revdep/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -checks -library -checks.noindex -library.noindex -data.sqlite -*.html -download -lib -cloud.noindex diff --git a/revdep/README.md b/revdep/README.md index 7c64b2fb..d9663e24 100644 --- a/revdep/README.md +++ b/revdep/README.md @@ -1,24 +1,25 @@ # Platform -|field |value | -|:--------|:----------------------------------------| -|version |R version 4.0.2 (2020-06-22) | -|os |OS X 12.2.1 | -|system |x86_64, darwin17.0 | -|ui |RStudio | -|language |(EN) | -|collate |en_US.UTF-8 | -|ctype |en_US.UTF-8 | -|tz |America/Chicago | -|date |2022-02-27 | -|rstudio |2021.09.1+372 Ghost Orchid (desktop) | -|pandoc |2.16.2 @ /usr/local/bin/ (via rmarkdown) | +|field |value | +|:--------|:-----------------------------------------------------------------------------------------------| +|version |R version 4.4.1 (2024-06-14) | +|os |macOS Monterey 12.7.6 | +|system |x86_64, darwin20 | +|ui |RStudio | +|language |(EN) | +|collate |en_US.UTF-8 | +|ctype |en_US.UTF-8 | +|tz |America/Chicago | +|date |2024-11-04 | +|rstudio |2024.09.0+375 Cranberry Hibiscus (desktop) | +|pandoc |3.2 @ /Applications/RStudio.app/Contents/Resources/app/quarto/bin/tools/x86_64/ (via rmarkdown) | # Dependencies -|package |old |new |Δ | -|:-----------|:-----|:-----|:--| -|salesforcer |1.0.0 |1.0.1 |* | +|package |old |new |Δ | +|:-----------|:-----|:----------|:--| +|salesforcer |1.0.1 |1.0.1.9999 |* | +|withr |NA |3.0.2 |* | # Revdeps diff --git a/revdep/checks.noindex/libraries.csv b/revdep/checks.noindex/libraries.csv new file mode 100644 index 00000000..384d9fc3 --- /dev/null +++ b/revdep/checks.noindex/libraries.csv @@ -0,0 +1,3 @@ +package,old,new,delta +salesforcer,1.0.1,1.0.1.9999,* +withr,NA,3.0.2,* diff --git a/revdep/data.sqlite b/revdep/data.sqlite new file mode 100644 index 00000000..9031ea2f Binary files /dev/null and b/revdep/data.sqlite differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/DESCRIPTION b/revdep/library.noindex/salesforcer/new/salesforcer/DESCRIPTION new file mode 100644 index 00000000..cabb18b6 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/salesforcer/DESCRIPTION @@ -0,0 +1,59 @@ +Package: salesforcer +Title: An Implementation of 'Salesforce' APIs Using Tidy Principles +Version: 1.0.1.9999 +Date: 2024-11-04 +Description: Functions connecting to the 'Salesforce' Platform APIs (REST, SOAP, + Bulk 1.0, Bulk 2.0, Metadata, Reports and Dashboards) + . + "API" is an acronym for "application programming interface". Most all calls + from these APIs are supported as they use CSV, XML or JSON data that can be + parsed into R data structures. For more details please see the 'Salesforce' + API documentation and this package's website + for more information, + documentation, and examples. +Authors@R: + c(person(given = c("Steven", "M."), + family = "Mortimer", + role = c("aut", "cre"), + email = "mortimer.steven.m@gmail.com"), + person(given = "Takekatsu", + family = "Hiramura", + role = "ctb", + email = "thira@plavox.info"), + person(given = "Jennifer", + family = "Bryan", + role = c("ctb", "cph"), + email = "jenny@rstudio.com"), + person(given = "Joanna", + family = "Zhao", + role = c("ctb", "cph"), + email = "joanna.zhao@alumni.ubc.ca")) +License: MIT + file LICENSE +URL: https://github.com/StevenMMortimer/salesforcer +BugReports: https://github.com/StevenMMortimer/salesforcer/issues +Depends: R (>= 3.6.0) +Imports: methods (>= 3.6.0), utils (>= 3.6.0), stats (>= 3.6.0), dplyr + (>= 1.0.0), purrr (>= 0.3.4), vctrs (>= 0.3.4), tibble (>= + 3.0.3), readr (>= 1.3.1), lubridate (>= 1.7.8), anytime (>= + 0.3.9), rlang (>= 0.4.7), httr (>= 1.4.1), curl (>= 4.3), + data.table (>= 1.13.0), XML (>= 3.99-0.3), xml2 (>= 1.3.2), + jsonlite (>= 1.6.1), rlist (>= 0.4.6.1), zip (>= 2.0.4), + base64enc (>= 0.1-3), mime (>= 0.9), lifecycle (>= 0.2.0) +Suggests: knitr, rmarkdown, testthat, spelling, here, microbenchmark, + ggplot2, sessioninfo +VignetteBuilder: knitr +ByteCompile: true +Encoding: UTF-8 +Language: en-US +Roxygen: list(markdown = TRUE) +RoxygenNote: 7.3.2 +RemoteType: local +RemoteUrl: /Users/steven.mortimer/github/salesforcer +NeedsCompilation: no +Packaged: 2024-11-04 19:29:42 UTC; steven.mortimer +Author: Steven M. Mortimer [aut, cre], + Takekatsu Hiramura [ctb], + Jennifer Bryan [ctb, cph], + Joanna Zhao [ctb, cph] +Maintainer: Steven M. Mortimer +Built: R 4.4.1; ; 2024-11-04 19:29:44 UTC; unix diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/INDEX b/revdep/library.noindex/salesforcer/new/salesforcer/INDEX new file mode 100644 index 00000000..58cb50c9 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/salesforcer/INDEX @@ -0,0 +1,191 @@ +collapse_list_with_dupe_names + Collapse Elements in List with Same Name +metadata_type_validator + Metadata Data Type Validator +parameterized_search_control + Auxiliary for Controlling Parametrized Searches +rforcecom.bulkAction The 'salesforcer' backwards compatible version + of the RForcecom function + 'rforcecom.bulkAction' +rforcecom.bulkQuery The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.bulkQuery' +rforcecom.create The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.create' +rforcecom.delete The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.delete' +rforcecom.getObjectDescription + The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.getObjectDescription' +rforcecom.getServerTimestamp + The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.getServerTimestamp' +rforcecom.login The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.login' +rforcecom.query The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.query' +rforcecom.retrieve The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.retrieve' +rforcecom.search The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.search' +rforcecom.update The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.update' +rforcecom.upsert The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.upsert' +sf_abort_job_bulk Abort Bulk API Job +sf_analytics_notification_create + Create an analytics notification +sf_analytics_notification_delete + Delete an analytics notification +sf_analytics_notification_describe + Describe an analytics notification +sf_analytics_notification_update + Update an analytics notification +sf_analytics_notifications_limits + Return limits of analytics notifications +sf_analytics_notifications_list + List analytics notifications +sf_auth Log in to Salesforce +sf_batch_details_bulk Returning the Details of a Batch in a Bulk API + Job +sf_batch_status_bulk Checking the Status of a Batch in a Bulk API + Job +sf_close_job_bulk Close Bulk API Job +sf_control Auxiliary for Controlling Calls to Salesforce + APIs +sf_convert_lead Convert Leads +sf_copy_dashboard Copy a dashboard +sf_copy_report Copy a report +sf_create Create Records +sf_create_attachment Create Attachments +sf_create_batches_bulk + Add Batches to a Bulk API Job +sf_create_job_bulk Create Bulk API Job +sf_create_metadata Create Object or Field Metadata in Salesforce +sf_create_report Create a report +sf_delete Delete Records +sf_delete_attachment Delete Attachments +sf_delete_dashboard Delete a dashboard +sf_delete_job_bulk Delete Bulk API Job +sf_delete_metadata Delete Object or Field Metadata in Salesforce +sf_delete_report Delete a report +sf_delete_report_instance + Delete a report instance +sf_describe_dashboard Describe a dashboard +sf_describe_dashboard_components + Describe dashboard components +sf_describe_metadata Describe the Metadata in an Organization +sf_describe_object_fields + Describe Object Fields +sf_describe_objects SObject Basic Information +sf_describe_report Describe a report +sf_describe_report_type + Describe a report type +sf_download_attachment + Download an Attachment +sf_empty_recycle_bin Empty Recycle Bin +sf_execute_report Execute a report +sf_filter_dashboard_operators_list + List dashboard filter operators +sf_filter_dashboard_options_analysis + Get an analysis of the filter options for a + dashboard +sf_find_duplicates Find Duplicate Records +sf_find_duplicates_by_id + Find Duplicate Records By Id +sf_get_all_jobs_bulk Get All Bulk API Jobs +sf_get_all_query_jobs_bulk + Get All Bulk API Query Jobs +sf_get_dashboard_data Get dashboard data in a tabular format +sf_get_dashboard_results + Get the results of an existing dashboard +sf_get_dashboard_status + Get the status of a dashboard +sf_get_deleted Get Deleted Records from a Timeframe +sf_get_job_bulk Get Bulk API Job +sf_get_job_records_bulk + Returning the Details of a Bulk API Job +sf_get_report_instance_results + Get report instance results +sf_get_updated Get Updated Records from a Timeframe +sf_job_batches_bulk Checking the Status of a Batch in a Bulk API + Job +sf_list_api_limits List the Limits for an API +sf_list_dashboards List dashboards +sf_list_metadata List All Objects of a Certain Metadata Type in + Salesforce +sf_list_objects List Organization Objects and their Metadata +sf_list_report_fields Get a list of report fields +sf_list_report_filter_operators + List report filter operators +sf_list_report_instances + List report instances +sf_list_report_types List report types +sf_list_reports List reports +sf_list_resources List the Resources for an API +sf_list_rest_api_versions + List REST API Versions +sf_merge Merge Records +sf_query Perform SOQL Query +sf_query_bulk_v1 Run Bulk 1.0 query +sf_query_bulk_v2 Run Bulk 2.0 query +sf_query_report Get Report Data without Saving Changes to or + Creating a Report +sf_query_result_bulk Retrieve the results of a completed bulk query +sf_query_result_bulk_v1 + Retrieve the results of a Bulk 1.0 query +sf_query_result_bulk_v2 + Retrieve the results of a Bulk 2.0 query +sf_read_metadata Read Object or Field Metadata from Salesforce +sf_refresh_dashboard Refresh an existing dashboard +sf_rename_metadata Rename Metadata Elements in Salesforce +sf_report_folder_children + Get the subfolders (children) of a report + folder +sf_report_folder_create + Create report folder +sf_report_folder_delete + Delete a report folder +sf_report_folder_describe + Describe a report folder +sf_report_folder_share_delete + Delete a report folder share +sf_report_folder_share_describe + Describe a report folder share +sf_report_folder_share_recipients + Get report folder share recipients +sf_report_folder_share_update + Update a report folder share +sf_report_folder_shares_add + Add shares to a report folder +sf_report_folder_shares_list + List the shares in a report folder +sf_report_folder_shares_update + Update the shares for a report folder +sf_report_folder_update + Update a report folder +sf_report_folders_list + List report folders +sf_reset_password Reset User Password +sf_retrieve Retrieve Records By Id +sf_retrieve_metadata Make A Request to Retrieve the Metadata +sf_run_bulk_operation Run Bulk Operation +sf_run_bulk_query Run bulk query +sf_run_report Get a report's data in tabular format +sf_search Perform SOSL Search +sf_server_timestamp Salesforce Server Timestamp +sf_set_dashboard_sticky_filter + Set a sticky dashboard filter +sf_set_password Set User Password +sf_submit_query_bulk Submit Bulk Query Batch to a Bulk API Job +sf_undelete Undelete Records +sf_update Update Records +sf_update_attachment Update Attachments +sf_update_dashboard Update a dashboard +sf_update_metadata Update Object or Field Metadata in Salesforce +sf_update_report Update a report +sf_upload_complete_bulk + Signal Upload Complete to Bulk API Job +sf_upsert Upsert Records +sf_upsert_metadata Upsert Object or Field Metadata in Salesforce +sf_user_info Return Current User Info +valid_metadata_list List of Valid Data Types diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/LICENSE b/revdep/library.noindex/salesforcer/new/salesforcer/LICENSE new file mode 100644 index 00000000..2b970cb5 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/salesforcer/LICENSE @@ -0,0 +1,2 @@ +YEAR: 2018-2020 +COPYRIGHT HOLDER: Steven M. Mortimer diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/Meta/Rd.rds b/revdep/library.noindex/salesforcer/new/salesforcer/Meta/Rd.rds new file mode 100644 index 00000000..9f127829 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/Meta/Rd.rds differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/Meta/features.rds b/revdep/library.noindex/salesforcer/new/salesforcer/Meta/features.rds new file mode 100644 index 00000000..781f60d4 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/Meta/features.rds differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/Meta/hsearch.rds b/revdep/library.noindex/salesforcer/new/salesforcer/Meta/hsearch.rds new file mode 100644 index 00000000..16865efa Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/Meta/hsearch.rds differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/Meta/links.rds b/revdep/library.noindex/salesforcer/new/salesforcer/Meta/links.rds new file mode 100644 index 00000000..c414c734 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/Meta/links.rds differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/Meta/nsInfo.rds b/revdep/library.noindex/salesforcer/new/salesforcer/Meta/nsInfo.rds new file mode 100644 index 00000000..55c86702 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/Meta/nsInfo.rds differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/Meta/package.rds b/revdep/library.noindex/salesforcer/new/salesforcer/Meta/package.rds new file mode 100644 index 00000000..00ae7825 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/Meta/package.rds differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/NAMESPACE b/revdep/library.noindex/salesforcer/new/salesforcer/NAMESPACE new file mode 100644 index 00000000..07f204d4 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/salesforcer/NAMESPACE @@ -0,0 +1,404 @@ +# Generated by roxygen2: do not edit by hand + +S3method(sf_format_time,"NULL") +S3method(sf_format_time,AsIs) +S3method(sf_format_time,Date) +S3method(sf_format_time,POSIXct) +S3method(sf_format_time,POSIXlt) +S3method(sf_format_time,POSIXt) +S3method(sf_format_time,character) +S3method(sf_format_time,data.frame) +S3method(sf_format_time,list) +S3method(sf_format_time,logical) +S3method(sf_format_time,numeric) +export(VERB_n) +export(accepted_controls_by_api) +export(accepted_controls_by_operation) +export(bind_query_resultsets) +export(build_manifest_xml_from_list) +export(build_metadata_xml_from_list) +export(build_proxy) +export(build_soap_xml_from_list) +export(catch_errors) +export(catch_unknown_api) +export(check_and_encode_files) +export(collapse_list_with_dupe_names) +export(combine_parent_and_child_resultsets) +export(compact2) +export(drop_attributes) +export(drop_attributes_recursively) +export(drop_empty_recursively) +export(drop_nested_child_records) +export(extract_nested_child_records) +export(extract_records_from_xml_node) +export(extract_records_from_xml_nodeset) +export(extract_records_from_xml_nodeset_of_records) +export(filter_valid_controls) +export(flatten_tbl_df) +export(format_headers_for_verbose) +export(format_report_row) +export(get_os) +export(guess_object_name_from_soql) +export(is_legit_token) +export(list_extract_parent_and_child_result) +export(make_analytics_folder_child_operations_url) +export(make_analytics_folder_collections_url) +export(make_analytics_folder_operations_url) +export(make_analytics_folder_share_by_id_url) +export(make_analytics_folder_share_recipients_url) +export(make_analytics_folder_shares_url) +export(make_analytics_notification_operations_url) +export(make_analytics_notifications_limits_url) +export(make_analytics_notifications_list_url) +export(make_base_metadata_url) +export(make_base_rest_url) +export(make_base_soap_url) +export(make_bulk_batch_details_url) +export(make_bulk_batch_status_url) +export(make_bulk_batches_url) +export(make_bulk_create_job_url) +export(make_bulk_delete_job_url) +export(make_bulk_end_job_generic_url) +export(make_bulk_get_all_jobs_url) +export(make_bulk_get_all_query_jobs_url) +export(make_bulk_get_job_url) +export(make_bulk_job_records_url) +export(make_bulk_query_result_url) +export(make_bulk_query_url) +export(make_chatter_users_url) +export(make_composite_batch_url) +export(make_composite_url) +export(make_dashboard_copy_url) +export(make_dashboard_describe_url) +export(make_dashboard_filter_operators_list_url) +export(make_dashboard_filter_options_analysis_url) +export(make_dashboard_status_url) +export(make_dashboard_url) +export(make_dashboards_list_url) +export(make_login_url) +export(make_parameterized_search_url) +export(make_query_url) +export(make_report_copy_url) +export(make_report_create_url) +export(make_report_describe_url) +export(make_report_execute_url) +export(make_report_fields_url) +export(make_report_filter_operators_list_url) +export(make_report_instance_url) +export(make_report_instances_list_url) +export(make_report_query_url) +export(make_report_type_describe_url) +export(make_report_types_list_url) +export(make_report_url) +export(make_reports_list_url) +export(make_rest_describe_url) +export(make_rest_objects_url) +export(make_rest_record_url) +export(make_search_url) +export(make_soap_xml_skeleton) +export(make_verbose_httr_message) +export(map_sf_type_to_r_type) +export(merge_null_to_na) +export(message_w_errors_listed) +export(metadata_type_validator) +export(parameterized_search_control) +export(parse_error_code_and_message) +export(parse_report_detail_rows) +export(patched_tempdir) +export(rDELETE) +export(rGET) +export(rPATCH) +export(rPOST) +export(rPUT) +export(records_list_to_tbl) +export(remove_empty_linked_object_cols) +export(return_matching_controls) +export(rforcecom.bulkAction) +export(rforcecom.bulkQuery) +export(rforcecom.create) +export(rforcecom.delete) +export(rforcecom.getObjectDescription) +export(rforcecom.getServerTimestamp) +export(rforcecom.login) +export(rforcecom.query) +export(rforcecom.retrieve) +export(rforcecom.search) +export(rforcecom.update) +export(rforcecom.upsert) +export(safe_bind_rows) +export(salesforcer_state) +export(session_id_available) +export(set_null_elements_to_na) +export(set_null_elements_to_na_recursively) +export(sf_abort_job_bulk) +export(sf_access_token) +export(sf_analytics_notification_create) +export(sf_analytics_notification_delete) +export(sf_analytics_notification_describe) +export(sf_analytics_notification_update) +export(sf_analytics_notifications_limits) +export(sf_analytics_notifications_list) +export(sf_auth) +export(sf_auth_check) +export(sf_auth_refresh) +export(sf_batch_details_bulk) +export(sf_batch_status_bulk) +export(sf_build_cols_spec) +export(sf_bulk_operation) +export(sf_close_job_bulk) +export(sf_control) +export(sf_convert_lead) +export(sf_copy_dashboard) +export(sf_copy_report) +export(sf_create) +export(sf_create_attachment) +export(sf_create_batches_bulk) +export(sf_create_job_bulk) +export(sf_create_job_bulk_v1) +export(sf_create_job_bulk_v2) +export(sf_create_metadata) +export(sf_create_report) +export(sf_delete) +export(sf_delete_attachment) +export(sf_delete_dashboard) +export(sf_delete_job_bulk) +export(sf_delete_metadata) +export(sf_delete_report) +export(sf_delete_report_instance) +export(sf_describe_dashboard) +export(sf_describe_dashboard_components) +export(sf_describe_metadata) +export(sf_describe_object_fields) +export(sf_describe_objects) +export(sf_describe_report) +export(sf_describe_report_type) +export(sf_download_attachment) +export(sf_empty_recycle_bin) +export(sf_end_job_bulk) +export(sf_execute_report) +export(sf_filter_dashboard_operators_list) +export(sf_filter_dashboard_options_analysis) +export(sf_find_duplicates) +export(sf_find_duplicates_by_id) +export(sf_format_date) +export(sf_format_datetime) +export(sf_format_time) +export(sf_get_all_jobs_bulk) +export(sf_get_all_query_jobs_bulk) +export(sf_get_dashboard_data) +export(sf_get_dashboard_results) +export(sf_get_dashboard_status) +export(sf_get_deleted) +export(sf_get_job_bulk) +export(sf_get_job_records_bulk) +export(sf_get_report_instance_results) +export(sf_get_updated) +export(sf_guess_cols) +export(sf_input_data_validation) +export(sf_job_batches_bulk) +export(sf_list_api_limits) +export(sf_list_dashboards) +export(sf_list_metadata) +export(sf_list_objects) +export(sf_list_report_fields) +export(sf_list_report_filter_operators) +export(sf_list_report_instances) +export(sf_list_report_types) +export(sf_list_reports) +export(sf_list_resources) +export(sf_list_rest_api_versions) +export(sf_merge) +export(sf_query) +export(sf_query_bulk) +export(sf_query_bulk_v1) +export(sf_query_bulk_v2) +export(sf_query_report) +export(sf_query_result_bulk) +export(sf_query_result_bulk_v1) +export(sf_query_result_bulk_v2) +export(sf_read_metadata) +export(sf_refresh_dashboard) +export(sf_rename_metadata) +export(sf_reorder_cols) +export(sf_report_folder_children) +export(sf_report_folder_create) +export(sf_report_folder_delete) +export(sf_report_folder_describe) +export(sf_report_folder_share_delete) +export(sf_report_folder_share_describe) +export(sf_report_folder_share_recipients) +export(sf_report_folder_share_update) +export(sf_report_folder_shares_add) +export(sf_report_folder_shares_list) +export(sf_report_folder_shares_update) +export(sf_report_folder_update) +export(sf_report_folders_list) +export(sf_reset_password) +export(sf_rest_list) +export(sf_retrieve) +export(sf_retrieve_metadata) +export(sf_retrieve_metadata_check_status) +export(sf_run_bulk_operation) +export(sf_run_bulk_query) +export(sf_run_report) +export(sf_search) +export(sf_server_timestamp) +export(sf_session_id) +export(sf_set_dashboard_sticky_filter) +export(sf_set_password) +export(sf_submit_query_bulk) +export(sf_undelete) +export(sf_update) +export(sf_update_attachment) +export(sf_update_dashboard) +export(sf_update_metadata) +export(sf_update_report) +export(sf_upload_complete_bulk) +export(sf_upsert) +export(sf_upsert_metadata) +export(sf_user_info) +export(sf_write_csv) +export(simplify_report_metadata) +export(stop_w_errors_listed) +export(token_available) +export(unbox_list_elements) +export(unbox_list_elements_recursively) +export(unnest_col) +export(valid_metadata_list) +export(validate_get_all_jobs_params) +export(warn_w_errors_listed) +export(xmlToList2) +export(xml_drop_and_unlist) +export(xml_drop_and_unlist_recursively) +export(xml_extract_parent_and_child_result) +export(xml_nodeset_to_df) +importFrom(XML,"xmlValue<-") +importFrom(XML,addChildren) +importFrom(XML,newXMLNode) +importFrom(XML,saveXML) +importFrom(XML,xmlApply) +importFrom(XML,xmlAttrs) +importFrom(XML,xmlChildren) +importFrom(XML,xmlDoc) +importFrom(XML,xmlInternalTreeParse) +importFrom(XML,xmlParse) +importFrom(XML,xmlRoot) +importFrom(XML,xmlSApply) +importFrom(XML,xmlSize) +importFrom(XML,xmlToList) +importFrom(XML,xmlValue) +importFrom(anytime,anydate) +importFrom(anytime,anytime) +importFrom(base64enc,base64encode) +importFrom(curl,form_data) +importFrom(curl,form_file) +importFrom(data.table,rbindlist) +importFrom(dplyr,"%>%") +importFrom(dplyr,across) +importFrom(dplyr,all_of) +importFrom(dplyr,any_of) +importFrom(dplyr,as_tibble) +importFrom(dplyr,bind_cols) +importFrom(dplyr,bind_rows) +importFrom(dplyr,contains) +importFrom(dplyr,everything) +importFrom(dplyr,expr) +importFrom(dplyr,filter) +importFrom(dplyr,if_all) +importFrom(dplyr,is.tbl) +importFrom(dplyr,matches) +importFrom(dplyr,mutate) +importFrom(dplyr,mutate_all) +importFrom(dplyr,mutate_if) +importFrom(dplyr,one_of) +importFrom(dplyr,rename) +importFrom(dplyr,rename_at) +importFrom(dplyr,rename_with) +importFrom(dplyr,select) +importFrom(dplyr,tibble) +importFrom(httr,DELETE) +importFrom(httr,GET) +importFrom(httr,PATCH) +importFrom(httr,POST) +importFrom(httr,PUT) +importFrom(httr,RETRY) +importFrom(httr,add_headers) +importFrom(httr,build_url) +importFrom(httr,config) +importFrom(httr,content) +importFrom(httr,headers) +importFrom(httr,http_error) +importFrom(httr,oauth2.0_token) +importFrom(httr,oauth_app) +importFrom(httr,oauth_endpoint) +importFrom(httr,parse_url) +importFrom(httr,status_code) +importFrom(httr,upload_file) +importFrom(httr,use_proxy) +importFrom(jsonlite,base64_dec) +importFrom(jsonlite,fromJSON) +importFrom(jsonlite,prettify) +importFrom(jsonlite,toJSON) +importFrom(lifecycle,deprecate_soft) +importFrom(lifecycle,deprecate_warn) +importFrom(lifecycle,deprecated) +importFrom(lifecycle,is_present) +importFrom(lubridate,as_datetime) +importFrom(lubridate,dmy_hms) +importFrom(lubridate,is.Date) +importFrom(lubridate,is.POSIXct) +importFrom(lubridate,is.POSIXlt) +importFrom(lubridate,is.POSIXt) +importFrom(methods,as) +importFrom(mime,guess_type) +importFrom(purrr,as_mapper) +importFrom(purrr,compact) +importFrom(purrr,discard) +importFrom(purrr,list_modify) +importFrom(purrr,map) +importFrom(purrr,map_chr) +importFrom(purrr,map_depth) +importFrom(purrr,map_df) +importFrom(purrr,map_dfc) +importFrom(purrr,map_if) +importFrom(purrr,map_lgl) +importFrom(purrr,modify) +importFrom(purrr,modify_at) +importFrom(purrr,modify_if) +importFrom(purrr,pluck) +importFrom(purrr,set_names) +importFrom(purrr,transpose) +importFrom(readr,col_character) +importFrom(readr,col_guess) +importFrom(readr,cols) +importFrom(readr,locale) +importFrom(readr,parse_datetime) +importFrom(readr,read_csv) +importFrom(readr,type_convert) +importFrom(readr,write_csv) +importFrom(rlang,is_empty) +importFrom(rlist,list.flatten) +importFrom(stats,quantile) +importFrom(stats,runif) +importFrom(stats,setNames) +importFrom(tibble,as_tibble_row) +importFrom(tools,file_ext) +importFrom(utils,capture.output) +importFrom(utils,head) +importFrom(utils,object.size) +importFrom(utils,tail) +importFrom(vctrs,vec_as_names) +importFrom(xml2,as_list) +importFrom(xml2,read_xml) +importFrom(xml2,url_escape) +importFrom(xml2,xml_add_child) +importFrom(xml2,xml_add_sibling) +importFrom(xml2,xml_child) +importFrom(xml2,xml_find_all) +importFrom(xml2,xml_find_first) +importFrom(xml2,xml_new_document) +importFrom(xml2,xml_ns_strip) +importFrom(xml2,xml_remove) +importFrom(xml2,xml_set_namespace) +importFrom(xml2,xml_text) +importFrom(zip,zipr) diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/NEWS.md b/revdep/library.noindex/salesforcer/new/salesforcer/NEWS.md new file mode 100644 index 00000000..9459020e --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/salesforcer/NEWS.md @@ -0,0 +1,464 @@ +# salesforcer 1.0.1.9999 + +## Dependencies + + * Increment the package's default Salesforce API version to 61.0 (Summer '24). + + * Remove deprecation warning for basic authentication (password and + security token) because many users have found that it's still possible to + use for programmatic (API-based) access even if their org requires users to + log in via multi-factor authentication. (#128) + +## Features + + * Add two new datetime formats that will automatically be parsed if they appear + in the query recordset `"%m-%d-%Y %H:%M"` and `"%d-%m-%Y %H:%M"`. (#127) + +## Bug fixes + + * Fix bug that caused Bulk 1.0 queries using the PKChunking option to error + out because the query info returned a vector of IDs instead of one which was + expected by the `sf_batch_status_bulk()` function. (#124) + + * Explicitly specify the column name repair method for all `as_tibble()` and + `as_tibble_row()` function calls because this could be causing issues when + parsing and binding query recordsets. (#124) + +--- + +# salesforcer 1.0.1 [release](https://github.com/StevenMMortimer/salesforcer/releases/tag/v1.0.1) + +## Dependencies + + * Increase the package's default Salesforce API version to 54.0 (Spring '22) + * Added a deprecation warning that using basic authentication (password and + security token) will no longer work since Salesforce announced that all + customers will be migrated to MFA beginning February 1st, 2022 + ([link](https://admin.salesforce.com/blog/2021/everything-admins-need-to-know-about-the-mfa-requirement)). Many thanks to @klaw2 for highlighting in #113. + * Remove deprecated use of `dplyr::across()` and add logic to circumvent a + new warning emitted by `readr::type_convert()` when no character columns + are present + +## Bug fixes + + * Changed the naming convention for dashboard-related functions to contain the + action verb first (e.g., `sf_copy_dashboard` instead of `sf_dashboard_copy`) + +--- + +# salesforcer 1.0.0 [release](https://github.com/StevenMMortimer/salesforcer/releases/tag/v1.0.0) + +## Dependencies + + * Increase the package's default Salesforce API version to 52.0 (Summer '21). + + * Remove uses of {RForcecom} after it was archived on CRAN on 6/8/2021 (#101) + + * Remove LazyData option in DESCRIPTION since `data()` is not utilized + + * Deprecate argument in `sf_write_csv()` from `path` to `file` as was done in + {readr} v1.4.0. + + * Deprecate argument `bind_using_character_cols` because we will always need + to bind as character and then parse if `guess_types=TRUE`. Per comments in + tidyverse/readr#588 and tidyverse/readr#98, we must read all of the data as + character first and then use `type_convert()` to ensure that we use all values + in the column to guess the type. The default for `read_csv()` is to only use + the first 1,000 rows and its `guess_max` argument cannot be set to `Inf`. + + * Change lifecycle status from "Maturing" to "Status" per the retirement of + "Maturing" in the {lifecycle} package. The documentation notes: + + > Previously we used as maturing for functions that lay somewhere between experimental and stable. We stopped using this stage because, like questioning, it’s not clear what actionable information this stage delivers. + + In addition, the lifecycle guidance states that experimental packages have + version numbers less than 1.0.0 and may have major changes in its future. + The {salesforcer} package has achieved a stable state with core + functionality implemented and a focus on backwards compatibility due to the + volume of users. + +## Features + + * Improve documentation to retrieve the access token or session ID after + authentication (#97) + + * Improve parsing of Bulk API query recordsets from CSV where all values + in the column will be used to guess the type instead of the first 1000. + +## Bug fixes + + * Generalize the date and datetime parsing mechanism, such that, reports with + date and datetime fields are not returned as NA (#93) + + * Fix the format of the `OwnerChangeOptions` header so it is accepted (#94) + + * Fix bug that caused Bulk 2.0 calls to crash when the results had datetime + fields in the recordset (#95) + +--- + +# salesforcer 0.2.2 [release](https://github.com/StevenMMortimer/salesforcer/releases/tag/v0.2.2) + +## Dependencies + + * This release relaxes the dependency on {dplyr} and brings back use of + `rbindlist()` from {data.table} because of limitations of `dplyr::bind_rows()`. + As noted in (tidyverse/dplyr#5429) {dplyr} will only support binding data.frames + or lists of data.frames, **not** a list of lists which is needed in some + applications of the {salesforcer} package. + * Due to other recent changes between {vctrs} and {dplyr}, you may now see the + following warning displayed when loading {salesforcer}, which is emitted by the + loading of {dplyr}: + + ```r + Warning: replacing previous import 'vctrs::data_frame' by 'tibble::data_frame' when loading 'dplyr' + ``` + +## Features + + * None + + +## Bug fixes + + * None + +# salesforcer 0.2.1 [release](https://github.com/StevenMMortimer/salesforcer/releases/tag/v0.2.1) + +## Dependencies + + * **CAUTION: This release requires {dplyr 1.0.0} because {dplyr 1.0.1} introduced + a bug in `bind_rows()` with how it binds lists where the list elements have differing + lengths. This is documented in tidyverse/dplyr#5417 and r-lib/vctrs#1073. The + timeline for a fix is unknown as of Aug 16, 2020.** You can install the older + version of {dplyr} using the following command: + + ```r + remotes::install_version("dplyr", "1.0.0") + ``` + +## Features + + * Add support for the `defaultLimit` argument in `sf_search()` to be able to + restrict the number of records from each individual object when searching + across one or more objects. + * Add support for updating attachments with the `sf_update_attachments()` + function (#79). + * Add support for downloading attachments just by its Id. In addition, the + `sf_download_attachment()` function returns the file path of the downloaded + content instead of a logical indicating success. + +## Bug fixes + + * Fix bug introduced in {salesforcer 0.2.0} which could not stack records with + errors longer than length 1. The new solution is to always return the `errors` + column as a list, which is coerced to length 1 for the record (#66). + * Fix bug in `sf_search()` that was passing `"true"/"false"` instead of actual + boolean value for the `spellCorrection` parameter in the POST body. + +--- + +# salesforcer 0.2.0 [release](https://github.com/StevenMMortimer/salesforcer/releases/tag/v0.2.0) + +## Dependencies + + * **CAUTION: This release only has automated test coverage on R 4.0.0 or greater. + Users should still be able to install and run using R (>= 3.6.0). However, it + is recommended to upgrade to R 4.0.0 or greater.** + +## Features + + * Add experimental support for the Reports and Dashboards REST API. + + * Add support for Bulk 2.0 queries that was added in Salesforce version 47.0 + (Winter '20). **CAUTION: The Bulk 2.0 API is now the default API when using + `sf_query_bulk()` or `sf_run_bulk_query()`**. Please test prior to upgrading + in a production environment where you are running bulk queries. + + * Standardize the column order and format of query and CRUD operations that + prioritizes the object type and Ids over other fields and finaly relationship + fields. **CAUTION: This will switch up the order of the columns returned by + your existing code**. Please test prior to upgrading in a production environment + where column ordering is a breaking change. For example we prioritize the following + fields in queries alphabetically within this prioritization waterfall: + + 1. The `sObject` field first (indicates the record's object if multiple objects returned in the results) + 2. The Id field second (`Id`, `id`, `sf__Id`) + 3. Salesforce record success status (`Success`, `success`, `sf_Success`) + 4. Salesforce record created status (`Created`, `created`, `sf__Created`) + 5. Salesforce record error(s) status (`Error`, `error`, `errors`, + `errors.statusCode`, `errors.fields`, `errors.message`, `sf__Error`) + 6. All other fields from the target object (e.g. `Name`, `Phone`, etc.) + 7. Relationship fields (fields from a parent or child of the target). For example, + anything typically containing a dot like `Account.Id`, `Owner.Name`, etc. + + * Standardize the names of functions that submit long running jobs to Salesforce. + These functions now all start with `sf_run_*`. However, the original names have + been aliased to the new names so this version will acknowledge the old function + names without deprecation warning.For example, the new names are: + + * `sf_query_bulk()` ==> `sf_run_bulk_query()` + * `sf_bulk_operation()` ==> `sf_run_bulk_operation()` + * `sf_run_report()` + + * Add support for logging in with a proxy without having to use OAuth 2.0 as + the authentication method. When proxy support was first implemented in + {salesforcer} 0.1.4, it only supported proxy connections when logging in via + OAuth 2.0. Now, this untested version of proxy support for basic + authentication has been implemented. This means that proxy users should be + able to login using just a username, password, and security token if their + organization has not implemented OAuth 2.0 or if they do not want to use OAuth + 2.0 while logging in via this package. + + * Add lifecycle badges to signal maturity of different package aspects. + + * Add two vignettes, one that outlines the query types supported by the package + and another that outlines the new report functionality that was introduced in + this release. + + * Add enhanced query test coverage in its own test script. + + * Remove dependency on {data.table} which does not have a build for R-devel. This + should only affect `sf_read_metadata()`. + + +## Bug Fixes + + * Fix bug that prevented enabling PKChunking in Bulk 1.0 queries. Users can + now specify using `TRUE/FALSE` or details like `chunkSize` that imply `TRUE`. + The results are then parsed appropriately by waiting for all individual + batches to finish. (#46) + + * Fix bugs in REST and SOAP API queries to prevent infinite looping and + mangling results of relationship queries, specifically parent-to-child + nested queries. (#19, #35, #38, #54) + + * Fix bug in REST and SOAP APIs where the creation of a record that fails + duplicate rules will return the duplicate match results as well and cause the + entire function call to fail because it cannot parse the results. Now only the + status code and message are returned and the function will execute + successfully even if the record has not been created due to the rule. + +--- + +# salesforcer 0.1.4 [release](https://github.com/StevenMMortimer/salesforcer/releases/tag/v0.1.4) + +## Features + + * Rebuilt package against R 4.0 (no issues observed with 3.6.3, 4.0.0, 4.0.1) + (#53) + + * Upgrade to Salesforce version 48.0 (Spring '20) from version 46.0 (Summer '19) + + * Add support for connections through a proxy by setting in package options (#32) + + * CRUD operations now automatically cast date and datetime (Date, POSIXct, + POSIXlt, POSIXt) formats into an accepted string format recognized by + Salesforce (`YYYY-MM-DDThh:mm:ss.sssZ`). + + * Add `batch_size` argument to support specifying custom batch sizes for Bulk jobs + + * Add `sf_convert_lead()` which takes leads and will associate them to the + corresponding Accounts, Contacts, and Opportunities as directed in the input + along with many other options to send an email to the new owner, block the + opportunity creation, and more. + + * Add `sf_create_attachment()` along with a vignette that better describes how + to interact with attachments and other blob data. + + * Add Attachment and Metadata vignettes along with updated Bulk vignette. + +## Bug Fixes + + * Fix issue where REST query was not correctly passing and honoring the batch + size control argument to paginate results + + * Fix issue in results of REST query pagination where the function was looping + infinitely because of a bug in the implementation that would continue using + the same `next_records_url` that was previously passed into the function (#54) + + * Fix issue where the results of Bulk 1.0 query batches where returning fewer + rows than expected because of using `content(..., as="text")` which truncated + the results instead of using `content(..., type="text/csv")` (#54) + + * Fix issue where the details of an object's picklist contains NULLs (e.g. the + `validFor` entry of a picklist value is NULL) so now it is replaced with NA + and then can be bound together into a data.frame (#27) + + * Fix issue where NA values in create, update, and upsert operations where + setting the fields to blank in Bulk APIs, but not the SOAP or REST APIs. Now + NA values in a record will set the field to blank across all APIs (#29) + + * Fix issue where supplying all NA values in the Id field for certain + operations would result in a cryptic error message (`"BAD_REQUEST: Unsupported + Tooling Sobject Type"`); the affected operations are: delete, undelete, + emptyRecycleBin, retrieve, update, and findDuplicatesByIds + +--- + +# salesforcer 0.1.3 [release](https://github.com/StevenMMortimer/salesforcer/releases/tag/v0.1.3) + +## Features + + * Upgrade to version 46.0 (Summer '19) from version 45.0 (Spring '19) + + * Add **RForcecom** backward compatible version of + `rforcecom.getObjectDescription()` + + * Add `sf_describe_object_fields()` which is a tidier version of + `rforcecom.getObjectDescription()` + + * Allow users to control whether query results are kept as all character or + the types are guessed (#12) + + * Add `sf_get_all_jobs_bulk()` so that users can see retrieve details for all + bulk jobs (#13) + + * Add new utility functions `sf_set_password()` and `sf_reset_password()` (#11) + + * Add two new functions to check for duplicates (`sf_find_duplicates()`, + `sf_find_duplicates_by_id()`) (#4) + + * Add new function to download attachments to disk + (`sf_download_attachment()`) (#20) + + * Add functionality to infer the `object_name` argument, required for bulk + queries, if left blank. + + * Add `control` argument to most all package functions and dots (`...`) which + allows for more than a dozen different control parameters listed in + `sf_control()` to be fed into existing function calls to tweak the default + behavior. For example, if you would like to override duplicate rules then you + can adjust the `DuplicateRuleHeader`. If you would like to have certain + assignment rule run on newly created records, then pass in the + `AssignmentRuleHeader` (#4, #5) + + * Add new function `sf_undelete()` which will take records out of the Recycle Bin + + * Add new function `sf_empty_recycle_bin()` which will remove records + permanently from the Recycle Bin + + * Add new function `sf_merge()` which combines up to 3 records of the same + type into 1 record (#22) + +## Bug Fixes + + * Fix bug where Username/Password authenticated sessions where not working with + api_type = "Bulk 1.0" + + * Fix bug where Bulk 1.0 queries that timeout hit an error while trying to abort + since that only supported aborting Bulk 2.0 jobs (#13) + + * Fix bug that had only production environment logins possible because of hard + coding (@weckstm, #18) + + * Enhance `sf_describe_object_fields()` to be robust against nested list + elements and also return picklist labels and their values as a tibble (#16) + + * Fix bug where four of the bulk operation options (`content_type`, `concurrency_mode`, + `line_ending`, and `column_delimiter`) where not being passed down from + the top level generic functions like `sf_create()`, `sf_update()`, etc. However, + `line_ending` has now been moved into the `sf_control` function so it is no longer + explicitly listed for bulk operations as an argument. (@mitch-niche, #23) + + * Ensure that for SOAP, REST, and Bulk 2.0 APIs the verbose argument prints out + the XML or JSON along with the URL of the call so it can be replicated via cURL or + some other programming language (#8) + +--- + +# salesforcer 0.1.2 [release](https://github.com/StevenMMortimer/salesforcer/releases/tag/v0.1.2) + +## Features + + * Add support for Bulk 1.0 operations of "create", "update", "upsert", "delete" + and "hardDelete" + + * Bulk 2.0 operations, by default, now return a single `tbl_df` containing all + of the successful records, error records, and unprocessed records + + * Create internal functions that explicitly call each API for an operation. For + example, `sf_create()` routes into `sf_create_soap()`, `sf_create_rest()`, and + `sf_bulk_operation()`. + +--- + +# salesforcer 0.1.1 [release](https://github.com/StevenMMortimer/salesforcer/releases/tag/v0.1.1) + +## Features + + * Add `sf_search()` with REST and SOAP API support for SOSL and free text search + + * Add `sf_describe_objects()` with REST and SOAP API to return object metadata + + * Add REST API support for upsert (`sf_upsert()`) + + * Add SOAP API support for the following operations: + + * `sf_create()` + * `sf_update()` + * `sf_delete()` + * `sf_retrieve()` + + * Add Metadata API support for the following operations: + + * `sf_create_metadata()` + * `sf_read_metadata()` + * `sf_update_metadata()` + * `sf_upsert_metadata()` + * `sf_delete_metadata()` + * `sf_describe_metadata()` + * `sf_list_metadata()` + * `sf_rename_metadata()` + * `sf_retrieve_metdata()` + * `sf_deploy_metdata()` + + * Update the default file name for a cached token to `.httr-oauth-salesforcer` + so that it does not clash with other package token names. + +## Bug Fixes + + * `sf_user_info()` returning `argument is of length zero` because token is not +automatically refreshed before calling GET. + + * `sf_token()` ignoring basic authorized sessions since it was only looking + for a token using `token_avaiable()`. Replace with `sf_auth_check()` so now + it considers a session or a token to be "available" (#1). + +--- + +# salesforcer 0.1.0 [release](https://github.com/StevenMMortimer/salesforcer/releases/tag/v0.1.0) + +## Features + + * OAuth 2.0 and Basic authentication methods (`sf_auth()`) + + * Query operations via REST and Bulk APIs (`sf_query()`) + + * CRUD operations (Create, Retrieve, Update, Delete) for REST and Bulk APIs: + + * `sf_create()` + * `sf_retrieve()` + * `sf_update()` + * `sf_upsert()` + * `sf_delete()` + + * Backwards compatible versions of **RForcecom** package functions: + + * `rforcecom.login()` + * `rforcecom.getServerTimestamp()` + * `rforcecom.query()` + * `rforcecom.bulkQuery()` + * `rforcecom.create()` + * `rforcecom.update()` + * `rforcecom.upsert()` + * `rforcecom.delete()` + + * Basic utility calls: + + * `sf_user_info()` + * `sf_server_timestamp()` + * `sf_list_rest_api_versions()` + * `sf_list_resources()` + * `sf_list_api_limits()` + * `sf_list_objects()` diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/R/salesforcer b/revdep/library.noindex/salesforcer/new/salesforcer/R/salesforcer new file mode 100644 index 00000000..66861563 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/salesforcer/R/salesforcer @@ -0,0 +1,27 @@ +# File share/R/nspackloader.R +# Part of the R package, https://www.R-project.org +# +# Copyright (C) 1995-2012 The R Core Team +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# A copy of the GNU General Public License is available at +# https://www.r-project.org/Licenses/ + +local({ + info <- loadingNamespaceInfo() + pkg <- info$pkgname + ns <- .getNamespace(as.name(pkg)) + if (is.null(ns)) + stop("cannot find namespace environment for ", pkg, domain = NA); + dbbase <- file.path(info$libname, pkg, "R", pkg) + lazyLoad(dbbase, ns, filter = function(n) n != ".__NAMESPACE__.") +}) diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/R/salesforcer.rdb b/revdep/library.noindex/salesforcer/new/salesforcer/R/salesforcer.rdb new file mode 100644 index 00000000..c8197307 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/R/salesforcer.rdb differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/R/salesforcer.rdx b/revdep/library.noindex/salesforcer/new/salesforcer/R/salesforcer.rdx new file mode 100644 index 00000000..5ac68825 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/R/salesforcer.rdx differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/WORDLIST b/revdep/library.noindex/salesforcer/new/salesforcer/WORDLIST new file mode 100644 index 00000000..983ffcfb --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/salesforcer/WORDLIST @@ -0,0 +1,1961 @@ +AAC +Abessive +aboveOrBelow +acceptedDataType +acceptedValues +AccessMapping +AccessMethod +AccessResource +accountCreator +accountId +AccountInformation +AccountMaster +accountOwner +AccountSettings +AccountSharingRuleSettings +accountTeam +ACGI +ACTIONCALL +actionCallName +ActionEmailRecipientTypes +ActionEmailSenderType +ActionLink +ActionLinkExecutionsAllowed +ActionLinkGroupTemplate +ActionLinkHttpMethod +ActionLinkTemplate +ActionLinkType +ActionLinkUserVisibility +ActionOverride +ActionOverrideType +ActionPlan +ActionTaskAssignedToTypes +actionValue +activateSessionPermSet +ActivationFailed +ActivitiesSettings +ActivityEvent +AddItem +AddMember +AddRecord +AddressSettings +Adessive +adhoc +AdjustmentsSettings +AdminOnly +AdminOrCurrentApprover +AdminSetupEvent +AdvancedTextPost +AE +AED +AES +AFA +AgentConfigAssignments +AgentConfigButtons +AgentConfigProfileAssignments +AgentConfigSkills +AgentConfigUserAssignments +aggregateValue +Allative +AllChannels +AllCspUsers +allInternalUsers +AllOrNoneHeader +AllowAllFraming +ALLOWBACK +AllowFieldTruncationHeader +ALLOWFINISH +ALLOWPAUSE +AllPrmUsers +ALLTHUMBS +AllUpdates +AllUsers +AlphaNumeric +analytics +Analytics +AnalyticsCloudComponentLayoutItem +AnalyticSnapshot +AnalyticSnapshotMapping +ANG +AnimateMasculine +AnnouncementPost +AnnualRevenue +AOA +APEXCALLOUT +ApexClass +APEXCLASS +apexClassName +ApexCodeUnitStatus +ApexComponent +ApexPage +ApexTestSuite +ApexTrigger +api +Api +APIs +API's +APIAccessLevel +APIAsync +ApiEvent +AppActionOverride +AppBrand +AppComponentList +AppLauncher +AppMenu +AppMenuItem +AppPage +AppPreferences +AppProfileActionOverride +ApprovalAction +ApprovalEntryCriteria +ApprovalPageField +ApprovalPost +ApprovalProcess +ApprovalStep +ApprovalStepApprover +ApprovalStepRejectBehavior +ApprovalSubmitter +Approver +ApproveRecord +AppWorkspaceConfig +ar +Args +ARS +ArticleTypeChannelDisplay +ArticleTypeTemplate +Asc +ASF +AsIs +AssignedToMe +ASSIGNMENTITEM +assignmentName +AssignmentRule +AssignmentRuleHeader +AssignmentRules +ASSIGNNEXTVALUETO +AssignToLookupValueType +ASSIGNTOREFERENCE +AssistantRecommendationType +AssociativeBusinessOrPersonalData +async +Async +AttachArticleEvent +attributeName +AUD +AudienceCriteriaType +AuditTrail +AuraBundleType +AuraDefinitionBundle +auth +authenticaion +AuthenticationData +AuthenticationProtocol +AuthProvider +AuthProviderType +Autofill +AUTOLAUNCHED +AutoLaunchedFlow +AutoNumber +AutoResponseRule +AutoResponseRules +AWG +AZM +AZN +BackToPrevious +BAM +BannerPhoto +BarGrouped +BarStacked +BasicTemplateFeedItem +BBD +BDT +BEF +BestCase +bg +BGL +BGN +BH +BHD +BIF +BigObjectIngest +BinaryOnly +BlankAsBlank +BlankAsZero +BlankValueBehavior +BMD +BMP +bn +BND +BottomLeft +BottomLeftBottom +BottomLeftLeft +BottomRight +BottomRightBottom +BottomRightRight +BOV +BOXNOTE +BrandingSet +BrandingSetProperty +BRB +BRL +bs +BTN +BubbleGrouped +BuildCustom +BusinessHoursEntry +BusinessHoursSettings +BusinessHoursSourceType +BusinessProcess +BusinessSetupDataBusinessDataAndAggregates +busop +BWP +BYB +BYN +BypassSharingRules +BYR +BZD +CallCenter +CallCenterItem +CallCenterSection +CallLogPost +CallOptions +Callout +callouts +CampaignInfluenceModel +campaignMemberDerivedOwner +CanvasLocationOptions +CanvasOptions +CanvasPost +CaseCommentPost +CaseCreation +CaseInteraction +CaseLastModified +CaseSettings +CaseSubjectOption +CaseSubjectParticle +CaseSubjectParticleType +caseTeam +CaseType +CaseUnifiedFiles +CategoryGroupVisibility +Causalfinal +CenterDropDown +ChangeDueDate +ChangePriority +ChangeStatus +ChangeStatusPost +ChannelLayout +ChannelLayoutItem +ChannelProgramGroup +characterLimit +ChartAxis +ChartBackgroundDirection +ChartColorPalettes +ChartLegendPosition +ChartPosition +ChartRangeType +ChartSummary +ChartTheme +ChartType +ChartUnits +ChatterAnswersReputationLevel +ChatterAnswersSettings +ChatterExtension +ChatterExtensionType +ChatterFeed +ChatterMobileSettings +chatterPost +ChatTranscriptPost +CHF +ChildServiceReportTemplateStyle +CHOICEFIELD +CHOICELOOKUP +choiceLookupName +choiceName +CHOICETYPE +choosePricebook +CLASSNAME +CleanDataService +CleanRule +CleanRuleStatus +CLF +CLP +CN +CNY +CodeLocation +CollaborationGroupCreated +CollaborationGroupUnarchived +COLLECTIONTYPES +ColonSeparator +colorSafe +ColumnGrouped +ColumnLine +ColumnLineGrouped +ColumnLineStacked +ColumnStacked +Comitative +CommAppPage +CommForgotPasswordPage +CommGlobalSearchResultPage +CommLoginPage +CommObjectPage +CommQuickActionCreatePage +CommRecordPage +CommRelatedListPage +CommSearchResultPage +CommSelfRegisterPage +CommThemeLayoutPage +CommunityBaseTemplate +CommunityCustomThemeLayoutType +CommunityRoles +CommunityTemplateBundleInfo +CommunityTemplateBundleInfoType +CommunityTemplateCategory +CommunityTemplateDefinition +CommunityTemplatePageSetting +CommunityThemeDefinition +CommunityThemeLayoutType +CommunityThemeSetting +CompactLayout +CompanyName +CompanySettings +ComponentInstance +ComponentInstanceProperty +ComponentInstancePropertyTypeEnum +componentName +concurrencyMode +ConfigurationAndUsageData +ConnectedApp +ConnectedAppAttribute +ConnectedAppCanvasConfig +ConnectedAppIpRange +ConnectedAppMobileDetailConfig +ConnectedAppOauthAccessScope +ConnectedAppOauthConfig +ConnectedAppSamlConfig +constantName +contactId +contactLookup +ContentAsset +ContentAssetAccess +ContentAssetFormat +ContentAssetLink +ContentAssetRelationships +ContentAssetVersion +ContentAssetVersions +ContentPost +contentWorkspaceEnableFolders +ContractSettings +ControlledByParent +coordinateLimit +coordinateName +CorsWhitelistOrigin +CountriesAndStates +CPP +CRC +CreateNew +CreateNewRecordType +CreateRecordEvent +createResponseEventAction +createServiceReport +creditCard +criterionIndex +CSD +Csp +CspTrustedSite +css +CUC +CURFY +cURL +CURNEXT +CURNEXTFY +CURNEXTQ +CURNEXTY +CURPREV +CURPREVQ +CurrencyIsoCode +CURRENTQ +CurrentUser +CURY +CustomApexPolicy +CustomApplication +CustomApplicationComponent +CustomApplications +CustomApplicationTranslation +CustomAttribute +CustomButton +CustomButtons +CustomChannel +CustomConditionBuilderPolicy +CustomConsoleComponents +CustomDataType +CustomDataTypeComponent +CustomDataTypeComponentTranslation +CustomDataTypeTranslation +customerPortalUser +CustomerPortalUser +CustomerSuccess +CustomEvent +CUSTOMEVENT +CUSTOMEVENTS +CustomExcludedUser +CustomExperience +CustomExperienceBranding +CustomExperienceTabSet +CustomFeedFilter +CustomField +CustomFieldTranslation +CustomLabel +CustomLabels +CustomLabelTranslation +CustomLinks +CustomList +CustomMetadata +CustomMetadataValue +CustomNotificationType +CustomObject +CustomObjects +CustomObjectTranslation +CustomPageWebLink +CustomPageWebLinkTranslation +CustomPermission +CustomPermissionDependencyRequired +CustomPermissions +CustomSettingsType +CustomShortcut +CustomSite +CustomSummaryFormula +CustomTab +CustomTabTranslation +CustomUser +CustomValue +CVE +cy +CYP +CZK +da +DashboardComponent +DashboardComponentColumn +DashboardComponentColumnType +DashboardComponentFilter +DashboardComponentSection +DashboardComponentSize +DashboardComponentSnapshot +DashboardComponentSortInfo +DashboardComponentType +DashboardFilter +DashboardFilterColumn +DashboardFilterOperation +DashboardFilterOption +DashboardFlexTableComponentProperties +DashboardFolder +DashboardGridComponent +DashboardGridLayout +DashboardMobileSettings +DashboardTableColumn +DashboardType +DataCategory +DataCategoryFilterOperation +DataCategoryGroup +Datacloud +DataExport +DataIntendedToBePublic +Datajourney +DataPipeline +DataPipelineType +dataType +dataTypeFilterOperatorMap +datatypes +DATATYPES +datetime +Datetime +DateTime +DATETIME +Datetimes +DayInMonth +ddThh +de +deactivateSessionPermSet +DeactivationFailed +DefaultChannel +DefaultOff +DefaultOn +DefaultQuoteTemplate +DefaultServiceReportTemplate +DefaultShortcut +DEFAULTVALUE +DefaultWorkflowUser +Delative +DelegateGroup +DeleteConstraint +DELETEs +DeployDetails +DeploymentStatus +DeployMessage +DeployOptions +deployOrchestration +Des +Desc +DescribeMetadataObject +dev +DeveloperControlled +DevicePlatformType +DeviceType +df +DisableFeedTrackingHeader +DisplayCurrency +DisplayText +DJF +DKK +Dockable +DocumentFolder +DoesNotContainPassword +DOESNT +doNotCreateOpportunity +Donut +DOP +DownForMaintenance +dplyr +DropdownBox +DupeActionType +DupeSecurityOptionType +DuplicateRule +DuplicateRuleFilter +DuplicateRuleFilterItem +DuplicateRuleMatchRule +DWG +DZD +EclairGeoData +EclairMap +ECS +EditAllContents +EditDescription +EG +EGP +EightHours +el +Elative +Electoronics +elementName +elementType +EmailAddress +emailAlert +EmailFolder +EmailHeader +EmailMessageEvent +EmailServicesAddress +EmailServicesAttOptions +EmailServicesErrorAction +EmailServicesFunction +emailSimple +EmailTemplate +EmailTemplateStyle +EmailTemplateType +EmailTemplateUiType +EmailToCase +EmailToCaseOnFailureActionType +EmailToCaseRoutingAddress +EmailToCaseRoutingAddressType +EmailToCaseSettings +EmbeddedServiceBranding +EmbeddedServiceConfig +EmbeddedServiceFieldService +EmbeddedServiceFontSize +EmbeddedServiceLiveAgent +EmbeddedServiceQuickAction +EmbeddedServiceScenario +emptyRecycleBin +EncryptedFieldMaskChar +EncryptedFieldMaskType +EncryptedText +EndsWith +EnforceSharingRules +EntitlementProcess +EntitlementProcessMilestoneItem +EntitlementProcessMilestoneTimeTrigger +EntitlementSettings +EntitlementTemplate +eo +EO +EqualTo +Ergative +ERN +errorCode +errorIdentifier +errorParams +EscalateToRecord +EscalationAction +EscalationRule +EscalationRules +EscalationStartTimeType +Essive +Essiveformal +et +ETB +eu +EUC +EventDelivery +EventDeliveryType +EventParameterMap +eventParameterName +EventSubscription +EVENTTYPE +EveryoneButCreator +EXCELT +EXE +explicity +ExtendedErrorCode +ExtendedErrorDetails +extensionName +ExternalDataSource +ExternalDataSourceType +ExternalLookup +ExternalPrincipalType +ExternalServiceRegistration +FacebookPost +Factmap +failedResults +FederationId +FeedElement +FeedFilterCriterion +FeedItemDisplayFormat +FeedItemSettings +FeedItemType +FeedItemVisibility +FeedLayout +FeedLayoutComponent +FeedLayoutComponentType +FeedLayoutFilter +FeedLayoutFilterPosition +FeedLayoutFilterType +fi +FIELDASSIGNMENT +FieldManageability +FieldMapping +FieldMappingField +FieldMappingRow +fieldName +FieldOverride +fieldReference +FIELDREFERENCE +fieldRelationshipName +FIELDSERVICE +FieldServiceMobile +FieldServiceSettings +FieldServiceWeb +FieldSet +FieldSetItem +FieldSetTranslation +fieldType +FieldType +FieldUpdate +FieldUpdateOperation +fieldValue +FieldValue +FifteenMinutes +FileDownloadBehavior +FileProperties +filesystem +FileType +FileTypeDispositionAssignmentBean +FileUploadAndDownloadSecuritySettings +FilterItem +FilterOperation +FilterScope +filterValues +FIM +finaly +findDuplicatesByIds +FindSimilarOppFilter +FirstName +FirstResponse +FiscalPeriod +FISCALPERIOD +FiscalQuarter +FiscalWeek +FISCALWEEK +FiscalYear +FiscalYearSettings +FiveAttempts +FJD +FK +FKP +Flexipage +FlexiPage +FLEXIPAGE +FlexiPageRegion +FlexiPageRegionMode +FlexiPageRegionType +FlexiPageTemplateInstance +FlexiPageType +FlexTable +FlowAction +FlowActionCall +FlowActionCallInputParameter +FlowActionCallOutputParameter +FlowApexPluginCall +FlowApexPluginCallInputParameter +FlowApexPluginCallOutputParameter +FlowAssignment +FlowAssignmentItem +FlowAssignmentOperator +FlowBaseElement +FlowCategory +FlowCategoryItems +FlowChoice +FlowChoiceTranslation +FlowChoiceUserInput +FlowChoiceUserInputTranslation +FlowComparisonOperator +FlowCondition +FlowConnector +FlowConstant +FlowDataType +flowDecision +FlowDecision +FlowDefinition +FlowDefinitionTranslation +FlowDynamicChoiceSet +FlowElement +FlowElementReferenceOrValue +FlowFormula +FlowInputFieldAssignment +FlowInputValidationRule +FlowInputValidationRuleTranslation +FlowLoop +FlowMetadataValue +flowName +FlowNode +FlowOutputFieldAssignment +FlowProcessType +FlowRecordCreate +FlowRecordDelete +FlowRecordFilter +FlowRecordFilterOperator +FlowRecordLookup +FlowRecordUpdate +FlowRule +FlowScreen +FlowScreenField +FlowScreenFieldInputParameter +FlowScreenFieldOutputParameter +FlowScreenFieldTranslation +FlowScreenFieldType +FlowScreenRule +FlowScreenRuleAction +FlowScreenTranslation +FlowStage +FlowStep +FlowSubflow +FlowSubflowInputAssignment +FlowSubflowOutputAssignment +FlowTextTemplate +FlowTranslation +FLOWTYPE +FlowVariable +flowVersion +FlowWait +FlowWaitEvent +FlowWaitEventInputParameter +FlowWaitEventOutputParameter +FolderAccessTypes +FolderId +FolderShare +FolderShareAccessLevel +FolderSharedToType +ForecastCategories +ForecastingCategoryMapping +ForecastingDateType +ForecastingDisplayedFamilySettings +ForecastingSettings +ForecastingTypeSettings +ForecastRangeSettings +formalLetter +FormFactor +formulaExpression +FourHours +freeForm +FreezeAndNotify +FRF +FullAccess +fullName +fullScreen +ga +GBP +generateWorkOrders +geolocation +GEOLOCATION +GETs +GHC +GHS +GIP +github +GlobalPicklistValue +GlobalQuickActionTranslation +GlobalValueSet +GlobalValueSetTranslation +GMD +GNF +googlesheets +GotoNextStep +GRD +greaterOrEqual +greaterThan +GreaterThan +GreaterThanOrEqualTo +GTQ +GWP +GYD +GZIP +hardDelete +HelpAndToolLinks +hh +HideBlankLines +HideHeader +HideShare +HighVolume +hiratake +HistoryRetentionPolicy +HK +HKD +HKSCS +HN +HNL +HomePage +HomePageComponent +HomePageLayout +HorizontalBar +HorizontalBarGrouped +HorizontalBarStacked +HorizontalBarStackedTo +HRD +HRK +HTG +HTM +htmlArea +HttpDelete +HttpGet +HttpHead +HttpPatch +HttpPost +HttpPut +https +httr +HTX +hu +HUF +hy +HyphenSeparator +IDASSIGNMENT +idcol +IdeaReputationLevel +IdeasSettings +IdpInitiated +IDR +IEP +Illative +ILS +imageOrNote +incompatibleDataType +incompatibleValue +InDevelopment +IndexField +IndirectLookup +Inessive +INI +inputAssignmentNames +InputField +INPUTPARAM +inputParameterName +inputParameterNames +inputVariableName +INR +InsightParentType +InsightTrendType +InsightType +InstalledPackage +IntegrationHubSettings +IntegrationHubSettingsType +InternalUsers +invalidTokens +invalidValue +InvocableAction +InvocableActionType +InvocableProcess +io +ios +IpRange +IQD +IRR +ISK +IsNull +isPkChunkingEnabled +ISREQUIRED +IterationOrder +ITL +iw +ja +Janrain +javascript +jennybc +JFIF +JIS +JMD +JobComplete +jobType +JOD +JourneyBuilderIntegration +JPE +JPG +JPY +js +JS +JSON +ka +KES +KeyboardShortcuts +KeywordList +KGS +KHR +KMF +KnowledgeAnswerSettings +KnowledgeCaseEditor +KnowledgeCaseField +KnowledgeCaseFieldsSettings +KnowledgeCaseSettings +KnowledgeCommunitiesSettings +KnowledgeLanguage +KnowledgeLanguageLookupValueType +KnowledgeLanguageSettings +KnowledgePublish +KnowledgeSettings +KnowledgeSitesSettings +KnowledgeSuggestedArticlesSettings +KnowledgeWorkflowAction +KnowledgeWorkOrderField +KnowledgeWorkOrderFieldsSettings +KnowledgeWorkOrderLineItemField +KnowledgeWorkOrderLineItemFieldsSettings +ko +KPW +KRW +KWD +KYD +KZT +LAK +LargeTextArea +lastFour +LASTMONTH +LastName +LASTTHIS +LASTTHISMONTH +LASTWEEK +LayoutColumn +LayoutHeader +LayoutItem +LayoutSection +LayoutSectionStyle +LayoutSectionTranslation +LayoutTranslation +LazyData +LBP +LeadConvertSettings +LeadSource +LeadStatus +LeastActive +leftElementName +leftElementType +LeftFixed +LeftFloat +LEFTOPERAND +LeftToRight +lessOrEqual +lessThan +LessThan +LessThanOrEqualTo +LetterheadHeaderFooter +LetterheadHorizontalAlignment +LetterheadLine +LetterheadVerticalAlignment +LF +LFs +LicensedCustomPermissions +LicenseDefinition +lifecycle +Lifecycle +LightningBolt +LightningBoltCategory +LightningBoltFeatures +LightningBoltImages +LightningBoltItems +LightningComponent +LightningComponentBundle +LightningExperienceTheme +LimitInfoHeader +LineCumulative +LineCumulativeGrouped +LineGrouped +LineGroupedCumulative +LinkedIn +LinkPost +ListMetadataQuery +ListPlacement +ListView +ListViewDefinition +ListViewFilter +ListViewRecord +LiveAgentConfig +LiveAgentSettings +LiveChatAgentConfig +LiveChatButton +LiveChatButtonDeployments +LiveChatButtonInviteEndPosition +LiveChatButtonInviteStartPosition +LiveChatButtonPresentation +LiveChatButtonRoutingType +LiveChatButtonSkills +LiveChatButtonType +LiveChatDeployment +LiveChatDeploymentDomainWhitelist +LiveChatSensitiveDataRule +LiveMessageSettings +LKR +localAction +LocaleOptions +Locative +LockoutInterval +LogACall +LogANote +LogCategory +LogCategoryLevel +LoggedInUser +LoginEvent +LoginFlow +LogInfo +LoginScopeHeader +LongTextArea +LookupFilter +LookupFilterTranslation +LookupValue +LookupValueType +LRD +LSL +lt +LTL +LUF +lv +LVL +LY +LYD +MacroSettings +MailAppAppPage +ManageableState +ManagedTopic +ManagedTopics +ManagerAndSubordinatesInternal +MappingOperation +MarketingActionSettings +MarketingResourceType +massActionButton +MasterDetail +MASTERFLOW +MatchBlanks +MatchingMethod +MatchingRule +MatchingRuleItem +MatchingRules +MatchingRuleStatus +MaxDaysInCommunity +maxLength +maxLimit +MaxLoginAttempts +MDL +MDM +mergeFieldReference +MessageType +MetadataRelationship +metadataValue +METADATAVALUES +MetadataWithContent +metricRefresh +MGA +MGF +MHTM +MHTML +MicrosoftACS +MilestoneEvent +MilestoneTimeUnits +MilestoneType +MilestoneTypeRecurrenceType +MiniLayout +minitablet +MISTMATCHED +mk +MKD +MMK +MNT +MobileNav +MobileSettings +ModeratedEntityField +ModerationRule +ModerationRuleAction +ModerationRuleType +ModifiedDate +MonitoredEvents +MonthInYear +MostAvailable +MOV +MRO +MruHeader +MruList +MruRow +MTL +multiBatch +MultiBlock +Multipicklist +MultiSelectCheckboxes +MULTISELECTCHOICE +MULTISELECTFIELD +MultiselectPicklist +MultiSelectPicklist +MUR +MVR +MWK +MX +MXN +MXV +MYR +MyTeamTerritory +MyTeamUser +MyTerritory +MZM +MZN +NAD +NamedCredential +NamedUser +NameSettings +NavigationLinkSet +NavigationMenuItem +NavigationSubMenu +NavType +NetworkAccess +NetworkBranding +NetworkMemberGroup +NetworkPageOverride +NetworkPageOverrideSetting +NetworkStatus +NetworkTabSet +NetworkUserType +NewChild +NewChildRecordType +NewRecordType +newWindow +NextAutomatedApprover +NEXTFY +NEXTMONTH +NextOwnerType +NEXTQ +NextValue +NEXTWEEK +NEXTY +NGN +NinetyDays +nino +NIO +nl +NL +NLG +NoAuthentication +NoContent +nodeset +NoFraming +NOK +NoLimit +NONCOLLECTION +NONSURVEY +NONVARIABLE +NoRestriction +noSidebar +notContain +notEqual +NotEqualTo +NoTestRun +NOTFOUND +NotVisible +NullNotAllowed +NULLs +NZD +oauth +Oauth +OAuth +ObjectFilterOperator +ObjectHomeChart +ObjectMapping +ObjectMappingField +objectName +ObjectNameCaseValue +ObjectPage +ObjectRelationship +ObjectSearchSetting +objectType +OBJECTTYPE +ObjectUsage +OBJECTVARIABLE +objectVariableName +OData +ODP +ODT +OfferFeedback +OfflineAccess +OFFSETNUMBER +OFFSETUNIT +OGV +OLDOBJECTVARIABLE +oldObjectVariableName +OMR +onAllChanges +OncePerUser +OnChart +onClickJavaScript +onCreateOnly +onCreateOrTriggeringUpdate +OneColumn +OneYear +OnRecursiveUpdate +OpenCTI +OpenID +OpenIdConnect +OpenSearch +operatorName +OpportunityCloseDate +opportunityId +OpportunityListFieldsLabelMapping +OpportunityListFieldsSelectedSettings +OpportunityListFieldsUnselectedSettings +opportunityName +OpportunitySettings +opportunityTeam +OPX +OrchestrationContext +OrchestrationContextEvent +orchestrationDebugLog +OrchestrationFlow +orchestrationTimer +OrderSettings +Org's +OrganizationSettingsDetail +OrgPreferenceSettings +OrgWideEmailAddress +otherFieldName +OutboundMessage +outgoingemail +outputAssignment +outputAssignmentName +OUTPUTPARAM +outputParameter +outputParameterNames +outputVariableName +OwnerChangeOptions +ownerId +PAB +PackageTypeMembers +PackageVersion +PackageVersionHeader +PageComponentType +PageComponentWidth +PageLayout +PARAM +parameterName +Parametrized +parentFlowName +ParentId +ParentIds +parentScreenFieldName +partnerUser +PartnerUser +PasswordField +PasswordPolicies +PATCHs +PathAssistant +PathAssistantSettings +PathAssistantStep +PAUSEDTEXT +PeriodTypes +PermissionSet +PermissionSetApexClassAccess +PermissionSetApexPageAccess +PermissionSetApplicationVisibility +PermissionSetCustomPermissions +PermissionSetExternalDataSourceAccess +PermissionSetFieldPermissions +PermissionSetGroup +PermissionSetObjectPermissions +PermissionSetRecordTypeVisibility +PermissionSetTabSetting +PermissionSetTabVisibility +PermissionSetUserPermission +PersistentId +PersonAccount +PersonalEnabled +PersonalJourneySettings +PersonalTagging +PersonListSettings +PerUser +PGK +PhP +picklist +Picklist +PICKLIST +PicklistEntry +PICKLISTFIELD +PicklistValue +picklistValues +PicklistValueTranslation +PipeSeparator +PJP +PJPEG +Pkb +PKChunking +pkgdown +PKR +PlatformActionGroupCategory +PlatformActionList +PlatformActionListContext +PlatformActionListItem +PlatformActionType +PlatformCachePartition +PlatformCachePartitionType +PlatformCacheType +PlatformEventType +PLN +POINTT +PollPost +portalRole +PortalRole +PortalRoleAndSubordinates +PortalRoles +portalRoleSubordinates +PortalType +POSIXct +POSIXlt +POSIXt +PostBinding +POSTs +PostTemplate +PPSX +PREV +PREVCUR +PREVCURFY +PREVCURY +PREVFY +PreviewImage +PreviousValue +PREVQ +PREVY +PrimaryTabComponents +Prm +PROCESSMETADATAVALUE +PROCESSMETADATAVALUES +ProcessSubmitterType +processType +PROCESSTYPE +ProductDate +ProductivityAction +ProductSettings +ProfileActionOverride +ProfileApexClassAccess +ProfileApexPageAccess +ProfileApplicationVisibility +ProfileCategoryGroupVisibility +ProfileCustomPermissions +ProfileExternalDataSourceAccess +ProfileFieldLevelSecurity +ProfileLayoutAssignment +ProfileLoginHours +ProfileLoginIpRange +ProfileObjectPermissions +ProfilePasswordPolicy +ProfileRecordTypeVisibility +ProfileSessionSetting +ProfileSkillPost +ProfileTabVisibility +ProfileUserPermission +programmatically +promotionLeft +promotionRight +propertyName +propertyType +ProvidedString +PSD +PTE +PublicFolderAccess +PublicGroups +PublicInternal +PublicTagging +PublishAsNew +purrr +PushNotification +PUTs +PY +PYG +QAR +QIngest +queryall +QueryOptions +questionName +QuestionPost +QuestionRestriction +queueable +QueueMembers +QueueSobject +quickAction +QuickAction +QuickActionLabel +QuickActionLayout +QuickActionLayoutColumn +QuickActionLayoutItem +QuickActionLayoutLeftRight +QuickActionLayoutTopDown +QuickActionList +QuickActionListItem +QuickActionSendEmailOptions +QuickActionTranslation +QuickActionType +QuickRecordType +QUIPDOC +QUIPSHEET +QuotasSettings +QuoteSettings +QuoteTemplate +RadioButtons +RateLimitTimePeriod +RCurl +README +Readonly +ReadOnly +readr +ReadSelect +ReadWrite +ReadWriteTransfer +RealName +RecommendationAudience +RecommendationAudienceDetail +RecommendationChannel +RecommendationDefinition +RecommendationDefinitionDetail +RecommendationStrategy +RecordEdit +RecordEditabilityType +RECORDFILTER +RECORDLOOKUP +RecordPage +RecordPreview +recordset +recordsets +RecordType +RecordTypePicklistValue +RecordTypeTranslation +RECORDUPDATE +recursChained +recursIndependently +RECURSIVECOUNTVARIABLE +RedirectBinding +REFERENCEDFLOW +referenceTo +RefreshToken +RegionFlagStatus +RejectRecord +RejectRequest +RelatedContent +RelatedContentItem +RelatedList +RelatedListItem +RelatedListRecord +relatedUserField +RELATIVEALARM +RemoteSiteSetting +ReplyAll +ReplyPost +ReportAggregate +ReportAggregateDatatype +ReportAggregateReference +ReportAggrType +ReportBlockInfo +ReportBucketField +ReportBucketFieldSourceValue +ReportBucketFieldType +ReportBucketFieldValue +ReportChart +ReportChartComponentLayoutItem +ReportChartComponentSize +ReportChartSize +ReportColorRange +ReportColumn +ReportCrossFilter +ReportDataCategoryFilter +ReportEvent +reportFilter +ReportFilter +ReportFilterItem +reportFilters +ReportFolder +ReportFormat +ReportFormulaNullTreatment +ReportGrouping +ReportHistoricalSelector +ReportJobSourceTypes +ReportLayoutSection +ReportParam +ReportSortType +ReportSummaryType +ReportTimeFrameFilter +ReportType +ReportTypeCategory +ReportTypeColumn +ReportTypeColumnTranslation +ReportTypeSectionTranslation +ReportTypeTranslation +ReputationBranding +ReputationLevel +ReputationLevelDefinitions +ReputationLevels +ReputationPointsRule +ReputationPointsRules +RequestFeedback +Requeue +requiredField +REST +RESTful +resultset +ResumeFlow +retrieveMetadata +retrieveRequest +RetrieveRequest +RetrieveResult +RForcecom +rightElementName +rightElementType +RIGHTOPERAND +RMB +ro +ROL +RoleAndSubordinates +RoleAndSubordinatesInternal +RoleOrTerritory +roleSubordinates +roleSubordinatesInternal +ROLLUP +RoutingType +RowCount +RowLabelAscending +RowLabelDescending +RowValueAscending +RowValueDescending +RSD +RTF +ru +RuleAssociation +RuleEntry +RuleItem +ruleName +RunAllTestsInOrg +RunLocalTests +RunSpecifiedTests +RunTestsResult +RUR +RWF +RypplePost +salesforce +SameOriginOnly +SAML +SamlEncryptionType +SamlIdentityLocationType +SamlIdentityType +SamlIdpSLOBinding +SamlInitiationMethod +SamlNameIdFormatType +SamlSpSLOBinding +SamlSsoConfig +SamlSubjectType +SamlType +SAR +SBD +ScatterGrouped +ScheduleDate +ScheduledRecommendation +ScheduledRecommendationDetail +sControl +Scontrol +SControlContentSource +ScontrolTranslation +SCR +SCREENFIELD +screenFieldName +SCREENFIELDTYPE +SCREENRULE +screenRuleName +SDD +SDG +SearchLayouts +SearchSettings +SearchSettingsByObject +SecurityClassification +SecuritySettings +SEK +SendAction +SendEmail +SensitiveDataActionType +ServiceCloudConsoleConfig +ServiceDesk +ServiceReportTemplate +sessionId +SessionSecurityLevel +SessionSettings +SessionTimeout +SetNull +SettingsOpportunityFilter +SetupObjectVisibility +SFDC +SFDCMobileSettings +SfdcOrg +SFX +SG +SGD +SharedTo +SharingBaseRule +SharingCriteriaRule +SharingModel +SharingOwnerRule +SharingReason +SharingReasonTranslation +SharingRecalculation +SharingRules +SharingSet +SharingTerritoryRule +SHP +SHTM +SHTML +SidebarComponent +SimpleURL +SiteClickjackProtectionLevel +SiteDotCom +Siteforce +SiteRedirect +SiteRedirectMapping +SiteType +SiteWebAddress +SixMonths +SixtyDays +SixtyMinutes +SJIS +sk +SkillAssignments +SkillProfileAssignments +SkillUserAssignments +SKK +sl +SLL +SNOTE +sobject +SObject +SOBJECT +sobjectName +SocialCustomerServiceSettings +SocialHandle +SocialNetwork +SocialPost +SocialPostContent +SocialPostSource +SOQL +sortOrder +SortOrder +sosl +SOSL +SpecialCharacters +SpecifiedUser +SpInitiated +SpokeId +sr +SRD +SRG +ssn +SSO +SSP +ssZ +stageName +StandardButton +StandardFieldTranslation +StandardValue +StandardValueSet +StandardValueSetTranslation +StandardVolume +StartFlow +startsWith +StartsWith +StaticResource +StaticResourceCacheControl +StepCriteriaNotMetType +StepRejectBehaviorType +stevenmmortimer +StevenMMortimer +StrategyNode +STYPI +SUBFLOW +subflowName +SUBFLOWS +subflowType +subfolders +SubjectNameId +Sublative +SubscriberControlled +SubtabComponents +successfulResults +SummaryLayout +SummaryLayoutItem +SummaryLayoutStyle +SummaryOperations +Superessive +SupervisorAgentConfigSkills +SupervisorAgentStatusFilter +SUR +surveyName +sv +SV +SVC +SVGZ +SY +SynonymDictionary +SynonymGroup +SYP +SZL +TabLimitConfig +TabVisibility +teardown +tempdir +TenAttempts +Termanative +TerritoryAndSubordinates +TestLevel +TestTest +TextArea +TextOnly +TextPost +th +THB +ThirtyDays +ThirtyMinutes +THISMONTH +THISNEXT +THISNEXTMONTH +THISWEEK +ThreeAttempts +THTML +thunderResponse +tibble +tibbles +Tidelift +tidyverse +TIF +timeframe +Timeframe +timespan +TJR +TJS +tl +TMM +TMT +TND +Toc +TopicsForObjects +topLeft +TopLeft +TopLeftLeft +TopLeftTop +TopRight +TopRightRight +TopRightTop +TopToBottom +TouchMobileSettings +TPE +TrackedChange +trailhead +TransactionSecurityAction +TransactionSecurityEventName +TransactionSecurityFlow +TransactionSecurityNotification +TransactionSecurityPolicy +Translative +TreatBlanksAs +TRIGGERTYPE +TRL +TRTF +TTD +TW +TWD +TwelveHours +TwentyFourHours +TwoColumnsLeftToRight +TwoColumnsTopToBottom +TwoHours +TXML +TxnSecurityPolicyType +TZS +UAH +UGX +UI +UiBehavior +UiFormulaCriterion +UiFormulaRule +UiPlugin +UiType +uk +undelete +Undelete +undeleted +Undeletes +UnderConstruction +unlist +Unlist +unmanaged +unnest +unnested +unprocessedRecords +UpperLowerCaseNumeric +UpperLowerCaseNumericSpecialCharacters +upsert +Upsert +upserting +Upserting +upserts +Upserts +ur +URI +UserCriteria +UserDateGranularity +UserDateInterval +userHierarchyField +UserId +USERINPUT +userLookup +UserProfile +UserProvisioningFlow +UserStatus +UserTerritoryDeleteHeader +UseSystemDefault +UtilityBar +UY +UYU +UZS +ValidationRule +VALIDATIONRULE +ValidationRuleTranslation +Validator +ValueSet +ValueSettings +ValueSetValuesDefinition +ValueTranslation +ValueTypeField +variableName +vctrs +VE +VEB +VEF +VerticalColumn +VerticalColumnGrouped +VerticalColumnGroupedLine +VerticalColumnLine +VerticalColumnStacked +VerticalColumnStackedLine +VerticalColumnStackedTo +VisibleOptional +VisibleOrRequired +VisibleRequired +VISIO +visualforce +Visualforce +VisualForce +visualforcePage +VisualforcePage +VisualizationPlugin +VisualizationResource +VisualizationResourceType +VisualizationType +VND +VUV +WAITEVENT +waitEventName +WasSelected +WasSet +WasVisited +WAV +WaveApplication +WaveDashboard +WaveDataflow +WaveDataset +WaveLens +WaveRecipe +WaveTemplateBundle +WaveXmd +WaveXmdDate +WaveXmdDimension +WaveXmdDimensionCustomAction +WaveXmdDimensionMember +WaveXmdDimensionSalesforceAction +WaveXmdMeasure +WaveXmdOrganization +WaveXmdRecordDisplayLookup +wdc +WebLink +WebLinkAvailability +WebLinkDisplayType +WebLinkPosition +WebLinkTranslation +WebLinkType +WebLinkWindowType +WebToCaseSettings +WEBVIEW +WeightedSourceCategory +WMA +WMV +WORDT +WorkflowAction +WorkflowActionReference +WorkflowActionType +WorkflowAlert +WorkflowEmailRecipient +WorkflowFieldUpdate +WorkflowFlowAction +WorkflowFlowActionParameter +WorkflowKnowledgePublish +WorkflowOutboundMessage +WorkflowRule +WorkflowSend +WorkflowTask +WorkflowTaskTranslation +WorkflowTimeTrigger +WorkflowTimeUnits +WorkflowTriggerTypes +WorkspaceMapping +WRF +WST +XAF +XCD +XHTML +XJS +xmlToList +XOF +XPF +XPSD +XSN +xxxxxZZZ +XYZXYZXYZXYZ +XZIP +yyyy +ZA +ZAR +zh +ZippedVersions +ZMK +ZMW +ZWD +ZWL diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/extdata/cloud.png b/revdep/library.noindex/salesforcer/new/salesforcer/extdata/cloud.png new file mode 100644 index 00000000..f3d90f71 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/extdata/cloud.png differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/extdata/logo.png b/revdep/library.noindex/salesforcer/new/salesforcer/extdata/logo.png new file mode 100644 index 00000000..ecf5fa74 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/extdata/logo.png differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/extdata/old-logo.png b/revdep/library.noindex/salesforcer/new/salesforcer/extdata/old-logo.png new file mode 100644 index 00000000..9e2ae3be Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/extdata/old-logo.png differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/AnIndex b/revdep/library.noindex/salesforcer/new/salesforcer/help/AnIndex new file mode 100644 index 00000000..0dc78b36 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/salesforcer/help/AnIndex @@ -0,0 +1,298 @@ +salesforcer-package salesforcer-package +accepted_controls_by_api accepted_controls_by_api +accepted_controls_by_operation accepted_controls_by_operation +bind_query_resultsets bind_query_resultsets +build_manifest_xml_from_list build_manifest_xml_from_list +build_metadata_xml_from_list build_metadata_xml_from_list +build_proxy build_proxy +build_soap_xml_from_list build_soap_xml_from_list +catch_errors catch_errors +catch_unknown_api catch_unknown_api +check_and_encode_files check_and_encode_files +collapse_list_with_dupe_names collapse_list_with_dupe_names +combine_parent_and_child_resultsets combine_parent_and_child_resultsets +compact2 compact2 +drop_attributes drop_attributes +drop_attributes_recursively drop_attributes_recursively +drop_empty_recursively drop_empty_recursively +drop_nested_child_records drop_nested_child_records +extract_nested_child_records extract_nested_child_records +extract_records_from_xml_node extract_records_from_xml_node +extract_records_from_xml_nodeset extract_records_from_xml_nodeset +extract_records_from_xml_nodeset_of_records extract_records_from_xml_nodeset_of_records +filter_valid_controls filter_valid_controls +flatten_tbl_df flatten_tbl_df +format_headers_for_verbose format_headers_for_verbose +format_report_row format_report_row +get_os get_os +guess_object_name_from_soql guess_object_name_from_soql +is_legit_token is_legit_token +list_extract_parent_and_child_result list_extract_parent_and_child_result +make_analytics_folder_child_operations_url make_analytics_folder_child_operations_url +make_analytics_folder_collections_url make_analytics_folder_collections_url +make_analytics_folder_operations_url make_analytics_folder_operations_url +make_analytics_folder_shares_url make_analytics_folder_shares_url +make_analytics_folder_share_by_id_url make_analytics_folder_share_by_id_url +make_analytics_folder_share_recipients_url make_analytics_folder_share_recipients_url +make_analytics_notifications_limits_url make_analytics_notifications_limits_url +make_analytics_notifications_list_url make_analytics_notifications_list_url +make_analytics_notification_operations_url make_analytics_notification_operations_url +make_base_metadata_url make_base_metadata_url +make_base_rest_url make_base_rest_url +make_base_soap_url make_base_soap_url +make_bulk_batches_url make_bulk_batches_url +make_bulk_batch_details_url make_bulk_batch_details_url +make_bulk_batch_status_url make_bulk_batch_status_url +make_bulk_create_job_url make_bulk_create_job_url +make_bulk_delete_job_url make_bulk_delete_job_url +make_bulk_end_job_generic_url make_bulk_end_job_generic_url +make_bulk_get_all_jobs_url make_bulk_get_all_jobs_url +make_bulk_get_all_query_jobs_url make_bulk_get_all_query_jobs_url +make_bulk_get_job_url make_bulk_get_job_url +make_bulk_job_records_url make_bulk_job_records_url +make_bulk_query_result_url make_bulk_query_result_url +make_bulk_query_url make_bulk_query_url +make_chatter_users_url make_chatter_users_url +make_composite_batch_url make_composite_batch_url +make_composite_url make_composite_url +make_dashboards_list_url make_dashboards_list_url +make_dashboard_copy_url make_dashboard_copy_url +make_dashboard_describe_url make_dashboard_describe_url +make_dashboard_filter_operators_list_url make_dashboard_filter_operators_list_url +make_dashboard_filter_options_analysis_url make_dashboard_filter_options_analysis_url +make_dashboard_status_url make_dashboard_status_url +make_dashboard_url make_dashboard_url +make_login_url make_login_url +make_parameterized_search_url make_parameterized_search_url +make_query_url make_query_url +make_reports_list_url make_reports_list_url +make_report_copy_url make_report_copy_url +make_report_create_url make_report_create_url +make_report_describe_url make_report_describe_url +make_report_execute_url make_report_execute_url +make_report_fields_url make_report_fields_url +make_report_filter_operators_list_url make_report_filter_operators_list_url +make_report_instances_list_url make_report_instances_list_url +make_report_instance_url make_report_instance_url +make_report_query_url make_report_query_url +make_report_types_list_url make_report_types_list_url +make_report_type_describe_url make_report_type_describe_url +make_report_url make_report_url +make_rest_describe_url make_rest_describe_url +make_rest_objects_url make_rest_objects_url +make_rest_record_url make_rest_record_url +make_search_url make_search_url +make_soap_xml_skeleton make_soap_xml_skeleton +make_verbose_httr_message make_verbose_httr_message +map_sf_type_to_r_type map_sf_type_to_r_type +merge_null_to_na merge_null_to_na +message_w_errors_listed message_w_errors_listed +metadata_type_validator metadata_type_validator +parameterized_search_control parameterized_search_control +parse_error_code_and_message parse_error_code_and_message +parse_report_detail_rows parse_report_detail_rows +patched_tempdir patched_tempdir +rDELETE rDELETE +records_list_to_tbl records_list_to_tbl +remove_empty_linked_object_cols remove_empty_linked_object_cols +return_matching_controls return_matching_controls +rforcecom.bulkAction rforcecom.bulkAction +rforcecom.bulkQuery rforcecom.bulkQuery +rforcecom.create rforcecom.create +rforcecom.delete rforcecom.delete +rforcecom.getObjectDescription rforcecom.getObjectDescription +rforcecom.getServerTimestamp rforcecom.getServerTimestamp +rforcecom.login rforcecom.login +rforcecom.query rforcecom.query +rforcecom.retrieve rforcecom.retrieve +rforcecom.search rforcecom.search +rforcecom.update rforcecom.update +rforcecom.upsert rforcecom.upsert +rGET rGET +rPATCH rPATCH +rPOST rPOST +rPUT rPUT +safe_bind_rows safe_bind_rows +salesforcer salesforcer-package +salesforcer_state salesforcer_state +session_id_available session_id_available +set_null_elements_to_na set_null_elements_to_na +set_null_elements_to_na_recursively set_null_elements_to_na_recursively +sf_abort_job_bulk sf_abort_job_bulk +sf_access_token sf_access_token +sf_analytics_notifications_limits sf_analytics_notifications_limits +sf_analytics_notifications_list sf_analytics_notifications_list +sf_analytics_notification_create sf_analytics_notification_create +sf_analytics_notification_delete sf_analytics_notification_delete +sf_analytics_notification_describe sf_analytics_notification_describe +sf_analytics_notification_update sf_analytics_notification_update +sf_auth sf_auth +sf_auth_check sf_auth_check +sf_auth_refresh sf_auth_refresh +sf_batch_details_bulk sf_batch_details_bulk +sf_batch_status_bulk sf_batch_status_bulk +sf_build_cols_spec sf_build_cols_spec +sf_bulk_operation sf_run_bulk_operation +sf_close_job_bulk sf_close_job_bulk +sf_control sf_control +sf_convert_lead sf_convert_lead +sf_copy_dashboard sf_copy_dashboard +sf_copy_report sf_copy_report +sf_create sf_create +sf_create_attachment sf_create_attachment +sf_create_attachment_bulk_v1 sf_create_attachment_bulk_v1 +sf_create_attachment_rest sf_create_attachment_rest +sf_create_attachment_soap sf_create_attachment_soap +sf_create_batches_bulk sf_create_batches_bulk +sf_create_bulk_v1 sf_create_bulk_v1 +sf_create_bulk_v2 sf_create_bulk_v2 +sf_create_job_bulk sf_create_job_bulk +sf_create_job_bulk_v1 sf_create_job_bulk_v1 +sf_create_job_bulk_v2 sf_create_job_bulk_v2 +sf_create_metadata sf_create_metadata +sf_create_report sf_create_report +sf_create_rest sf_create_rest +sf_create_soap sf_create_soap +sf_delete sf_delete +sf_delete_attachment sf_delete_attachment +sf_delete_bulk_v1 sf_delete_bulk_v1 +sf_delete_bulk_v2 sf_delete_bulk_v2 +sf_delete_dashboard sf_delete_dashboard +sf_delete_job_bulk sf_delete_job_bulk +sf_delete_metadata sf_delete_metadata +sf_delete_report sf_delete_report +sf_delete_report_instance sf_delete_report_instance +sf_delete_rest sf_delete_rest +sf_delete_soap sf_delete_soap +sf_describe_dashboard sf_describe_dashboard +sf_describe_dashboard_components sf_describe_dashboard_components +sf_describe_metadata sf_describe_metadata +sf_describe_objects sf_describe_objects +sf_describe_object_fields sf_describe_object_fields +sf_describe_report sf_describe_report +sf_describe_report_type sf_describe_report_type +sf_download_attachment sf_download_attachment +sf_empty_recycle_bin sf_empty_recycle_bin +sf_end_job_bulk sf_end_job_bulk +sf_execute_report sf_execute_report +sf_filter_dashboard_operators_list sf_filter_dashboard_operators_list +sf_filter_dashboard_options_analysis sf_filter_dashboard_options_analysis +sf_find_duplicates sf_find_duplicates +sf_find_duplicates_by_id sf_find_duplicates_by_id +sf_format_date sf_format_date +sf_format_datetime sf_format_datetime +sf_format_time sf_format_time +sf_format_time.AsIs sf_format_time +sf_format_time.character sf_format_time +sf_format_time.data.frame sf_format_time +sf_format_time.Date sf_format_time +sf_format_time.list sf_format_time +sf_format_time.logical sf_format_time +sf_format_time.NULL sf_format_time +sf_format_time.numeric sf_format_time +sf_format_time.POSIXct sf_format_time +sf_format_time.POSIXlt sf_format_time +sf_format_time.POSIXt sf_format_time +sf_get_all_jobs_bulk sf_get_all_jobs_bulk +sf_get_all_query_jobs_bulk sf_get_all_query_jobs_bulk +sf_get_dashboard_data sf_get_dashboard_data +sf_get_dashboard_results sf_get_dashboard_results +sf_get_dashboard_status sf_get_dashboard_status +sf_get_deleted sf_get_deleted +sf_get_job_bulk sf_get_job_bulk +sf_get_job_records_bulk sf_get_job_records_bulk +sf_get_report_instance_results sf_get_report_instance_results +sf_get_updated sf_get_updated +sf_guess_cols sf_guess_cols +sf_input_data_validation sf_input_data_validation +sf_job_batches_bulk sf_job_batches_bulk +sf_list_api_limits sf_list_api_limits +sf_list_dashboards sf_list_dashboards +sf_list_metadata sf_list_metadata +sf_list_objects sf_list_objects +sf_list_reports sf_list_reports +sf_list_report_fields sf_list_report_fields +sf_list_report_filter_operators sf_list_report_filter_operators +sf_list_report_instances sf_list_report_instances +sf_list_report_types sf_list_report_types +sf_list_resources sf_list_resources +sf_list_rest_api_versions sf_list_rest_api_versions +sf_merge sf_merge +sf_query sf_query +sf_query_bulk sf_run_bulk_query +sf_query_bulk_v1 sf_query_bulk_v1 +sf_query_bulk_v2 sf_query_bulk_v2 +sf_query_report sf_query_report +sf_query_result_bulk sf_query_result_bulk +sf_query_result_bulk_v1 sf_query_result_bulk_v1 +sf_query_result_bulk_v2 sf_query_result_bulk_v2 +sf_read_metadata sf_read_metadata +sf_refresh_dashboard sf_refresh_dashboard +sf_rename_metadata sf_rename_metadata +sf_reorder_cols sf_reorder_cols +sf_report_folders_list sf_report_folders_list +sf_report_folder_children sf_report_folder_children +sf_report_folder_create sf_report_folder_create +sf_report_folder_delete sf_report_folder_delete +sf_report_folder_describe sf_report_folder_describe +sf_report_folder_shares_add sf_report_folder_shares_add +sf_report_folder_shares_list sf_report_folder_shares_list +sf_report_folder_shares_update sf_report_folder_shares_update +sf_report_folder_share_delete sf_report_folder_share_delete +sf_report_folder_share_describe sf_report_folder_share_describe +sf_report_folder_share_recipients sf_report_folder_share_recipients +sf_report_folder_share_update sf_report_folder_share_update +sf_report_folder_update sf_report_folder_update +sf_reset_password sf_reset_password +sf_rest_list sf_rest_list +sf_retrieve sf_retrieve +sf_retrieve_metadata sf_retrieve_metadata +sf_retrieve_metadata_check_status sf_retrieve_metadata_check_status +sf_retrieve_rest sf_retrieve_rest +sf_retrieve_soap sf_retrieve_soap +sf_run_bulk_operation sf_run_bulk_operation +sf_run_bulk_query sf_run_bulk_query +sf_run_report sf_run_report +sf_search sf_search +sf_server_timestamp sf_server_timestamp +sf_session_id sf_session_id +sf_set_dashboard_sticky_filter sf_set_dashboard_sticky_filter +sf_set_password sf_set_password +sf_submit_query_bulk sf_submit_query_bulk +sf_undelete sf_undelete +sf_update sf_update +sf_update_attachment sf_update_attachment +sf_update_attachment_bulk_v1 sf_update_attachment_bulk_v1 +sf_update_attachment_rest sf_update_attachment_rest +sf_update_attachment_soap sf_update_attachment_soap +sf_update_bulk_v1 sf_update_bulk_v1 +sf_update_bulk_v2 sf_update_bulk_v2 +sf_update_dashboard sf_update_dashboard +sf_update_metadata sf_update_metadata +sf_update_report sf_update_report +sf_update_rest sf_update_rest +sf_update_soap sf_update_soap +sf_upload_complete_bulk sf_upload_complete_bulk +sf_upsert sf_upsert +sf_upsert_bulk_v1 sf_upsert_bulk_v1 +sf_upsert_bulk_v2 sf_upsert_bulk_v2 +sf_upsert_metadata sf_upsert_metadata +sf_upsert_rest sf_upsert_rest +sf_upsert_soap sf_upsert_soap +sf_user_info sf_user_info +sf_write_csv sf_write_csv +simplify_report_metadata simplify_report_metadata +stop_w_errors_listed stop_w_errors_listed +token_available token_available +unbox_list_elements unbox_list_elements +unbox_list_elements_recursively unbox_list_elements_recursively +unnest_col unnest_col +validate_get_all_jobs_params validate_get_all_jobs_params +valid_metadata_list valid_metadata_list +VERB_n VERB_n +warn_w_errors_listed warn_w_errors_listed +xmlToList2 xmlToList2 +xml_drop_and_unlist xml_drop_and_unlist +xml_drop_and_unlist_recursively xml_drop_and_unlist_recursively +xml_extract_parent_and_child_result xml_extract_parent_and_child_result +xml_nodeset_to_df xml_nodeset_to_df diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/aliases.rds b/revdep/library.noindex/salesforcer/new/salesforcer/help/aliases.rds new file mode 100644 index 00000000..3f800954 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/help/aliases.rds differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/cloud.png b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/cloud.png new file mode 100644 index 00000000..f3d90f71 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/cloud.png differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-archived.svg b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-archived.svg new file mode 100644 index 00000000..48f72a6f --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-archived.svg @@ -0,0 +1 @@ + lifecyclelifecyclearchivedarchived \ No newline at end of file diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-defunct.svg b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-defunct.svg new file mode 100644 index 00000000..01452e5f --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-defunct.svg @@ -0,0 +1 @@ +lifecyclelifecycledefunctdefunct \ No newline at end of file diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-deprecated.svg b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-deprecated.svg new file mode 100644 index 00000000..4baaee01 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-deprecated.svg @@ -0,0 +1 @@ +lifecyclelifecycledeprecateddeprecated \ No newline at end of file diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-experimental.svg b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-experimental.svg new file mode 100644 index 00000000..d1d060e9 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-experimental.svg @@ -0,0 +1 @@ +lifecyclelifecycleexperimentalexperimental \ No newline at end of file diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-maturing.svg b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-maturing.svg new file mode 100644 index 00000000..df713101 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-maturing.svg @@ -0,0 +1 @@ +lifecyclelifecyclematuringmaturing \ No newline at end of file diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-questioning.svg b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-questioning.svg new file mode 100644 index 00000000..08ee0c90 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-questioning.svg @@ -0,0 +1 @@ +lifecyclelifecyclequestioningquestioning \ No newline at end of file diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-soft-deprecated.svg b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-soft-deprecated.svg new file mode 100644 index 00000000..9f014fd1 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-soft-deprecated.svg @@ -0,0 +1 @@ +lifecyclelifecyclesoft-deprecatedsoft-deprecated \ No newline at end of file diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-stable.svg b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-stable.svg new file mode 100644 index 00000000..e015dc81 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-stable.svg @@ -0,0 +1 @@ +lifecyclelifecyclestablestable \ No newline at end of file diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-superseded.svg b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-superseded.svg new file mode 100644 index 00000000..75f24f55 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/lifecycle-superseded.svg @@ -0,0 +1 @@ + lifecyclelifecyclesupersededsuperseded \ No newline at end of file diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/logo.png b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/logo.png new file mode 100644 index 00000000..ecf5fa74 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/logo.png differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/old-logo.png b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/old-logo.png new file mode 100644 index 00000000..9e2ae3be Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/old-logo.png differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/old-salesforcer-hex.png b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/old-salesforcer-hex.png new file mode 100644 index 00000000..2fc28638 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/old-salesforcer-hex.png differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/old-salesforcer.png b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/old-salesforcer.png new file mode 100644 index 00000000..90772457 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/old-salesforcer.png differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/salesforcer.png b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/salesforcer.png new file mode 100644 index 00000000..ff56023c Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/help/figures/salesforcer.png differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/paths.rds b/revdep/library.noindex/salesforcer/new/salesforcer/help/paths.rds new file mode 100644 index 00000000..ca091d35 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/help/paths.rds differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/salesforcer.rdb b/revdep/library.noindex/salesforcer/new/salesforcer/help/salesforcer.rdb new file mode 100644 index 00000000..995f698a Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/help/salesforcer.rdb differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/help/salesforcer.rdx b/revdep/library.noindex/salesforcer/new/salesforcer/help/salesforcer.rdx new file mode 100644 index 00000000..3c11dcfd Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/salesforcer/help/salesforcer.rdx differ diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/html/00Index.html b/revdep/library.noindex/salesforcer/new/salesforcer/html/00Index.html new file mode 100644 index 00000000..bfa5c8f1 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/salesforcer/html/00Index.html @@ -0,0 +1,317 @@ + + +R: An Implementation of 'Salesforce' APIs Using Tidy Principles + + + +
+

An Implementation of 'Salesforce' APIs Using Tidy Principles + +

+
+
+[Up] +[Top] +

Documentation for package ‘salesforcer’ version 1.0.1.9999

+ + + +

Help Pages

+ + +

+C +M +P +R +S +V +

+ + +

-- C --

+ + + + +
collapse_list_with_dupe_namesCollapse Elements in List with Same Name
+ +

-- M --

+ + + + +
metadata_type_validatorMetadata Data Type Validator
+ +

-- P --

+ + + + +
parameterized_search_controlAuxiliary for Controlling Parametrized Searches
+ +

-- R --

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
rforcecom.bulkActionThe 'salesforcer' backwards compatible version of the RForcecom function 'rforcecom.bulkAction'
rforcecom.bulkQueryThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.bulkQuery'
rforcecom.createThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.create'
rforcecom.deleteThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.delete'
rforcecom.getObjectDescriptionThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.getObjectDescription'
rforcecom.getServerTimestampThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.getServerTimestamp'
rforcecom.loginThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.login'
rforcecom.queryThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.query'
rforcecom.retrieveThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.retrieve'
rforcecom.searchThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.search'
rforcecom.updateThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.update'
rforcecom.upsertThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.upsert'
+ +

-- S --

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
sf_abort_job_bulkAbort Bulk API Job
sf_analytics_notifications_limitsReturn limits of analytics notifications
sf_analytics_notifications_listList analytics notifications
sf_analytics_notification_createCreate an analytics notification
sf_analytics_notification_deleteDelete an analytics notification
sf_analytics_notification_describeDescribe an analytics notification
sf_analytics_notification_updateUpdate an analytics notification
sf_authLog in to Salesforce
sf_batch_details_bulkReturning the Details of a Batch in a Bulk API Job
sf_batch_status_bulkChecking the Status of a Batch in a Bulk API Job
sf_bulk_operationRun Bulk Operation
sf_close_job_bulkClose Bulk API Job
sf_controlAuxiliary for Controlling Calls to Salesforce APIs
sf_convert_leadConvert Leads
sf_copy_dashboardCopy a dashboard
sf_copy_reportCopy a report
sf_createCreate Records
sf_create_attachmentCreate Attachments
sf_create_batches_bulkAdd Batches to a Bulk API Job
sf_create_job_bulkCreate Bulk API Job
sf_create_metadataCreate Object or Field Metadata in Salesforce
sf_create_reportCreate a report
sf_deleteDelete Records
sf_delete_attachmentDelete Attachments
sf_delete_dashboardDelete a dashboard
sf_delete_job_bulkDelete Bulk API Job
sf_delete_metadataDelete Object or Field Metadata in Salesforce
sf_delete_reportDelete a report
sf_delete_report_instanceDelete a report instance
sf_describe_dashboardDescribe a dashboard
sf_describe_dashboard_componentsDescribe dashboard components
sf_describe_metadataDescribe the Metadata in an Organization
sf_describe_objectsSObject Basic Information
sf_describe_object_fieldsDescribe Object Fields
sf_describe_reportDescribe a report
sf_describe_report_typeDescribe a report type
sf_download_attachmentDownload an Attachment
sf_empty_recycle_binEmpty Recycle Bin
sf_execute_reportExecute a report
sf_filter_dashboard_operators_listList dashboard filter operators
sf_filter_dashboard_options_analysisGet an analysis of the filter options for a dashboard
sf_find_duplicatesFind Duplicate Records
sf_find_duplicates_by_idFind Duplicate Records By Id
sf_get_all_jobs_bulkGet All Bulk API Jobs
sf_get_all_query_jobs_bulkGet All Bulk API Query Jobs
sf_get_dashboard_dataGet dashboard data in a tabular format
sf_get_dashboard_resultsGet the results of an existing dashboard
sf_get_dashboard_statusGet the status of a dashboard
sf_get_deletedGet Deleted Records from a Timeframe
sf_get_job_bulkGet Bulk API Job
sf_get_job_records_bulkReturning the Details of a Bulk API Job
sf_get_report_instance_resultsGet report instance results
sf_get_updatedGet Updated Records from a Timeframe
sf_job_batches_bulkChecking the Status of a Batch in a Bulk API Job
sf_list_api_limitsList the Limits for an API
sf_list_dashboardsList dashboards
sf_list_metadataList All Objects of a Certain Metadata Type in Salesforce
sf_list_objectsList Organization Objects and their Metadata
sf_list_reportsList reports
sf_list_report_fieldsGet a list of report fields
sf_list_report_filter_operatorsList report filter operators
sf_list_report_instancesList report instances
sf_list_report_typesList report types
sf_list_resourcesList the Resources for an API
sf_list_rest_api_versionsList REST API Versions
sf_mergeMerge Records
sf_queryPerform SOQL Query
sf_query_bulkRun bulk query
sf_query_bulk_v1Run Bulk 1.0 query
sf_query_bulk_v2Run Bulk 2.0 query
sf_query_reportGet Report Data without Saving Changes to or Creating a Report
sf_query_result_bulkRetrieve the results of a completed bulk query
sf_query_result_bulk_v1Retrieve the results of a Bulk 1.0 query
sf_query_result_bulk_v2Retrieve the results of a Bulk 2.0 query
sf_read_metadataRead Object or Field Metadata from Salesforce
sf_refresh_dashboardRefresh an existing dashboard
sf_rename_metadataRename Metadata Elements in Salesforce
sf_report_folders_listList report folders
sf_report_folder_childrenGet the subfolders (children) of a report folder
sf_report_folder_createCreate report folder
sf_report_folder_deleteDelete a report folder
sf_report_folder_describeDescribe a report folder
sf_report_folder_shares_addAdd shares to a report folder
sf_report_folder_shares_listList the shares in a report folder
sf_report_folder_shares_updateUpdate the shares for a report folder
sf_report_folder_share_deleteDelete a report folder share
sf_report_folder_share_describeDescribe a report folder share
sf_report_folder_share_recipientsGet report folder share recipients
sf_report_folder_share_updateUpdate a report folder share
sf_report_folder_updateUpdate a report folder
sf_reset_passwordReset User Password
sf_retrieveRetrieve Records By Id
sf_retrieve_metadataMake A Request to Retrieve the Metadata
sf_run_bulk_operationRun Bulk Operation
sf_run_bulk_queryRun bulk query
sf_run_reportGet a report's data in tabular format
sf_searchPerform SOSL Search
sf_server_timestampSalesforce Server Timestamp
sf_set_dashboard_sticky_filterSet a sticky dashboard filter
sf_set_passwordSet User Password
sf_submit_query_bulkSubmit Bulk Query Batch to a Bulk API Job
sf_undeleteUndelete Records
sf_updateUpdate Records
sf_update_attachmentUpdate Attachments
sf_update_dashboardUpdate a dashboard
sf_update_metadataUpdate Object or Field Metadata in Salesforce
sf_update_reportUpdate a report
sf_upload_complete_bulkSignal Upload Complete to Bulk API Job
sf_upsertUpsert Records
sf_upsert_metadataUpsert Object or Field Metadata in Salesforce
sf_user_infoReturn Current User Info
+ +

-- V --

+ + + + +
valid_metadata_listList of Valid Data Types
+
diff --git a/revdep/library.noindex/salesforcer/new/salesforcer/html/R.css b/revdep/library.noindex/salesforcer/new/salesforcer/html/R.css new file mode 100644 index 00000000..c2289098 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/salesforcer/html/R.css @@ -0,0 +1,130 @@ +@media screen { + .container { + padding-right: 10px; + padding-left: 10px; + margin-right: auto; + margin-left: auto; + max-width: 900px; + } +} + +.rimage img { /* from knitr - for examples and demos */ + width: 96%; + margin-left: 2%; +} + +.katex { font-size: 1.1em; } + +code { + color: inherit; + background: inherit; +} + +body { + line-height: 1.4; + background: white; + color: black; +} + +a:link { + background: white; + color: blue; +} + +a:visited { + background: white; + color: rgb(50%, 0%, 50%); +} + +h1 { + background: white; + color: rgb(55%, 55%, 55%); + font-family: monospace; + font-size: 1.4em; /* x-large; */ + text-align: center; +} + +h2 { + background: white; + color: rgb(40%, 40%, 40%); + font-family: monospace; + font-size: 1.2em; /* large; */ + text-align: center; +} + +h3 { + background: white; + color: rgb(40%, 40%, 40%); + font-family: monospace; + font-size: 1.2em; /* large; */ +} + +h4 { + background: white; + color: rgb(40%, 40%, 40%); + font-family: monospace; + font-style: italic; + font-size: 1.2em; /* large; */ +} + +h5 { + background: white; + color: rgb(40%, 40%, 40%); + font-family: monospace; +} + +h6 { + background: white; + color: rgb(40%, 40%, 40%); + font-family: monospace; + font-style: italic; +} + +img.toplogo { + width: 4em; + vertical-align: middle; +} + +img.arrow { + width: 30px; + height: 30px; + border: 0; +} + +span.acronym { + font-size: small; +} + +span.env { + font-family: monospace; +} + +span.file { + font-family: monospace; +} + +span.option{ + font-family: monospace; +} + +span.pkg { + font-weight: bold; +} + +span.samp{ + font-family: monospace; +} + +div.vignettes a:hover { + background: rgb(85%, 85%, 85%); +} + +tr { + vertical-align: top; +} + +span.rlang { + font-family: Courier New, Courier; + color: #666666; +} + diff --git a/revdep/library.noindex/salesforcer/new/withr/DESCRIPTION b/revdep/library.noindex/salesforcer/new/withr/DESCRIPTION new file mode 100644 index 00000000..dee77ce9 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/DESCRIPTION @@ -0,0 +1,51 @@ +Package: withr +Title: Run Code 'With' Temporarily Modified Global State +Version: 3.0.2 +Authors@R: c( + person("Jim", "Hester", role = "aut"), + person("Lionel", "Henry", , "lionel@posit.co", role = c("aut", "cre")), + person("Kirill", "Müller", , "krlmlr+r@mailbox.org", role = "aut"), + person("Kevin", "Ushey", , "kevinushey@gmail.com", role = "aut"), + person("Hadley", "Wickham", , "hadley@posit.co", role = "aut"), + person("Winston", "Chang", role = "aut"), + person("Jennifer", "Bryan", role = "ctb"), + person("Richard", "Cotton", role = "ctb"), + person("Posit Software, PBC", role = c("cph", "fnd")) + ) +Description: A set of functions to run code 'with' safely and temporarily + modified global state. Many of these functions were originally a part + of the 'devtools' package, this provides a simple package with limited + dependencies to provide access to these functions. +License: MIT + file LICENSE +URL: https://withr.r-lib.org, https://github.com/r-lib/withr#readme +BugReports: https://github.com/r-lib/withr/issues +Depends: R (>= 3.6.0) +Imports: graphics, grDevices +Suggests: callr, DBI, knitr, methods, rlang, rmarkdown (>= 2.12), + RSQLite, testthat (>= 3.0.0) +VignetteBuilder: knitr +Config/Needs/website: tidyverse/tidytemplate +Config/testthat/edition: 3 +Encoding: UTF-8 +RoxygenNote: 7.3.2 +Collate: 'aaa.R' 'collate.R' 'connection.R' 'db.R' 'defer-exit.R' + 'standalone-defer.R' 'defer.R' 'devices.R' 'local_.R' 'with_.R' + 'dir.R' 'env.R' 'file.R' 'language.R' 'libpaths.R' 'locale.R' + 'makevars.R' 'namespace.R' 'options.R' 'par.R' 'path.R' 'rng.R' + 'seed.R' 'wrap.R' 'sink.R' 'tempfile.R' 'timezone.R' + 'torture.R' 'utils.R' 'with.R' +NeedsCompilation: no +Packaged: 2024-10-28 10:58:18 UTC; lionel +Author: Jim Hester [aut], + Lionel Henry [aut, cre], + Kirill Müller [aut], + Kevin Ushey [aut], + Hadley Wickham [aut], + Winston Chang [aut], + Jennifer Bryan [ctb], + Richard Cotton [ctb], + Posit Software, PBC [cph, fnd] +Maintainer: Lionel Henry +Repository: CRAN +Date/Publication: 2024-10-28 13:30:02 UTC +Built: R 4.4.1; ; 2024-10-28 13:49:02 UTC; unix diff --git a/revdep/library.noindex/salesforcer/new/withr/INDEX b/revdep/library.noindex/salesforcer/new/withr/INDEX new file mode 100644 index 00000000..e14842da --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/INDEX @@ -0,0 +1,24 @@ +defer Defer Evaluation of an Expression +devices Graphics devices +with_collate Collation Order +with_connection Connections which close themselves +with_db_connection DBMS Connections which disconnect themselves. +with_dir Working directory +with_envvar Environment variables +with_file Files which delete themselves +with_gctorture2 Torture Garbage Collector +with_language Language +with_libpaths Library paths +with_locale Locale settings +with_makevars Makevars variables +with_options Options +with_package Execute code with a modified search path +with_par Graphics parameters +with_path PATH environment variable +with_rng_version RNG version +with_seed Random seed +with_sink Output redirection +with_temp_libpaths Library paths +with_tempfile Temporary files and directories +with_timezone Time zone +withr Execute code in temporarily altered environment diff --git a/revdep/library.noindex/salesforcer/new/withr/LICENSE b/revdep/library.noindex/salesforcer/new/withr/LICENSE new file mode 100644 index 00000000..855af9ff --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/LICENSE @@ -0,0 +1,2 @@ +YEAR: 2020 +COPYRIGHT HOLDER: withr authors diff --git a/revdep/library.noindex/salesforcer/new/withr/Meta/Rd.rds b/revdep/library.noindex/salesforcer/new/withr/Meta/Rd.rds new file mode 100644 index 00000000..3d20df2f Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/withr/Meta/Rd.rds differ diff --git a/revdep/library.noindex/salesforcer/new/withr/Meta/features.rds b/revdep/library.noindex/salesforcer/new/withr/Meta/features.rds new file mode 100644 index 00000000..781f60d4 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/withr/Meta/features.rds differ diff --git a/revdep/library.noindex/salesforcer/new/withr/Meta/hsearch.rds b/revdep/library.noindex/salesforcer/new/withr/Meta/hsearch.rds new file mode 100644 index 00000000..05922484 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/withr/Meta/hsearch.rds differ diff --git a/revdep/library.noindex/salesforcer/new/withr/Meta/links.rds b/revdep/library.noindex/salesforcer/new/withr/Meta/links.rds new file mode 100644 index 00000000..867445e9 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/withr/Meta/links.rds differ diff --git a/revdep/library.noindex/salesforcer/new/withr/Meta/nsInfo.rds b/revdep/library.noindex/salesforcer/new/withr/Meta/nsInfo.rds new file mode 100644 index 00000000..b7b620ea Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/withr/Meta/nsInfo.rds differ diff --git a/revdep/library.noindex/salesforcer/new/withr/Meta/package.rds b/revdep/library.noindex/salesforcer/new/withr/Meta/package.rds new file mode 100644 index 00000000..c9677790 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/withr/Meta/package.rds differ diff --git a/revdep/library.noindex/salesforcer/new/withr/Meta/vignette.rds b/revdep/library.noindex/salesforcer/new/withr/Meta/vignette.rds new file mode 100644 index 00000000..3b393b23 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/withr/Meta/vignette.rds differ diff --git a/revdep/library.noindex/salesforcer/new/withr/NAMESPACE b/revdep/library.noindex/salesforcer/new/withr/NAMESPACE new file mode 100644 index 00000000..4cc4cff2 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/NAMESPACE @@ -0,0 +1,81 @@ +# Generated by roxygen2: do not edit by hand + +export(defer) +export(defer_parent) +export(deferred_clear) +export(deferred_run) +export(global_defer) +export(local_) +export(local_bmp) +export(local_cairo_pdf) +export(local_cairo_ps) +export(local_collate) +export(local_connection) +export(local_db_connection) +export(local_dir) +export(local_environment) +export(local_envvar) +export(local_file) +export(local_jpeg) +export(local_language) +export(local_libpaths) +export(local_locale) +export(local_makevars) +export(local_message_sink) +export(local_namespace) +export(local_options) +export(local_output_sink) +export(local_package) +export(local_par) +export(local_path) +export(local_pdf) +export(local_png) +export(local_postscript) +export(local_preserve_seed) +export(local_rng_version) +export(local_seed) +export(local_svg) +export(local_temp_libpaths) +export(local_tempdir) +export(local_tempfile) +export(local_tiff) +export(local_timezone) +export(local_xfig) +export(makevars_user) +export(set_makevars) +export(with_) +export(with_bmp) +export(with_cairo_pdf) +export(with_cairo_ps) +export(with_collate) +export(with_connection) +export(with_db_connection) +export(with_dir) +export(with_environment) +export(with_envvar) +export(with_file) +export(with_jpeg) +export(with_language) +export(with_libpaths) +export(with_locale) +export(with_makevars) +export(with_message_sink) +export(with_namespace) +export(with_options) +export(with_output_sink) +export(with_package) +export(with_par) +export(with_path) +export(with_pdf) +export(with_png) +export(with_postscript) +export(with_preserve_seed) +export(with_rng_version) +export(with_seed) +export(with_svg) +export(with_temp_libpaths) +export(with_tempdir) +export(with_tempfile) +export(with_tiff) +export(with_timezone) +export(with_xfig) diff --git a/revdep/library.noindex/salesforcer/new/withr/NEWS.md b/revdep/library.noindex/salesforcer/new/withr/NEWS.md new file mode 100644 index 00000000..5685970e --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/NEWS.md @@ -0,0 +1,274 @@ +# withr 3.0.2 + +* `local_language()` now never warns when set to `"C"` (#254). + This is a cross-platform and silent way of disabling `gettext()` + translations. + + +# withr 3.0.1 + +* Fixes for CRAN checks. + + +# withr 3.0.0 + +## Performance of withr + +* `defer()` is now a thin wrapper around `base::on.exit()`. This is + possible thanks to two contributions that we made to R 3.5: + + - We added an argument for LIFO cleanup: `on.exit(after = FALSE)`. + - Calling `sys.on.exit()` elsewhere than top-level didn't work. This + is needed for manual invocation with `deferred_run()`. + + Following this change, `defer()` is now much faster (although still + slower than `on.exit()` which is a primitive function and about as + fast as it gets). This also increases the compatibility of `defer()` + with `on.exit()` (all handlers are now run in the expected order + even if they are registered with `on.exit()`) and standalone + versions of `defer()`. + + +## Breaking change + +* When `source()` is used with a local environment, as opposed to + `globalenv()` (the default), you now need to set + `options(withr.hook_source = TRUE)` to get proper withr support + (running `defer()` or `local_` functions at top-level of a script). + This support is disabled by default in local environments to avoid a + performance penalty in normal usage of withr features. + + +## Other features and bugfixes + +* `deferred_run()` now reports the number of executed expressions with + a message. + +* `deferred_run()` can now be run at any point in a knitr file (#235). + +* `local_tempfile()` now writes `lines` in UTF-8 (#210) and always uses + `\n` for newlines (#216). + +* `local_pdf()` and friends now correctly restore to the previously + active device (#138). + +* `local_()` now works even if withr isn't attached (#207). + +* `local_par()` and `with_par()` now work if you don't set any parameters + (#238). + +* `with_language()` now properly resets the translation cache (#213). + +* Fixes for Debian packaging. + + +# withr 2.5.2 + +* Fixes for CRAN checks. + + +# withr 2.5.1 + +* Fixes for CRAN checks. + + +# withr 2.5.0 + +* `defer()` and all `local_*()` functions now work when run inside of + a `.Rmd`. The deferred expressions are executed when knitr exits. + +* `defer()` and `local_` functions now work within `source()`. + The deferred expressions are executed when `source()` exits. + +* `with_()` and `local_()` gain a `get` argument. Supply a getter + function to create `with` and `local` functions that are robust to + early exits. + + When supplied, this restoration pattern is used: + + ``` + old <- get() + on.exit(set(old)) + set(new) + action() + ``` + + Instead of: + + ``` + old <- set(new) + on.exit(set(old)) + action() + ``` + + This ensures proper restoration of the old state when an early exit + occurs during `set()` (for instance when a deprecation warning is + caught, see #191). + +* These `with_` and `local_` functions are now robust to early exits (see next bullet): + + - `_locale()` + - `_envvar()` + - `_libpaths()` + - `_options()` + - `_par()` + - `_path()` + - `_seed()` + +* `with_namespace()` and `local_namespace()` now pass `warn.conflicts` + to `attach()` (@kyleam, #185). + +* `local_rng_version()` and `local_seed()` no longer warn when + restoring `sample.kind` to `"Rounding"` (#167). + +* `with_seed()` now preserves the current values of `RNGkind()` (#167). + +* `with_collate()` is no longer affected by the `LC_COLLATE` + environment variable set to "C" (#179). + +* Local evaluations in the `globalenv()` (as opposed to top-level + ones) are now unwound in the same way as regular environments. + +* `local_tempfile()` gains a lines argument so, if desired, you can pre-fill + the temporary file with some data. + + +# withr 2.4.3 + +* Lionel Henry is the new maintainer. + +* Handlers registered with the global environment (as happens when `local_()` + is run at the top-level, outside a function) are now automatically run + when the R session ends (#173). + +* New `with_language()` and `local_language()` to temporarily control the + language used for translations (#180). + +* `with_seed()` now caches the check for R version, so is now faster (#170) + +* `with_makevars()` and `local_makevars()` now eagerly evaluate the `path` argument (#169) + +# withr 2.4.2 + +- `local_options()` now lets you set an option to `NULL` as intended (#156) + +- `local_tempfile()` argument `envir` is deprecated, in favor of `.local_envir`. + All withr functions except `local_tempfile()` used `.local_envir` to specify environments, so this makes this function consistent with the rest. (#157) + +- `with_environment()` now passing `pos` and `warn.conflicts` to `attach()`, as intended (#161). + +- `with_seed()` now also sets the RNG via new arguments `.rng_kind`, `.rng_normal_kind` and `.rng_sample_kind` + (#162, @AshesITR). + +- `with_timezone()` now works after recent changes to `Sys.timezone()` in R-devel (#165) + +# withr 2.4.1 + +- Tests which require `capabilities("cairo")` are now skipped. + +# withr 2.4.0 + +- withr is now licensed as MIT (#154). + +- Tests for `with_cairo_pdf()` and `with_cairo_ps()` have been removed, as they fail if Cairo is not available, such as with M1 macOS systems (#158) + +- `local_seed()` is now exported (#153) + +# withr 2.3.0 + +## Deprecations + +- `local_tempfile()` argument `new` is deprecated, in favor of returning the path to the new tempfile. + calls like `local_tempfile("xyz")` should be replaced with `xyx <- local_tempfile()` in your code (#141). + +## New features + +- New `local_seed()` function and `local_preserve_seed()` functions to correspond to `with_seed()` and `with_preserve_seed()` (#139). + +- New `local_tempdir()` function added to create a temp directory (#140) + +- `local_*()` functions now take dots (`...`), which can simplify calls in some cases, e.g. you can now use `local_options(foo = "bar")` rather than `local_options(c(foo = "bar"))`. + +## Minor improvements and fixes + +- `defer()` now throws an error if an error occurs in the deferred expression (#148) + +- `with_file()` and `local_file()` can now work if the file is actually a directory (#144). + +# withr 2.2.0 + +- `defer()` can set deferred events on `.GlobalEnv` to facilitate the interactive development of code inside a function or test. + Helpers `deferred_run()` (and `deferred_clear()`) provide a way to explicity run and clear (or just clear) deferred events (#76, @jennybc). + +- `with_connection()` now works when existing objects or connections exist with the same names (#120) + +- `with_makevars()` now uses `tools::makevars_user()` to determine the default user makevars file (#77, @siddharthab). + +- `with_options()` no longer uses `do.call()`, so optiosn are not evaluated on exit (#73, @mtmorgan). + +- `with_package()` no longer has the `help` argument (#94, @wendtke). + +- `with_package()` now does not try to detach the package if it is already attached before calling `with_package()` (#107) + +- `with_preserve_seed()` now restores `.Random.seed` if it is not set + originally (#124). + +- Add `with_rng_version()` and `local_rng_version()` functions to change the version of the RNG (#90, @gaborcsardi). + +- `with_svg()` documentation now is consistent across R versions (#129) + +- Add `with_timezone()` and `local_timezone()` functions to change the time zone (#92, @gaborcsardi). + +- `with_tempfile()` and `local_tempfile()` now delete recursively directories on exit (#84, @meta00). + +# withr 2.1.2 + +- `set_makevars()` is now exported (#68, @gaborcsardi). + +- `with_temp_libpaths()` gains an `action` argument, to specify how the + temporary library path will be added (#66, @krlmlr). + +# withr 2.1.1 + +- Fixes test failures with testthat 2.0.0 + +- `with_file()` function to automatically remove files. + +# withr 2.1.0 + +- `with_connection()` function to automatically close R file connections. + +- `with_db_connection()` function to automatically disconnect from DBI database + connections. + +- `with_gctorture2` command to run code with gctorture2, useful for testing + (#47). + +- `with_package()`, `with_namespace()` and `with_environment()` (and equivalent + locals) functions added, to run code with a modified object search path (#38, + #48). + +- Add `with_tempfile()` and `local_tempfile()` functions to create temporary + files which are cleanup up afterwards. (#32) + +- Remove the `code` argument from `local_` functions (#50). + +# withr 2.0.0 + +- Each `with_` function now has a `local_` variant, which reset at the end of + their local scope, generally at the end of the function body. + +- New functions `with_seed()` and `with_preserve_seed()` for running code with + a given random seed (#45, @krlmlr). + +# withr 1.0.2 +- `with_makevars()` gains an `assignment` argument to allow specifying + additional assignment types. + +# withr 1.0.1 +- Relaxed R version requirement to 3.0.2 (#35, #39). +- New `with_output_sink()` and `with_message_sink()` (#24). + +# withr 1.0.0 + +- First Public Release diff --git a/revdep/library.noindex/salesforcer/new/withr/R/withr b/revdep/library.noindex/salesforcer/new/withr/R/withr new file mode 100644 index 00000000..66861563 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/R/withr @@ -0,0 +1,27 @@ +# File share/R/nspackloader.R +# Part of the R package, https://www.R-project.org +# +# Copyright (C) 1995-2012 The R Core Team +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# A copy of the GNU General Public License is available at +# https://www.r-project.org/Licenses/ + +local({ + info <- loadingNamespaceInfo() + pkg <- info$pkgname + ns <- .getNamespace(as.name(pkg)) + if (is.null(ns)) + stop("cannot find namespace environment for ", pkg, domain = NA); + dbbase <- file.path(info$libname, pkg, "R", pkg) + lazyLoad(dbbase, ns, filter = function(n) n != ".__NAMESPACE__.") +}) diff --git a/revdep/library.noindex/salesforcer/new/withr/R/withr.rdb b/revdep/library.noindex/salesforcer/new/withr/R/withr.rdb new file mode 100644 index 00000000..400879d9 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/withr/R/withr.rdb differ diff --git a/revdep/library.noindex/salesforcer/new/withr/R/withr.rdx b/revdep/library.noindex/salesforcer/new/withr/R/withr.rdx new file mode 100644 index 00000000..adf13063 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/withr/R/withr.rdx differ diff --git a/revdep/library.noindex/salesforcer/new/withr/doc/index.html b/revdep/library.noindex/salesforcer/new/withr/doc/index.html new file mode 100644 index 00000000..fc108321 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/doc/index.html @@ -0,0 +1,29 @@ + + +R: Vignettes and other documentation + + + +
+

Vignettes and other documentation + +

+
+
+[Top] +
+

Vignettes from package 'withr'

+ +++++++ + + + + +
withr::withrChanging and restoring stateHTMLsourceR code
+
diff --git a/revdep/library.noindex/salesforcer/new/withr/doc/withr.R b/revdep/library.noindex/salesforcer/new/withr/doc/withr.R new file mode 100644 index 00000000..a570085a --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/doc/withr.R @@ -0,0 +1,184 @@ +## ----include = FALSE---------------------------------------------------------- +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) + +## ----setup-------------------------------------------------------------------- +library(withr) + +## ----include = FALSE---------------------------------------------------------- +op <- options() + +## ----------------------------------------------------------------------------- +sloppy <- function(x, sig_digits) { + options(digits = sig_digits) + print(x) +} + +pi + +sloppy(pi, 2) + +pi + +## ----include = FALSE---------------------------------------------------------- +options(op) + +## ----------------------------------------------------------------------------- +neat <- function(x, sig_digits) { + op <- options(digits = sig_digits) + on.exit(options(op), add = TRUE) + print(x) +} + +pi + +neat(pi, 2) + +pi + +## ----------------------------------------------------------------------------- +neater <- function(x, sig_digits) { + op <- options(digits = sig_digits) + defer(options(op)) + print(x) +} + +pi + +neater(pi, 2) + +pi + +## ----------------------------------------------------------------------------- +defer_stack <- function() { + cat("put on socks\n") + defer(cat("take off socks\n")) + + cat("put on shoes\n") + defer(cat("take off shoes\n")) +} +defer_stack() + +## ----------------------------------------------------------------------------- +on_exit_last_one_wins <- function() { + cat("put on socks\n") + on.exit(cat("take off socks\n")) + + cat("put on shoes\n") + on.exit(cat("take off shoes\n")) +} +on_exit_last_one_wins() + +## ----eval = getRversion() >= "3.5.0"------------------------------------------ +on_exit_stack <- function() { + cat("put on socks\n") + on.exit(cat("take off socks\n"), add = TRUE, after = FALSE) + + cat("put on shoes\n") + on.exit(cat("take off shoes\n"), add = TRUE, after = FALSE) +} +on_exit_stack() + +## ----------------------------------------------------------------------------- +defer_queue <- function() { + cat("Adam gets in line for ice cream\n") + defer(cat("Adam gets ice cream\n"), priority = "last") + + cat("Beth gets in line for ice cream\n") + defer(cat("Beth gets ice cream\n"), priority = "last") +} +defer_queue() + +## ----------------------------------------------------------------------------- +neater <- function(x, sig_digits) { + op <- options(digits = sig_digits) # record orig. "digits" & change "digits" + defer(options(op)) # schedule restoration of "digits" + + print(x) +} + +## ----------------------------------------------------------------------------- +local_digits <- function(sig_digits, envir = parent.frame()) { + op <- options(digits = sig_digits) + defer(options(op), envir = envir) +} + +## ----------------------------------------------------------------------------- +neato <- function(x, digits) { + local_digits(digits) + print(x) +} + +pi + +neato(pi, 2) + +neato(pi, 4) + +## ----------------------------------------------------------------------------- +neatful <- function(x) { + local_digits(1) + print(x) + local_digits(3) + print(x) + local_digits(5) + print(x) +} + +neatful(pi) + +## ----------------------------------------------------------------------------- +neatest <- function(x, sig_digits) { + local_options(list(digits = sig_digits)) + print(x) +} + +pi + +neatest(pi, 2) + +neatest(pi, 4) + +## ----eval = FALSE------------------------------------------------------------- +# neat_with <- function(x, sig_digits) { +# # imagine lots of code here +# withr::with_options( +# list(digits = sig_digits), +# print(x) +# ) +# # ... and a lot more code here +# } + +## ----eval = FALSE------------------------------------------------------------- +# neat_local <- function(x, sig_digits) { +# withr::local_options(list(digits = sig_digits)) +# print(x) +# # imagine lots of code here +# } + +## ----------------------------------------------------------------------------- +library(withr) + +defer(print("hi")) + +pi + +# this adds another deferred event, but does not re-message +local_digits(3) + +pi + +deferred_run() + +pi + +## ----eval = FALSE------------------------------------------------------------- +# defer(print("hi")) +# #> Setting global deferred event(s). +# #> i These will be run: +# #> * Automatically, when the R session ends. +# #> * On demand, if you call `withr::deferred_run()`. +# #> i Use `withr::deferred_clear()` to clear them without executing. + diff --git a/revdep/library.noindex/salesforcer/new/withr/doc/withr.Rmd b/revdep/library.noindex/salesforcer/new/withr/doc/withr.Rmd new file mode 100644 index 00000000..57659d53 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/doc/withr.Rmd @@ -0,0 +1,343 @@ +--- +title: "Changing and restoring state" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Changing and restoring state} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +```{r setup} +library(withr) +``` + + + +This article explains the type of problem withr solves and shows typical patterns of usage. +It also compares withr's functionality to the `on.exit()` function from base R. + +## It's dangerous to change state + +Whenever possible, it is desirable to write so-called **pure** functions. +The property we focus on here is that the function should not change the surrounding R landscape, i.e. it should not change things like the search path, global options, or the working directory. +If the behaviour of *other* functions differs before and after running your function, you've modified the landscape. +Changing the landscape is bad because it makes code much harder to understand. + +Here's a `sloppy()` function that prints a number with a specific number of significant digits, by adjusting R's global "digits" option. + +```{r include = FALSE} +op <- options() +``` + +```{r} +sloppy <- function(x, sig_digits) { + options(digits = sig_digits) + print(x) +} + +pi + +sloppy(pi, 2) + +pi +``` + +```{r include = FALSE} +options(op) +``` + +Notice how `pi` prints differently before and after the call to `sloppy()`? +Calling `sloppy()` has a side effect: it changes the "digits" option globally, not just within its own scope of operations. +This is what we want to avoid. + +*Don't worry, we're restoring global state (specifically, the "digits" option) behind the scenes here.* + +Sometimes you cannot avoid modifying the state of the world, in which case you just have to make sure that you put things back the way you found them. +This is what the withr package is for. + +## The base solution: `on.exit()` + +The first function to know about is base R's `on.exit()`. +Inside your function body, every time you do something that should be undone **on exit**, you immediately register the cleanup code with `on.exit(expr, add = TRUE)`[^on-exit-add]. + +[^on-exit-add]: It's too bad `add = TRUE` isn't the default, because you almost always want this. Without it, each call to `on.exit()` clobbers the effect of previous calls. + +`neat()` is an improvement over `sloppy()`, because it uses `on.exit()` to ensure that the "digits" option is restored to its original value. + +```{r} +neat <- function(x, sig_digits) { + op <- options(digits = sig_digits) + on.exit(options(op), add = TRUE) + print(x) +} + +pi + +neat(pi, 2) + +pi +``` + +`on.exit()` also works when you exit the function abnormally, i.e. due to error. +This is why official tools, like `on.exit()`, are a better choice than any do-it-yourself solution to this problem. + +`on.exit()` is a very useful function, but it's not very flexible. +The withr package provides an extensible `on.exit()`-inspired toolkit. + +## `defer()` is the foundation of withr + +`defer()` is the core function of withr and is very much like `on.exit()`, i.e. it schedules the execution of arbitrary code when the current function exits: + +```{r} +neater <- function(x, sig_digits) { + op <- options(digits = sig_digits) + defer(options(op)) + print(x) +} + +pi + +neater(pi, 2) + +pi +``` + +`withr::defer()` is basically a drop-in substitute for `on.exit()`, but with three key differences we explore below: + +1. Different default behaviour around the effect of a series of two or more + calls +1. Control over the environment the deferred events are associated with +1. Ability to work with the global environment + +Here we focus on using withr inside your functions. +See the blog post [Self-cleaning test fixtures](https://www.tidyverse.org/blog/2020/04/self-cleaning-test-fixtures/) or the testthat vignette [Test fixtures](https://testthat.r-lib.org/articles/test-fixtures.html) for how to use withr inside tests. + +## Last-in, first-out + +If you make more than one call to `defer()`, by default, it **adds** expressions to the **top** of the stack of deferred actions. + +```{r} +defer_stack <- function() { + cat("put on socks\n") + defer(cat("take off socks\n")) + + cat("put on shoes\n") + defer(cat("take off shoes\n")) +} +defer_stack() +``` + +In contrast, by default, a subsequent call to `on.exit()` **overwrites** the deferred actions registered in the previous call. + +```{r} +on_exit_last_one_wins <- function() { + cat("put on socks\n") + on.exit(cat("take off socks\n")) + + cat("put on shoes\n") + on.exit(cat("take off shoes\n")) +} +on_exit_last_one_wins() +``` + +Oops, we still have our socks on! +The last-in, first-out, stack-like behaviour of `defer()` tends to be what you want in most applications. + +To get such behaviour with `on.exit()`, remember to call it with `add = TRUE, after = FALSE`[^on-exit-after]. + +[^on-exit-after]: Note: the `after` argument of `on.exit()` first appeared in R 3.5.0. + +```{r, eval = getRversion() >= "3.5.0"} +on_exit_stack <- function() { + cat("put on socks\n") + on.exit(cat("take off socks\n"), add = TRUE, after = FALSE) + + cat("put on shoes\n") + on.exit(cat("take off shoes\n"), add = TRUE, after = FALSE) +} +on_exit_stack() +``` + +Conversely, if you want `defer()` to have first-in, first-out behaviour, specify `priority = "last"`. + +```{r} +defer_queue <- function() { + cat("Adam gets in line for ice cream\n") + defer(cat("Adam gets ice cream\n"), priority = "last") + + cat("Beth gets in line for ice cream\n") + defer(cat("Beth gets ice cream\n"), priority = "last") +} +defer_queue() +``` + +## "Local" functions (and "with" functions) + +Both `on.exit()` and `withr::defer()` schedule actions to be executed when a certain environment goes out of scope, most typically the execution environment of a function. +But the `envir` argument of `withr::defer()` lets you specify a *different* environment, which makes it possible to create customised `on.exit()` extensions. + +Let's look at the `neater()` function again. + +```{r} +neater <- function(x, sig_digits) { + op <- options(digits = sig_digits) # record orig. "digits" & change "digits" + defer(options(op)) # schedule restoration of "digits" + + print(x) +} +``` + +The first two lines are typical `on.exit()` maneuvers where, in some order, you record an original state, arrange for its eventual restoration, and +change it. +In real life, this can be much more involved and you might want to wrap this logic up into a helper function. +You can't wrap `on.exit()` in this way, because there's no way to reach back up into the correct parent frame and schedule cleanup there. +But with `defer()`, we can! +Here is such a custom helper, called `local_digits()`. + +```{r} +local_digits <- function(sig_digits, envir = parent.frame()) { + op <- options(digits = sig_digits) + defer(options(op), envir = envir) +} +``` + +We can use `local_digits()` to keep any manipulation of `digits` local to a function. + +```{r} +neato <- function(x, digits) { + local_digits(digits) + print(x) +} + +pi + +neato(pi, 2) + +neato(pi, 4) +``` + +You can even call `local_digits()` multiple times inside a function. +Each call to `local_digits()` is in effect until the next or until the function exits, which ever comes first. + +```{r} +neatful <- function(x) { + local_digits(1) + print(x) + local_digits(3) + print(x) + local_digits(5) + print(x) +} + +neatful(pi) +``` + +Certain state changes, such as modifying global options, come up so often that withr offers pre-made helpers. +These helpers come in two forms: `local_*()` functions, like the one we just made, and `with_*()` functions, which we explain below. +Here are the state change helpers in withr that you are most likely to find useful: + +| Do / undo this | withr functions | +|-----------------------------|-------------------------------------| +| Set an R option | `local_options()`,`with_options()` | +| Set an environment variable | `local_envvar()`, `with_envvar()` | +| Change working directory | `local_dir()`, `with_dir()` | +| Set a graphics parameter | `local_par()`, `with_par()` | + +We didn't really need to write our own `local_digits()` helper, because the built-in `withr::local_options()` also gets the job done: + +```{r} +neatest <- function(x, sig_digits) { + local_options(list(digits = sig_digits)) + print(x) +} + +pi + +neatest(pi, 2) + +neatest(pi, 4) +``` + +The `local_*()` functions target a slightly different use case from the `with_*()` functions, which are inspired by base R's `with()` function: + +* `with_*()` functions are best for executing a small snippet of code with a + modified state + ```{r eval = FALSE} + neat_with <- function(x, sig_digits) { + # imagine lots of code here + withr::with_options( + list(digits = sig_digits), + print(x) + ) + # ... and a lot more code here + } + ``` +* `local_*()` functions are best for modifying state "from now until the + function exits" + ```{r eval = FALSE} + neat_local <- function(x, sig_digits) { + withr::local_options(list(digits = sig_digits)) + print(x) + # imagine lots of code here + } + ``` + +It's best to minimize the footprint of your state modifications. +Therefore, use `with_*()` functions where you can. +But when this forces you to put lots of (indented) code inside `with_*()`, e.g. most of your function's body, then it's better to use `local_*()`. + +## Deferring events on the global environment + +Here is one last difference between `withr::defer()` and `on.exit()`: the ability to defer events on the global environment[^withr-2-2-0]. + +[^withr-2-2-0]: This feature first appeared in withr v2.2.0. + +At first, it sounds pretty weird to propose scheduling deferred actions on the global environment. +It's not ephemeral, the way function execution environments are. +It goes out of scope very rarely, i.e. when you exit R. +Why would you want this? + +The answer is: for development purposes. + +If you are developing functions or tests that use withr, it's very useful to be able to execute that code interactively, without error, and with the ability to trigger the deferred events. +It's hard to develop with functions that work one way inside a function, but another way in the global environment (or, worse, throw an error). + +Here's how `defer()` (and all functions based on it) works in an interactive session. + +```{r} +library(withr) + +defer(print("hi")) + +pi + +# this adds another deferred event, but does not re-message +local_digits(3) + +pi + +deferred_run() + +pi +``` + +Note that because this example is running in a vignette, it doesn't look exactly the same as what you'll see interactively. When you defer events on the global environment for the first time, you get this message that alerts you to the situation: + +```{r, eval = FALSE} +defer(print("hi")) +#> Setting global deferred event(s). +#> i These will be run: +#> * Automatically, when the R session ends. +#> * On demand, if you call `withr::deferred_run()`. +#> i Use `withr::deferred_clear()` to clear them without executing. +``` + +If you add subsequent events, the message is *not* repeated. +Since the global environment isn't perishable, like a test environment is, you have to call `deferred_run()` explicitly to execute the deferred events. You can also clear them, without running, with `deferred_clear()`. diff --git a/revdep/library.noindex/salesforcer/new/withr/doc/withr.html b/revdep/library.noindex/salesforcer/new/withr/doc/withr.html new file mode 100644 index 00000000..bfc53cf8 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/doc/withr.html @@ -0,0 +1,726 @@ + + + + + + + + + + + + + + +Changing and restoring state + + + + + + + + + + + + + + + + + + + + + + + + + + +

Changing and restoring state

+ + + +
library(withr)
+ +

This article explains the type of problem withr solves and shows +typical patterns of usage. It also compares withr’s functionality to the +on.exit() function from base R.

+
+

It’s dangerous to change state

+

Whenever possible, it is desirable to write so-called +pure functions. The property we focus on here is that +the function should not change the surrounding R landscape, i.e. it +should not change things like the search path, global options, or the +working directory. If the behaviour of other functions differs +before and after running your function, you’ve modified the landscape. +Changing the landscape is bad because it makes code much harder to +understand.

+

Here’s a sloppy() function that prints a number with a +specific number of significant digits, by adjusting R’s global “digits” +option.

+
sloppy <- function(x, sig_digits) {
+  options(digits = sig_digits)
+  print(x)
+}
+
+pi
+#> [1] 3.141593
+
+sloppy(pi, 2)
+#> [1] 3.1
+
+pi
+#> [1] 3.1
+

Notice how pi prints differently before and after the +call to sloppy()? Calling sloppy() has a side +effect: it changes the “digits” option globally, not just within its own +scope of operations. This is what we want to avoid.

+

Don’t worry, we’re restoring global state (specifically, the +“digits” option) behind the scenes here.

+

Sometimes you cannot avoid modifying the state of the world, in which +case you just have to make sure that you put things back the way you +found them. This is what the withr package is for.

+
+
+

The base solution: on.exit()

+

The first function to know about is base R’s on.exit(). +Inside your function body, every time you do something that should be +undone on exit, you immediately register the cleanup +code with on.exit(expr, add = TRUE)1.

+

neat() is an improvement over sloppy(), +because it uses on.exit() to ensure that the “digits” +option is restored to its original value.

+
neat <- function(x, sig_digits) {
+  op <- options(digits = sig_digits)
+  on.exit(options(op), add = TRUE)
+  print(x)
+}
+
+pi
+#> [1] 3.141593
+
+neat(pi, 2)
+#> [1] 3.1
+
+pi
+#> [1] 3.141593
+

on.exit() also works when you exit the function +abnormally, i.e. due to error. This is why official tools, like +on.exit(), are a better choice than any do-it-yourself +solution to this problem.

+

on.exit() is a very useful function, but it’s not very +flexible. The withr package provides an extensible +on.exit()-inspired toolkit.

+
+
+

defer() is the foundation of withr

+

defer() is the core function of withr and is very much +like on.exit(), i.e. it schedules the execution of +arbitrary code when the current function exits:

+
neater <- function(x, sig_digits) {
+  op <- options(digits = sig_digits)
+  defer(options(op))
+  print(x)
+}
+
+pi
+#> [1] 3.141593
+
+neater(pi, 2)
+#> [1] 3.1
+
+pi
+#> [1] 3.141593
+

withr::defer() is basically a drop-in substitute for +on.exit(), but with three key differences we explore +below:

+
    +
  1. Different default behaviour around the effect of a series of two or +more calls
  2. +
  3. Control over the environment the deferred events are associated +with
  4. +
  5. Ability to work with the global environment
  6. +
+

Here we focus on using withr inside your functions. See the blog post +Self-cleaning +test fixtures or the testthat vignette Test +fixtures for how to use withr inside tests.

+
+
+

Last-in, first-out

+

If you make more than one call to defer(), by default, +it adds expressions to the top of the +stack of deferred actions.

+
defer_stack <- function() {
+  cat("put on socks\n")
+  defer(cat("take off socks\n"))
+  
+  cat("put on shoes\n")
+  defer(cat("take off shoes\n"))
+}
+defer_stack()
+#> put on socks
+#> put on shoes
+#> take off shoes
+#> take off socks
+

In contrast, by default, a subsequent call to on.exit() +overwrites the deferred actions registered in the +previous call.

+
on_exit_last_one_wins <- function() {
+  cat("put on socks\n")
+  on.exit(cat("take off socks\n"))
+  
+  cat("put on shoes\n")
+  on.exit(cat("take off shoes\n"))
+}
+on_exit_last_one_wins()
+#> put on socks
+#> put on shoes
+#> take off shoes
+

Oops, we still have our socks on! The last-in, first-out, stack-like +behaviour of defer() tends to be what you want in most +applications.

+

To get such behaviour with on.exit(), remember to call +it with add = TRUE, after = FALSE2.

+
on_exit_stack <- function() {
+  cat("put on socks\n")
+  on.exit(cat("take off socks\n"), add = TRUE, after = FALSE)
+  
+  cat("put on shoes\n")
+  on.exit(cat("take off shoes\n"), add = TRUE, after = FALSE)
+}
+on_exit_stack()
+#> put on socks
+#> put on shoes
+#> take off shoes
+#> take off socks
+

Conversely, if you want defer() to have first-in, +first-out behaviour, specify priority = "last".

+
defer_queue <- function() {
+  cat("Adam gets in line for ice cream\n")
+  defer(cat("Adam gets ice cream\n"), priority = "last")
+
+  cat("Beth gets in line for ice cream\n")
+  defer(cat("Beth gets ice cream\n"), priority = "last")
+}
+defer_queue()
+#> Adam gets in line for ice cream
+#> Beth gets in line for ice cream
+#> Adam gets ice cream
+#> Beth gets ice cream
+
+
+

“Local” functions (and “with” functions)

+

Both on.exit() and withr::defer() schedule +actions to be executed when a certain environment goes out of scope, +most typically the execution environment of a function. But the +envir argument of withr::defer() lets you +specify a different environment, which makes it possible to +create customised on.exit() extensions.

+

Let’s look at the neater() function again.

+
neater <- function(x, sig_digits) {
+  op <- options(digits = sig_digits) # record orig. "digits" & change "digits"
+  defer(options(op))                 # schedule restoration of "digits"
+  
+  print(x)
+}
+

The first two lines are typical on.exit() maneuvers +where, in some order, you record an original state, arrange for its +eventual restoration, and change it. In real life, this can be much more +involved and you might want to wrap this logic up into a helper +function. You can’t wrap on.exit() in this way, because +there’s no way to reach back up into the correct parent frame and +schedule cleanup there. But with defer(), we can! Here is +such a custom helper, called local_digits().

+
local_digits <- function(sig_digits, envir = parent.frame()) {
+  op <- options(digits = sig_digits)
+  defer(options(op), envir = envir)
+}
+

We can use local_digits() to keep any manipulation of +digits local to a function.

+
neato <- function(x, digits) {
+  local_digits(digits)
+  print(x)
+}
+
+pi
+#> [1] 3.141593
+
+neato(pi, 2)
+#> [1] 3.1
+
+neato(pi, 4)
+#> [1] 3.142
+

You can even call local_digits() multiple times inside a +function. Each call to local_digits() is in effect until +the next or until the function exits, which ever comes first.

+
neatful <- function(x) {
+  local_digits(1)
+  print(x)
+  local_digits(3)
+  print(x)
+  local_digits(5)
+  print(x)
+}
+
+neatful(pi)
+#> [1] 3
+#> [1] 3.14
+#> [1] 3.1416
+

Certain state changes, such as modifying global options, come up so +often that withr offers pre-made helpers. These helpers come in two +forms: local_*() functions, like the one we just made, and +with_*() functions, which we explain below. Here are the +state change helpers in withr that you are most likely to find +useful:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Do / undo thiswithr functions
Set an R optionlocal_options(),with_options()
Set an environment variablelocal_envvar(), with_envvar()
Change working directorylocal_dir(), with_dir()
Set a graphics parameterlocal_par(), with_par()
+

We didn’t really need to write our own local_digits() +helper, because the built-in withr::local_options() also +gets the job done:

+
neatest <- function(x, sig_digits) {
+  local_options(list(digits = sig_digits))
+  print(x)
+}
+
+pi
+#> [1] 3.141593
+
+neatest(pi, 2)
+#> [1] 3.1
+
+neatest(pi, 4)
+#> [1] 3.142
+

The local_*() functions target a slightly different use +case from the with_*() functions, which are inspired by +base R’s with() function:

+
    +
  • with_*() functions are best for executing a small +snippet of code with a modified state

    +
    neat_with <- function(x, sig_digits) {
    +  # imagine lots of code here
    +  withr::with_options(
    +    list(digits = sig_digits),
    +    print(x)
    +  )
    +  # ... and a lot more code here
    +}
  • +
  • local_*() functions are best for modifying state +“from now until the function exits”

    +
    neat_local <- function(x, sig_digits) {
    +  withr::local_options(list(digits = sig_digits))
    +  print(x)
    +  # imagine lots of code here
    +}
  • +
+

It’s best to minimize the footprint of your state modifications. +Therefore, use with_*() functions where you can. But when +this forces you to put lots of (indented) code inside +with_*(), e.g. most of your function’s body, then it’s +better to use local_*().

+
+
+

Deferring events on the global environment

+

Here is one last difference between withr::defer() and +on.exit(): the ability to defer events on the global +environment3.

+

At first, it sounds pretty weird to propose scheduling deferred +actions on the global environment. It’s not ephemeral, the way function +execution environments are. It goes out of scope very rarely, i.e. when +you exit R. Why would you want this?

+

The answer is: for development purposes.

+

If you are developing functions or tests that use withr, it’s very +useful to be able to execute that code interactively, without error, and +with the ability to trigger the deferred events. It’s hard to develop +with functions that work one way inside a function, but another way in +the global environment (or, worse, throw an error).

+

Here’s how defer() (and all functions based on it) works +in an interactive session.

+
library(withr)
+
+defer(print("hi"))
+
+pi
+#> [1] 3.141593
+
+# this adds another deferred event, but does not re-message
+local_digits(3)
+
+pi
+#> [1] 3.14
+
+deferred_run()
+#> [1] "hi"
+#> Ran 2/2 deferred expressions
+
+pi
+#> [1] 3.141593
+

Note that because this example is running in a vignette, it doesn’t +look exactly the same as what you’ll see interactively. When you defer +events on the global environment for the first time, you get this +message that alerts you to the situation:

+
defer(print("hi"))
+#> Setting global deferred event(s).
+#> i These will be run:
+#>   * Automatically, when the R session ends.
+#>   * On demand, if you call `withr::deferred_run()`.
+#> i Use `withr::deferred_clear()` to clear them without executing.
+

If you add subsequent events, the message is not repeated. +Since the global environment isn’t perishable, like a test environment +is, you have to call deferred_run() explicitly to execute +the deferred events. You can also clear them, without running, with +deferred_clear().

+
+
+
+
    +
  1. It’s too bad add = TRUE isn’t the default, +because you almost always want this. Without it, each call to +on.exit() clobbers the effect of previous calls.↩︎

  2. +
  3. Note: the after argument of +on.exit() first appeared in R 3.5.0.↩︎

  4. +
  5. This feature first appeared in withr v2.2.0.↩︎

  6. +
+
+ + + + + + + + + + + diff --git a/revdep/library.noindex/salesforcer/new/withr/help/AnIndex b/revdep/library.noindex/salesforcer/new/withr/help/AnIndex new file mode 100644 index 00000000..4511aed3 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/help/AnIndex @@ -0,0 +1,86 @@ +withr-package withr +defer defer +deferred_clear defer +deferred_run defer +defer_parent defer +devices devices +global_defer global_defer +local_ with_ +local_bmp devices +local_cairo_pdf devices +local_cairo_ps devices +local_collate with_collate +local_connection with_connection +local_db_connection with_db_connection +local_dir with_dir +local_environment with_package +local_envvar with_envvar +local_file with_file +local_jpeg devices +local_language with_language +local_libpaths with_libpaths +local_locale with_locale +local_makevars with_makevars +local_message_sink with_sink +local_namespace with_package +local_options with_options +local_output_sink with_sink +local_package with_package +local_par with_par +local_path with_path +local_pdf devices +local_png devices +local_postscript devices +local_preserve_seed with_seed +local_rng_version with_rng_version +local_seed with_seed +local_svg devices +local_tempdir with_tempfile +local_tempfile with_tempfile +local_temp_libpaths with_temp_libpaths +local_tiff devices +local_timezone with_timezone +local_xfig devices +makevars_user makevars_user +set_makevars set_makevars +withr withr +with_ with_ +with_bmp devices +with_cairo_pdf devices +with_cairo_ps devices +with_collate with_collate +with_connection with_connection +with_db_connection with_db_connection +with_dev devices +with_device devices +with_dir with_dir +with_environment with_package +with_envvar with_envvar +with_file with_file +with_gctorture2 with_gctorture2 +with_jpeg devices +with_language with_language +with_libpaths with_libpaths +with_locale with_locale +with_makevars with_makevars +with_message_sink with_sink +with_namespace with_package +with_options with_options +with_output_sink with_sink +with_package with_package +with_par with_par +with_path with_path +with_pdf devices +with_png devices +with_postscript devices +with_preserve_seed with_seed +with_rng_version with_rng_version +with_seed with_seed +with_sink with_sink +with_svg devices +with_tempdir with_tempfile +with_tempfile with_tempfile +with_temp_libpaths with_temp_libpaths +with_tiff devices +with_timezone with_timezone +with_xfig devices diff --git a/revdep/library.noindex/salesforcer/new/withr/help/aliases.rds b/revdep/library.noindex/salesforcer/new/withr/help/aliases.rds new file mode 100644 index 00000000..8487eae3 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/withr/help/aliases.rds differ diff --git a/revdep/library.noindex/salesforcer/new/withr/help/figures/README-unnamed-chunk-3-1.png b/revdep/library.noindex/salesforcer/new/withr/help/figures/README-unnamed-chunk-3-1.png new file mode 100644 index 00000000..4cf82a9a Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/withr/help/figures/README-unnamed-chunk-3-1.png differ diff --git a/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-archived.svg b/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-archived.svg new file mode 100644 index 00000000..745ab0c7 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-archived.svg @@ -0,0 +1,21 @@ + + lifecycle: archived + + + + + + + + + + + + + + + lifecycle + + archived + + diff --git a/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-defunct.svg b/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-defunct.svg new file mode 100644 index 00000000..d5c9559e --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-defunct.svg @@ -0,0 +1,21 @@ + + lifecycle: defunct + + + + + + + + + + + + + + + lifecycle + + defunct + + diff --git a/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-deprecated.svg b/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-deprecated.svg new file mode 100644 index 00000000..b61c57c3 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-deprecated.svg @@ -0,0 +1,21 @@ + + lifecycle: deprecated + + + + + + + + + + + + + + + lifecycle + + deprecated + + diff --git a/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-experimental.svg b/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-experimental.svg new file mode 100644 index 00000000..5d88fc2c --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-experimental.svg @@ -0,0 +1,21 @@ + + lifecycle: experimental + + + + + + + + + + + + + + + lifecycle + + experimental + + diff --git a/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-maturing.svg b/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-maturing.svg new file mode 100644 index 00000000..897370ec --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-maturing.svg @@ -0,0 +1,21 @@ + + lifecycle: maturing + + + + + + + + + + + + + + + lifecycle + + maturing + + diff --git a/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-questioning.svg b/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-questioning.svg new file mode 100644 index 00000000..7c1721d0 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-questioning.svg @@ -0,0 +1,21 @@ + + lifecycle: questioning + + + + + + + + + + + + + + + lifecycle + + questioning + + diff --git a/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-soft-deprecated.svg b/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-soft-deprecated.svg new file mode 100644 index 00000000..9c166ff3 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-soft-deprecated.svg @@ -0,0 +1,21 @@ + + lifecycle: soft-deprecated + + + + + + + + + + + + + + + lifecycle + + soft-deprecated + + diff --git a/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-stable.svg b/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-stable.svg new file mode 100644 index 00000000..9bf21e76 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-stable.svg @@ -0,0 +1,29 @@ + + lifecycle: stable + + + + + + + + + + + + + + + + lifecycle + + + + stable + + + diff --git a/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-superseded.svg b/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-superseded.svg new file mode 100644 index 00000000..db8d757f --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/help/figures/lifecycle-superseded.svg @@ -0,0 +1,21 @@ + + lifecycle: superseded + + + + + + + + + + + + + + + lifecycle + + superseded + + diff --git a/revdep/library.noindex/salesforcer/new/withr/help/figures/logo.png b/revdep/library.noindex/salesforcer/new/withr/help/figures/logo.png new file mode 100644 index 00000000..935cb298 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/withr/help/figures/logo.png differ diff --git a/revdep/library.noindex/salesforcer/new/withr/help/paths.rds b/revdep/library.noindex/salesforcer/new/withr/help/paths.rds new file mode 100644 index 00000000..143f5fad Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/withr/help/paths.rds differ diff --git a/revdep/library.noindex/salesforcer/new/withr/help/withr.rdb b/revdep/library.noindex/salesforcer/new/withr/help/withr.rdb new file mode 100644 index 00000000..a7a9ae0c Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/withr/help/withr.rdb differ diff --git a/revdep/library.noindex/salesforcer/new/withr/help/withr.rdx b/revdep/library.noindex/salesforcer/new/withr/help/withr.rdx new file mode 100644 index 00000000..0c4fd4e2 Binary files /dev/null and b/revdep/library.noindex/salesforcer/new/withr/help/withr.rdx differ diff --git a/revdep/library.noindex/salesforcer/new/withr/html/00Index.html b/revdep/library.noindex/salesforcer/new/withr/html/00Index.html new file mode 100644 index 00000000..f136845e --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/html/00Index.html @@ -0,0 +1,189 @@ + + +R: Run Code 'With' Temporarily Modified Global State + + + +
+

Run Code 'With' Temporarily Modified Global State + +

+
+
+[Up] +[Top] +

Documentation for package ‘withr’ version 3.0.2

+ + + +

Help Pages

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
withr-packageExecute code in temporarily altered environment
deferDefer Evaluation of an Expression
deferred_clearDefer Evaluation of an Expression
deferred_runDefer Evaluation of an Expression
defer_parentDefer Evaluation of an Expression
devicesGraphics devices
local_bmpGraphics devices
local_cairo_pdfGraphics devices
local_cairo_psGraphics devices
local_collateCollation Order
local_connectionConnections which close themselves
local_db_connectionDBMS Connections which disconnect themselves.
local_dirWorking directory
local_environmentExecute code with a modified search path
local_envvarEnvironment variables
local_fileFiles which delete themselves
local_jpegGraphics devices
local_languageLanguage
local_libpathsLibrary paths
local_localeLocale settings
local_makevarsMakevars variables
local_message_sinkOutput redirection
local_namespaceExecute code with a modified search path
local_optionsOptions
local_output_sinkOutput redirection
local_packageExecute code with a modified search path
local_parGraphics parameters
local_pathPATH environment variable
local_pdfGraphics devices
local_pngGraphics devices
local_postscriptGraphics devices
local_preserve_seedRandom seed
local_rng_versionRNG version
local_seedRandom seed
local_svgGraphics devices
local_tempdirTemporary files and directories
local_tempfileTemporary files and directories
local_temp_libpathsLibrary paths
local_tiffGraphics devices
local_timezoneTime zone
local_xfigGraphics devices
withrExecute code in temporarily altered environment
with_bmpGraphics devices
with_cairo_pdfGraphics devices
with_cairo_psGraphics devices
with_collateCollation Order
with_connectionConnections which close themselves
with_db_connectionDBMS Connections which disconnect themselves.
with_devGraphics devices
with_deviceGraphics devices
with_dirWorking directory
with_environmentExecute code with a modified search path
with_envvarEnvironment variables
with_fileFiles which delete themselves
with_gctorture2Torture Garbage Collector
with_jpegGraphics devices
with_languageLanguage
with_libpathsLibrary paths
with_localeLocale settings
with_makevarsMakevars variables
with_message_sinkOutput redirection
with_namespaceExecute code with a modified search path
with_optionsOptions
with_output_sinkOutput redirection
with_packageExecute code with a modified search path
with_parGraphics parameters
with_pathPATH environment variable
with_pdfGraphics devices
with_pngGraphics devices
with_postscriptGraphics devices
with_preserve_seedRandom seed
with_rng_versionRNG version
with_seedRandom seed
with_sinkOutput redirection
with_svgGraphics devices
with_tempdirTemporary files and directories
with_tempfileTemporary files and directories
with_temp_libpathsLibrary paths
with_tiffGraphics devices
with_timezoneTime zone
with_xfigGraphics devices
+
diff --git a/revdep/library.noindex/salesforcer/new/withr/html/R.css b/revdep/library.noindex/salesforcer/new/withr/html/R.css new file mode 100644 index 00000000..c2289098 --- /dev/null +++ b/revdep/library.noindex/salesforcer/new/withr/html/R.css @@ -0,0 +1,130 @@ +@media screen { + .container { + padding-right: 10px; + padding-left: 10px; + margin-right: auto; + margin-left: auto; + max-width: 900px; + } +} + +.rimage img { /* from knitr - for examples and demos */ + width: 96%; + margin-left: 2%; +} + +.katex { font-size: 1.1em; } + +code { + color: inherit; + background: inherit; +} + +body { + line-height: 1.4; + background: white; + color: black; +} + +a:link { + background: white; + color: blue; +} + +a:visited { + background: white; + color: rgb(50%, 0%, 50%); +} + +h1 { + background: white; + color: rgb(55%, 55%, 55%); + font-family: monospace; + font-size: 1.4em; /* x-large; */ + text-align: center; +} + +h2 { + background: white; + color: rgb(40%, 40%, 40%); + font-family: monospace; + font-size: 1.2em; /* large; */ + text-align: center; +} + +h3 { + background: white; + color: rgb(40%, 40%, 40%); + font-family: monospace; + font-size: 1.2em; /* large; */ +} + +h4 { + background: white; + color: rgb(40%, 40%, 40%); + font-family: monospace; + font-style: italic; + font-size: 1.2em; /* large; */ +} + +h5 { + background: white; + color: rgb(40%, 40%, 40%); + font-family: monospace; +} + +h6 { + background: white; + color: rgb(40%, 40%, 40%); + font-family: monospace; + font-style: italic; +} + +img.toplogo { + width: 4em; + vertical-align: middle; +} + +img.arrow { + width: 30px; + height: 30px; + border: 0; +} + +span.acronym { + font-size: small; +} + +span.env { + font-family: monospace; +} + +span.file { + font-family: monospace; +} + +span.option{ + font-family: monospace; +} + +span.pkg { + font-weight: bold; +} + +span.samp{ + font-family: monospace; +} + +div.vignettes a:hover { + background: rgb(85%, 85%, 85%); +} + +tr { + vertical-align: top; +} + +span.rlang { + font-family: Courier New, Courier; + color: #666666; +} + diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/DESCRIPTION b/revdep/library.noindex/salesforcer/old/salesforcer/DESCRIPTION new file mode 100644 index 00000000..1cd9499d --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/DESCRIPTION @@ -0,0 +1,58 @@ +Package: salesforcer +Title: An Implementation of 'Salesforce' APIs Using Tidy Principles +Version: 1.0.1 +Date: 2022-02-28 +Description: Functions connecting to the 'Salesforce' Platform APIs (REST, SOAP, + Bulk 1.0, Bulk 2.0, Metadata, Reports and Dashboards) + . + "API" is an acronym for "application programming interface". Most all calls + from these APIs are supported as they use CSV, XML or JSON data that can be + parsed into R data structures. For more details please see the 'Salesforce' + API documentation and this package's website + for more information, + documentation, and examples. +Authors@R: + c(person(given = c("Steven", "M."), + family = "Mortimer", + role = c("aut", "cre"), + email = "mortimer.steven.m@gmail.com"), + person(given = "Takekatsu", + family = "Hiramura", + role = "ctb", + email = "thira@plavox.info"), + person(given = "Jennifer", + family = "Bryan", + role = c("ctb", "cph"), + email = "jenny@rstudio.com"), + person(given = "Joanna", + family = "Zhao", + role = c("ctb", "cph"), + email = "joanna.zhao@alumni.ubc.ca")) +License: MIT + file LICENSE +URL: https://github.com/StevenMMortimer/salesforcer +BugReports: https://github.com/StevenMMortimer/salesforcer/issues +Depends: R (>= 3.6.0) +Imports: methods (>= 3.6.0), utils (>= 3.6.0), stats (>= 3.6.0), dplyr + (>= 1.0.0), purrr (>= 0.3.4), vctrs (>= 0.3.4), tibble (>= + 3.0.3), readr (>= 1.3.1), lubridate (>= 1.7.8), anytime (>= + 0.3.9), rlang (>= 0.4.7), httr (>= 1.4.1), curl (>= 4.3), + data.table (>= 1.13.0), XML (>= 3.99-0.3), xml2 (>= 1.3.2), + jsonlite (>= 1.6.1), rlist (>= 0.4.6.1), zip (>= 2.0.4), + base64enc (>= 0.1-3), mime (>= 0.9), lifecycle (>= 0.2.0) +Suggests: knitr, rmarkdown, testthat, spelling, here, microbenchmark, + ggplot2, sessioninfo +VignetteBuilder: knitr +ByteCompile: true +Encoding: UTF-8 +Language: en-US +RoxygenNote: 7.1.2 +NeedsCompilation: no +Packaged: 2022-03-01 21:31:36 UTC; steven.mortimer +Author: Steven M. Mortimer [aut, cre], + Takekatsu Hiramura [ctb], + Jennifer Bryan [ctb, cph], + Joanna Zhao [ctb, cph] +Maintainer: Steven M. Mortimer +Repository: CRAN +Date/Publication: 2022-03-01 21:50:02 UTC +Built: R 4.4.0; ; 2024-06-02 00:07:24 UTC; unix diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/INDEX b/revdep/library.noindex/salesforcer/old/salesforcer/INDEX new file mode 100644 index 00000000..58cb50c9 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/INDEX @@ -0,0 +1,191 @@ +collapse_list_with_dupe_names + Collapse Elements in List with Same Name +metadata_type_validator + Metadata Data Type Validator +parameterized_search_control + Auxiliary for Controlling Parametrized Searches +rforcecom.bulkAction The 'salesforcer' backwards compatible version + of the RForcecom function + 'rforcecom.bulkAction' +rforcecom.bulkQuery The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.bulkQuery' +rforcecom.create The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.create' +rforcecom.delete The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.delete' +rforcecom.getObjectDescription + The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.getObjectDescription' +rforcecom.getServerTimestamp + The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.getServerTimestamp' +rforcecom.login The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.login' +rforcecom.query The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.query' +rforcecom.retrieve The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.retrieve' +rforcecom.search The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.search' +rforcecom.update The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.update' +rforcecom.upsert The 'salesforcer' backwards compatible version + of 'RForcecom::rforcecom.upsert' +sf_abort_job_bulk Abort Bulk API Job +sf_analytics_notification_create + Create an analytics notification +sf_analytics_notification_delete + Delete an analytics notification +sf_analytics_notification_describe + Describe an analytics notification +sf_analytics_notification_update + Update an analytics notification +sf_analytics_notifications_limits + Return limits of analytics notifications +sf_analytics_notifications_list + List analytics notifications +sf_auth Log in to Salesforce +sf_batch_details_bulk Returning the Details of a Batch in a Bulk API + Job +sf_batch_status_bulk Checking the Status of a Batch in a Bulk API + Job +sf_close_job_bulk Close Bulk API Job +sf_control Auxiliary for Controlling Calls to Salesforce + APIs +sf_convert_lead Convert Leads +sf_copy_dashboard Copy a dashboard +sf_copy_report Copy a report +sf_create Create Records +sf_create_attachment Create Attachments +sf_create_batches_bulk + Add Batches to a Bulk API Job +sf_create_job_bulk Create Bulk API Job +sf_create_metadata Create Object or Field Metadata in Salesforce +sf_create_report Create a report +sf_delete Delete Records +sf_delete_attachment Delete Attachments +sf_delete_dashboard Delete a dashboard +sf_delete_job_bulk Delete Bulk API Job +sf_delete_metadata Delete Object or Field Metadata in Salesforce +sf_delete_report Delete a report +sf_delete_report_instance + Delete a report instance +sf_describe_dashboard Describe a dashboard +sf_describe_dashboard_components + Describe dashboard components +sf_describe_metadata Describe the Metadata in an Organization +sf_describe_object_fields + Describe Object Fields +sf_describe_objects SObject Basic Information +sf_describe_report Describe a report +sf_describe_report_type + Describe a report type +sf_download_attachment + Download an Attachment +sf_empty_recycle_bin Empty Recycle Bin +sf_execute_report Execute a report +sf_filter_dashboard_operators_list + List dashboard filter operators +sf_filter_dashboard_options_analysis + Get an analysis of the filter options for a + dashboard +sf_find_duplicates Find Duplicate Records +sf_find_duplicates_by_id + Find Duplicate Records By Id +sf_get_all_jobs_bulk Get All Bulk API Jobs +sf_get_all_query_jobs_bulk + Get All Bulk API Query Jobs +sf_get_dashboard_data Get dashboard data in a tabular format +sf_get_dashboard_results + Get the results of an existing dashboard +sf_get_dashboard_status + Get the status of a dashboard +sf_get_deleted Get Deleted Records from a Timeframe +sf_get_job_bulk Get Bulk API Job +sf_get_job_records_bulk + Returning the Details of a Bulk API Job +sf_get_report_instance_results + Get report instance results +sf_get_updated Get Updated Records from a Timeframe +sf_job_batches_bulk Checking the Status of a Batch in a Bulk API + Job +sf_list_api_limits List the Limits for an API +sf_list_dashboards List dashboards +sf_list_metadata List All Objects of a Certain Metadata Type in + Salesforce +sf_list_objects List Organization Objects and their Metadata +sf_list_report_fields Get a list of report fields +sf_list_report_filter_operators + List report filter operators +sf_list_report_instances + List report instances +sf_list_report_types List report types +sf_list_reports List reports +sf_list_resources List the Resources for an API +sf_list_rest_api_versions + List REST API Versions +sf_merge Merge Records +sf_query Perform SOQL Query +sf_query_bulk_v1 Run Bulk 1.0 query +sf_query_bulk_v2 Run Bulk 2.0 query +sf_query_report Get Report Data without Saving Changes to or + Creating a Report +sf_query_result_bulk Retrieve the results of a completed bulk query +sf_query_result_bulk_v1 + Retrieve the results of a Bulk 1.0 query +sf_query_result_bulk_v2 + Retrieve the results of a Bulk 2.0 query +sf_read_metadata Read Object or Field Metadata from Salesforce +sf_refresh_dashboard Refresh an existing dashboard +sf_rename_metadata Rename Metadata Elements in Salesforce +sf_report_folder_children + Get the subfolders (children) of a report + folder +sf_report_folder_create + Create report folder +sf_report_folder_delete + Delete a report folder +sf_report_folder_describe + Describe a report folder +sf_report_folder_share_delete + Delete a report folder share +sf_report_folder_share_describe + Describe a report folder share +sf_report_folder_share_recipients + Get report folder share recipients +sf_report_folder_share_update + Update a report folder share +sf_report_folder_shares_add + Add shares to a report folder +sf_report_folder_shares_list + List the shares in a report folder +sf_report_folder_shares_update + Update the shares for a report folder +sf_report_folder_update + Update a report folder +sf_report_folders_list + List report folders +sf_reset_password Reset User Password +sf_retrieve Retrieve Records By Id +sf_retrieve_metadata Make A Request to Retrieve the Metadata +sf_run_bulk_operation Run Bulk Operation +sf_run_bulk_query Run bulk query +sf_run_report Get a report's data in tabular format +sf_search Perform SOSL Search +sf_server_timestamp Salesforce Server Timestamp +sf_set_dashboard_sticky_filter + Set a sticky dashboard filter +sf_set_password Set User Password +sf_submit_query_bulk Submit Bulk Query Batch to a Bulk API Job +sf_undelete Undelete Records +sf_update Update Records +sf_update_attachment Update Attachments +sf_update_dashboard Update a dashboard +sf_update_metadata Update Object or Field Metadata in Salesforce +sf_update_report Update a report +sf_upload_complete_bulk + Signal Upload Complete to Bulk API Job +sf_upsert Upsert Records +sf_upsert_metadata Upsert Object or Field Metadata in Salesforce +sf_user_info Return Current User Info +valid_metadata_list List of Valid Data Types diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/LICENSE b/revdep/library.noindex/salesforcer/old/salesforcer/LICENSE new file mode 100644 index 00000000..2b970cb5 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/LICENSE @@ -0,0 +1,2 @@ +YEAR: 2018-2020 +COPYRIGHT HOLDER: Steven M. Mortimer diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/Meta/Rd.rds b/revdep/library.noindex/salesforcer/old/salesforcer/Meta/Rd.rds new file mode 100644 index 00000000..08f67669 Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/Meta/Rd.rds differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/Meta/features.rds b/revdep/library.noindex/salesforcer/old/salesforcer/Meta/features.rds new file mode 100644 index 00000000..ded31532 Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/Meta/features.rds differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/Meta/hsearch.rds b/revdep/library.noindex/salesforcer/old/salesforcer/Meta/hsearch.rds new file mode 100644 index 00000000..73b52fcd Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/Meta/hsearch.rds differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/Meta/links.rds b/revdep/library.noindex/salesforcer/old/salesforcer/Meta/links.rds new file mode 100644 index 00000000..6cbeff46 Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/Meta/links.rds differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/Meta/nsInfo.rds b/revdep/library.noindex/salesforcer/old/salesforcer/Meta/nsInfo.rds new file mode 100644 index 00000000..1a19783c Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/Meta/nsInfo.rds differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/Meta/package.rds b/revdep/library.noindex/salesforcer/old/salesforcer/Meta/package.rds new file mode 100644 index 00000000..ac5d8e29 Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/Meta/package.rds differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/Meta/vignette.rds b/revdep/library.noindex/salesforcer/old/salesforcer/Meta/vignette.rds new file mode 100644 index 00000000..b1d61053 Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/Meta/vignette.rds differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/NAMESPACE b/revdep/library.noindex/salesforcer/old/salesforcer/NAMESPACE new file mode 100644 index 00000000..07f204d4 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/NAMESPACE @@ -0,0 +1,404 @@ +# Generated by roxygen2: do not edit by hand + +S3method(sf_format_time,"NULL") +S3method(sf_format_time,AsIs) +S3method(sf_format_time,Date) +S3method(sf_format_time,POSIXct) +S3method(sf_format_time,POSIXlt) +S3method(sf_format_time,POSIXt) +S3method(sf_format_time,character) +S3method(sf_format_time,data.frame) +S3method(sf_format_time,list) +S3method(sf_format_time,logical) +S3method(sf_format_time,numeric) +export(VERB_n) +export(accepted_controls_by_api) +export(accepted_controls_by_operation) +export(bind_query_resultsets) +export(build_manifest_xml_from_list) +export(build_metadata_xml_from_list) +export(build_proxy) +export(build_soap_xml_from_list) +export(catch_errors) +export(catch_unknown_api) +export(check_and_encode_files) +export(collapse_list_with_dupe_names) +export(combine_parent_and_child_resultsets) +export(compact2) +export(drop_attributes) +export(drop_attributes_recursively) +export(drop_empty_recursively) +export(drop_nested_child_records) +export(extract_nested_child_records) +export(extract_records_from_xml_node) +export(extract_records_from_xml_nodeset) +export(extract_records_from_xml_nodeset_of_records) +export(filter_valid_controls) +export(flatten_tbl_df) +export(format_headers_for_verbose) +export(format_report_row) +export(get_os) +export(guess_object_name_from_soql) +export(is_legit_token) +export(list_extract_parent_and_child_result) +export(make_analytics_folder_child_operations_url) +export(make_analytics_folder_collections_url) +export(make_analytics_folder_operations_url) +export(make_analytics_folder_share_by_id_url) +export(make_analytics_folder_share_recipients_url) +export(make_analytics_folder_shares_url) +export(make_analytics_notification_operations_url) +export(make_analytics_notifications_limits_url) +export(make_analytics_notifications_list_url) +export(make_base_metadata_url) +export(make_base_rest_url) +export(make_base_soap_url) +export(make_bulk_batch_details_url) +export(make_bulk_batch_status_url) +export(make_bulk_batches_url) +export(make_bulk_create_job_url) +export(make_bulk_delete_job_url) +export(make_bulk_end_job_generic_url) +export(make_bulk_get_all_jobs_url) +export(make_bulk_get_all_query_jobs_url) +export(make_bulk_get_job_url) +export(make_bulk_job_records_url) +export(make_bulk_query_result_url) +export(make_bulk_query_url) +export(make_chatter_users_url) +export(make_composite_batch_url) +export(make_composite_url) +export(make_dashboard_copy_url) +export(make_dashboard_describe_url) +export(make_dashboard_filter_operators_list_url) +export(make_dashboard_filter_options_analysis_url) +export(make_dashboard_status_url) +export(make_dashboard_url) +export(make_dashboards_list_url) +export(make_login_url) +export(make_parameterized_search_url) +export(make_query_url) +export(make_report_copy_url) +export(make_report_create_url) +export(make_report_describe_url) +export(make_report_execute_url) +export(make_report_fields_url) +export(make_report_filter_operators_list_url) +export(make_report_instance_url) +export(make_report_instances_list_url) +export(make_report_query_url) +export(make_report_type_describe_url) +export(make_report_types_list_url) +export(make_report_url) +export(make_reports_list_url) +export(make_rest_describe_url) +export(make_rest_objects_url) +export(make_rest_record_url) +export(make_search_url) +export(make_soap_xml_skeleton) +export(make_verbose_httr_message) +export(map_sf_type_to_r_type) +export(merge_null_to_na) +export(message_w_errors_listed) +export(metadata_type_validator) +export(parameterized_search_control) +export(parse_error_code_and_message) +export(parse_report_detail_rows) +export(patched_tempdir) +export(rDELETE) +export(rGET) +export(rPATCH) +export(rPOST) +export(rPUT) +export(records_list_to_tbl) +export(remove_empty_linked_object_cols) +export(return_matching_controls) +export(rforcecom.bulkAction) +export(rforcecom.bulkQuery) +export(rforcecom.create) +export(rforcecom.delete) +export(rforcecom.getObjectDescription) +export(rforcecom.getServerTimestamp) +export(rforcecom.login) +export(rforcecom.query) +export(rforcecom.retrieve) +export(rforcecom.search) +export(rforcecom.update) +export(rforcecom.upsert) +export(safe_bind_rows) +export(salesforcer_state) +export(session_id_available) +export(set_null_elements_to_na) +export(set_null_elements_to_na_recursively) +export(sf_abort_job_bulk) +export(sf_access_token) +export(sf_analytics_notification_create) +export(sf_analytics_notification_delete) +export(sf_analytics_notification_describe) +export(sf_analytics_notification_update) +export(sf_analytics_notifications_limits) +export(sf_analytics_notifications_list) +export(sf_auth) +export(sf_auth_check) +export(sf_auth_refresh) +export(sf_batch_details_bulk) +export(sf_batch_status_bulk) +export(sf_build_cols_spec) +export(sf_bulk_operation) +export(sf_close_job_bulk) +export(sf_control) +export(sf_convert_lead) +export(sf_copy_dashboard) +export(sf_copy_report) +export(sf_create) +export(sf_create_attachment) +export(sf_create_batches_bulk) +export(sf_create_job_bulk) +export(sf_create_job_bulk_v1) +export(sf_create_job_bulk_v2) +export(sf_create_metadata) +export(sf_create_report) +export(sf_delete) +export(sf_delete_attachment) +export(sf_delete_dashboard) +export(sf_delete_job_bulk) +export(sf_delete_metadata) +export(sf_delete_report) +export(sf_delete_report_instance) +export(sf_describe_dashboard) +export(sf_describe_dashboard_components) +export(sf_describe_metadata) +export(sf_describe_object_fields) +export(sf_describe_objects) +export(sf_describe_report) +export(sf_describe_report_type) +export(sf_download_attachment) +export(sf_empty_recycle_bin) +export(sf_end_job_bulk) +export(sf_execute_report) +export(sf_filter_dashboard_operators_list) +export(sf_filter_dashboard_options_analysis) +export(sf_find_duplicates) +export(sf_find_duplicates_by_id) +export(sf_format_date) +export(sf_format_datetime) +export(sf_format_time) +export(sf_get_all_jobs_bulk) +export(sf_get_all_query_jobs_bulk) +export(sf_get_dashboard_data) +export(sf_get_dashboard_results) +export(sf_get_dashboard_status) +export(sf_get_deleted) +export(sf_get_job_bulk) +export(sf_get_job_records_bulk) +export(sf_get_report_instance_results) +export(sf_get_updated) +export(sf_guess_cols) +export(sf_input_data_validation) +export(sf_job_batches_bulk) +export(sf_list_api_limits) +export(sf_list_dashboards) +export(sf_list_metadata) +export(sf_list_objects) +export(sf_list_report_fields) +export(sf_list_report_filter_operators) +export(sf_list_report_instances) +export(sf_list_report_types) +export(sf_list_reports) +export(sf_list_resources) +export(sf_list_rest_api_versions) +export(sf_merge) +export(sf_query) +export(sf_query_bulk) +export(sf_query_bulk_v1) +export(sf_query_bulk_v2) +export(sf_query_report) +export(sf_query_result_bulk) +export(sf_query_result_bulk_v1) +export(sf_query_result_bulk_v2) +export(sf_read_metadata) +export(sf_refresh_dashboard) +export(sf_rename_metadata) +export(sf_reorder_cols) +export(sf_report_folder_children) +export(sf_report_folder_create) +export(sf_report_folder_delete) +export(sf_report_folder_describe) +export(sf_report_folder_share_delete) +export(sf_report_folder_share_describe) +export(sf_report_folder_share_recipients) +export(sf_report_folder_share_update) +export(sf_report_folder_shares_add) +export(sf_report_folder_shares_list) +export(sf_report_folder_shares_update) +export(sf_report_folder_update) +export(sf_report_folders_list) +export(sf_reset_password) +export(sf_rest_list) +export(sf_retrieve) +export(sf_retrieve_metadata) +export(sf_retrieve_metadata_check_status) +export(sf_run_bulk_operation) +export(sf_run_bulk_query) +export(sf_run_report) +export(sf_search) +export(sf_server_timestamp) +export(sf_session_id) +export(sf_set_dashboard_sticky_filter) +export(sf_set_password) +export(sf_submit_query_bulk) +export(sf_undelete) +export(sf_update) +export(sf_update_attachment) +export(sf_update_dashboard) +export(sf_update_metadata) +export(sf_update_report) +export(sf_upload_complete_bulk) +export(sf_upsert) +export(sf_upsert_metadata) +export(sf_user_info) +export(sf_write_csv) +export(simplify_report_metadata) +export(stop_w_errors_listed) +export(token_available) +export(unbox_list_elements) +export(unbox_list_elements_recursively) +export(unnest_col) +export(valid_metadata_list) +export(validate_get_all_jobs_params) +export(warn_w_errors_listed) +export(xmlToList2) +export(xml_drop_and_unlist) +export(xml_drop_and_unlist_recursively) +export(xml_extract_parent_and_child_result) +export(xml_nodeset_to_df) +importFrom(XML,"xmlValue<-") +importFrom(XML,addChildren) +importFrom(XML,newXMLNode) +importFrom(XML,saveXML) +importFrom(XML,xmlApply) +importFrom(XML,xmlAttrs) +importFrom(XML,xmlChildren) +importFrom(XML,xmlDoc) +importFrom(XML,xmlInternalTreeParse) +importFrom(XML,xmlParse) +importFrom(XML,xmlRoot) +importFrom(XML,xmlSApply) +importFrom(XML,xmlSize) +importFrom(XML,xmlToList) +importFrom(XML,xmlValue) +importFrom(anytime,anydate) +importFrom(anytime,anytime) +importFrom(base64enc,base64encode) +importFrom(curl,form_data) +importFrom(curl,form_file) +importFrom(data.table,rbindlist) +importFrom(dplyr,"%>%") +importFrom(dplyr,across) +importFrom(dplyr,all_of) +importFrom(dplyr,any_of) +importFrom(dplyr,as_tibble) +importFrom(dplyr,bind_cols) +importFrom(dplyr,bind_rows) +importFrom(dplyr,contains) +importFrom(dplyr,everything) +importFrom(dplyr,expr) +importFrom(dplyr,filter) +importFrom(dplyr,if_all) +importFrom(dplyr,is.tbl) +importFrom(dplyr,matches) +importFrom(dplyr,mutate) +importFrom(dplyr,mutate_all) +importFrom(dplyr,mutate_if) +importFrom(dplyr,one_of) +importFrom(dplyr,rename) +importFrom(dplyr,rename_at) +importFrom(dplyr,rename_with) +importFrom(dplyr,select) +importFrom(dplyr,tibble) +importFrom(httr,DELETE) +importFrom(httr,GET) +importFrom(httr,PATCH) +importFrom(httr,POST) +importFrom(httr,PUT) +importFrom(httr,RETRY) +importFrom(httr,add_headers) +importFrom(httr,build_url) +importFrom(httr,config) +importFrom(httr,content) +importFrom(httr,headers) +importFrom(httr,http_error) +importFrom(httr,oauth2.0_token) +importFrom(httr,oauth_app) +importFrom(httr,oauth_endpoint) +importFrom(httr,parse_url) +importFrom(httr,status_code) +importFrom(httr,upload_file) +importFrom(httr,use_proxy) +importFrom(jsonlite,base64_dec) +importFrom(jsonlite,fromJSON) +importFrom(jsonlite,prettify) +importFrom(jsonlite,toJSON) +importFrom(lifecycle,deprecate_soft) +importFrom(lifecycle,deprecate_warn) +importFrom(lifecycle,deprecated) +importFrom(lifecycle,is_present) +importFrom(lubridate,as_datetime) +importFrom(lubridate,dmy_hms) +importFrom(lubridate,is.Date) +importFrom(lubridate,is.POSIXct) +importFrom(lubridate,is.POSIXlt) +importFrom(lubridate,is.POSIXt) +importFrom(methods,as) +importFrom(mime,guess_type) +importFrom(purrr,as_mapper) +importFrom(purrr,compact) +importFrom(purrr,discard) +importFrom(purrr,list_modify) +importFrom(purrr,map) +importFrom(purrr,map_chr) +importFrom(purrr,map_depth) +importFrom(purrr,map_df) +importFrom(purrr,map_dfc) +importFrom(purrr,map_if) +importFrom(purrr,map_lgl) +importFrom(purrr,modify) +importFrom(purrr,modify_at) +importFrom(purrr,modify_if) +importFrom(purrr,pluck) +importFrom(purrr,set_names) +importFrom(purrr,transpose) +importFrom(readr,col_character) +importFrom(readr,col_guess) +importFrom(readr,cols) +importFrom(readr,locale) +importFrom(readr,parse_datetime) +importFrom(readr,read_csv) +importFrom(readr,type_convert) +importFrom(readr,write_csv) +importFrom(rlang,is_empty) +importFrom(rlist,list.flatten) +importFrom(stats,quantile) +importFrom(stats,runif) +importFrom(stats,setNames) +importFrom(tibble,as_tibble_row) +importFrom(tools,file_ext) +importFrom(utils,capture.output) +importFrom(utils,head) +importFrom(utils,object.size) +importFrom(utils,tail) +importFrom(vctrs,vec_as_names) +importFrom(xml2,as_list) +importFrom(xml2,read_xml) +importFrom(xml2,url_escape) +importFrom(xml2,xml_add_child) +importFrom(xml2,xml_add_sibling) +importFrom(xml2,xml_child) +importFrom(xml2,xml_find_all) +importFrom(xml2,xml_find_first) +importFrom(xml2,xml_new_document) +importFrom(xml2,xml_ns_strip) +importFrom(xml2,xml_remove) +importFrom(xml2,xml_set_namespace) +importFrom(xml2,xml_text) +importFrom(zip,zipr) diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/NEWS.md b/revdep/library.noindex/salesforcer/old/salesforcer/NEWS.md new file mode 100644 index 00000000..53e20ba0 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/NEWS.md @@ -0,0 +1,436 @@ +# salesforcer 1.0.1 + +## Dependencies + + * Increase the package's default Salesforce API version to 54.0 (Spring '22) + * Added a deprecation warning that using basic authentication (password and + security token) will no longer work since Salesforce announced that all + customers will be migrated to MFA beginning February 1st, 2022 + ([link](https://admin.salesforce.com/blog/2021/everything-admins-need-to-know-about-the-mfa-requirement)). Many thanks to @klaw2 for highlighting in #113. + * Remove deprecated use of `dplyr::across()` and add logic to circumvent a + new warning emitted by `readr::type_convert()` when no character columns + are present + +## Bug fixes + + * Changed the naming convention for dashboard-related functions to contain the + action verb first (e.g., `sf_copy_dashboard` instead of `sf_dashboard_copy`) + +--- + +# salesforcer 1.0.0 [release](https://github.com/StevenMMortimer/salesforcer/releases/tag/v1.0.0) + +## Dependencies + + * Increase the package's default Salesforce API version to 52.0 (Summer '21). + + * Remove uses of {RForcecom} after it was archived on CRAN on 6/8/2021 (#101) + + * Remove LazyData option in DESCRIPTION since `data()` is not utilized + + * Deprecate argument in `sf_write_csv()` from `path` to `file` as was done in + {readr} v1.4.0. + + * Deprecate argument `bind_using_character_cols` because we will always need + to bind as character and then parse if `guess_types=TRUE`. Per comments in + tidyverse/readr#588 and tidyverse/readr#98, we must read all of the data as + character first and then use `type_convert()` to ensure that we use all values + in the column to guess the type. The default for `read_csv()` is to only use + the first 1,000 rows and its `guess_max` argument cannot be set to `Inf`. + + * Change lifecycle status from "Maturing" to "Status" per the retirement of + "Maturing" in the {lifecycle} package. The documentation notes: + + > Previously we used as maturing for functions that lay somewhere between experimental and stable. We stopped using this stage because, like questioning, it’s not clear what actionable information this stage delivers. + + In addition, the lifecycle guidance states that experimental packages have + version numbers less than 1.0.0 and may have major changes in its future. + The {salesforcer} package has achieved a stable state with core + functionality implemented and a focus on backwards compatibility due to the + volume of users. + +## Features + + * Improve documentation to retrieve the access token or session ID after + authentication (#97) + + * Improve parsing of Bulk API query recordsets from CSV where all values + in the column will be used to guess the type instead of the first 1000. + +## Bug fixes + + * Generalize the date and datetime parsing mechanism, such that, reports with + date and datetime fields are not returned as NA (#93) + + * Fix the format of the `OwnerChangeOptions` header so it is accepted (#94) + + * Fix bug that caused Bulk 2.0 calls to crash when the results had datetime + fields in the recordset (#95) + +--- + +# salesforcer 0.2.2 [release](https://github.com/StevenMMortimer/salesforcer/releases/tag/v0.2.2) + +## Dependencies + + * This release relaxes the dependency on {dplyr} and brings back use of + `rbindlist()` from {data.table} because of limitations of `dplyr::bind_rows()`. + As noted in (tidyverse/dplyr#5429) {dplyr} will only support binding data.frames + or lists of data.frames, **not** a list of lists which is needed in some + applications of the {salesforcer} package. + * Due to other recent changes between {vctrs} and {dplyr}, you may now see the + following warning displayed when loading {salesforcer}, which is emitted by the + loading of {dplyr}: + + ```r + Warning: replacing previous import 'vctrs::data_frame' by 'tibble::data_frame' when loading 'dplyr' + ``` + +## Features + + * None + + +## Bug fixes + + * None + +# salesforcer 0.2.1 [release](https://github.com/StevenMMortimer/salesforcer/releases/tag/v0.2.1) + +## Dependencies + + * **CAUTION: This release requires {dplyr 1.0.0} because {dplyr 1.0.1} introduced + a bug in `bind_rows()` with how it binds lists where the list elements have differing + lengths. This is documented in tidyverse/dplyr#5417 and r-lib/vctrs#1073. The + timeline for a fix is unknown as of Aug 16, 2020.** You can install the older + version of {dplyr} using the following command: + + ```r + remotes::install_version("dplyr", "1.0.0") + ``` + +## Features + + * Add support for the `defaultLimit` argument in `sf_search()` to be able to + restrict the number of records from each individual object when searching + across one or more objects. + * Add support for updating attachments with the `sf_update_attachments()` + function (#79). + * Add support for downloading attachments just by its Id. In addition, the + `sf_download_attachment()` function returns the file path of the downloaded + content instead of a logical indicating success. + +## Bug fixes + + * Fix bug introduced in {salesforcer 0.2.0} which could not stack records with + errors longer than length 1. The new solution is to always return the `errors` + column as a list, which is coerced to length 1 for the record (#66). + * Fix bug in `sf_search()` that was passing `"true"/"false"` instead of actual + boolean value for the `spellCorrection` parameter in the POST body. + +--- + +# salesforcer 0.2.0 [release](https://github.com/StevenMMortimer/salesforcer/releases/tag/v0.2.0) + +## Dependencies + + * **CAUTION: This release only has automated test coverage on R 4.0.0 or greater. + Users should still be able to install and run using R (>= 3.6.0). However, it + is recommended to upgrade to R 4.0.0 or greater.** + +## Features + + * Add experimental support for the Reports and Dashboards REST API. + + * Add support for Bulk 2.0 queries that was added in Salesforce version 47.0 + (Winter '20). **CAUTION: The Bulk 2.0 API is now the default API when using + `sf_query_bulk()` or `sf_run_bulk_query()`**. Please test prior to upgrading + in a production environment where you are running bulk queries. + + * Standardize the column order and format of query and CRUD operations that + prioritizes the object type and Ids over other fields and finaly relationship + fields. **CAUTION: This will switch up the order of the columns returned by + your existing code**. Please test prior to upgrading in a production environment + where column ordering is a breaking change. For example we prioritize the following + fields in queries alphabetically within this prioritization waterfall: + + 1. The `sObject` field first (indicates the record's object if multiple objects returned in the results) + 2. The Id field second (`Id`, `id`, `sf__Id`) + 3. Salesforce record success status (`Success`, `success`, `sf_Success`) + 4. Salesforce record created status (`Created`, `created`, `sf__Created`) + 5. Salesforce record error(s) status (`Error`, `error`, `errors`, + `errors.statusCode`, `errors.fields`, `errors.message`, `sf__Error`) + 6. All other fields from the target object (e.g. `Name`, `Phone`, etc.) + 7. Relationship fields (fields from a parent or child of the target). For example, + anything typically containing a dot like `Account.Id`, `Owner.Name`, etc. + + * Standardize the names of functions that submit long running jobs to Salesforce. + These functions now all start with `sf_run_*`. However, the original names have + been aliased to the new names so this version will acknowledge the old function + names without deprecation warning.For example, the new names are: + + * `sf_query_bulk()` ==> `sf_run_bulk_query()` + * `sf_bulk_operation()` ==> `sf_run_bulk_operation()` + * `sf_run_report()` + + * Add support for logging in with a proxy without having to use OAuth 2.0 as + the authentication method. When proxy support was first implemented in + {salesforcer} 0.1.4, it only supported proxy connections when logging in via + OAuth 2.0. Now, this untested version of proxy support for basic + authentication has been implemented. This means that proxy users should be + able to login using just a username, password, and security token if their + organization has not implemented OAuth 2.0 or if they do not want to use OAuth + 2.0 while logging in via this package. + + * Add lifecycle badges to signal maturity of different package aspects. + + * Add two vignettes, one that outlines the query types supported by the package + and another that outlines the new report functionality that was introduced in + this release. + + * Add enhanced query test coverage in its own test script. + + * Remove dependency on {data.table} which does not have a build for R-devel. This + should only affect `sf_read_metadata()`. + + +## Bug Fixes + + * Fix bug that prevented enabling PKChunking in Bulk 1.0 queries. Users can + now specify using `TRUE/FALSE` or details like `chunkSize` that imply `TRUE`. + The results are then parsed appropriately by waiting for all individual + batches to finish. (#46) + + * Fix bugs in REST and SOAP API queries to prevent infinite looping and + mangling results of relationship queries, specifically parent-to-child + nested queries. (#19, #35, #38, #54) + + * Fix bug in REST and SOAP APIs where the creation of a record that fails + duplicate rules will return the duplicate match results as well and cause the + entire function call to fail because it cannot parse the results. Now only the + status code and message are returned and the function will execute + successfully even if the record has not been created due to the rule. + +--- + +# salesforcer 0.1.4 [release](https://github.com/StevenMMortimer/salesforcer/releases/tag/v0.1.4) + +## Features + + * Rebuilt package against R 4.0 (no issues observed with 3.6.3, 4.0.0, 4.0.1) + (#53) + + * Upgrade to Salesforce version 48.0 (Spring '20) from version 46.0 (Summer '19) + + * Add support for connections through a proxy by setting in package options (#32) + + * CRUD operations now automatically cast date and datetime (Date, POSIXct, + POSIXlt, POSIXt) formats into an accepted string format recognized by + Salesforce (`YYYY-MM-DDThh:mm:ss.sssZ`). + + * Add `batch_size` argument to support specifying custom batch sizes for Bulk jobs + + * Add `sf_convert_lead()` which takes leads and will associate them to the + corresponding Accounts, Contacts, and Opportunities as directed in the input + along with many other options to send an email to the new owner, block the + opportunity creation, and more. + + * Add `sf_create_attachment()` along with a vignette that better describes how + to interact with attachments and other blob data. + + * Add Attachment and Metadata vignettes along with updated Bulk vignette. + +## Bug Fixes + + * Fix issue where REST query was not correctly passing and honoring the batch + size control argument to paginate results + + * Fix issue in results of REST query pagination where the function was looping + infinitely because of a bug in the implementation that would continue using + the same `next_records_url` that was previously passed into the function (#54) + + * Fix issue where the results of Bulk 1.0 query batches where returning fewer + rows than expected because of using `content(..., as="text")` which truncated + the results instead of using `content(..., type="text/csv")` (#54) + + * Fix issue where the details of an object's picklist contains NULLs (e.g. the + `validFor` entry of a picklist value is NULL) so now it is replaced with NA + and then can be bound together into a data.frame (#27) + + * Fix issue where NA values in create, update, and upsert operations where + setting the fields to blank in Bulk APIs, but not the SOAP or REST APIs. Now + NA values in a record will set the field to blank across all APIs (#29) + + * Fix issue where supplying all NA values in the Id field for certain + operations would result in a cryptic error message (`"BAD_REQUEST: Unsupported + Tooling Sobject Type"`); the affected operations are: delete, undelete, + emptyRecycleBin, retrieve, update, and findDuplicatesByIds + +--- + +# salesforcer 0.1.3 [release](https://github.com/StevenMMortimer/salesforcer/releases/tag/v0.1.3) + +## Features + + * Upgrade to version 46.0 (Summer '19) from version 45.0 (Spring '19) + + * Add **RForcecom** backward compatible version of + `rforcecom.getObjectDescription()` + + * Add `sf_describe_object_fields()` which is a tidier version of + `rforcecom.getObjectDescription()` + + * Allow users to control whether query results are kept as all character or + the types are guessed (#12) + + * Add `sf_get_all_jobs_bulk()` so that users can see retrieve details for all + bulk jobs (#13) + + * Add new utility functions `sf_set_password()` and `sf_reset_password()` (#11) + + * Add two new functions to check for duplicates (`sf_find_duplicates()`, + `sf_find_duplicates_by_id()`) (#4) + + * Add new function to download attachments to disk + (`sf_download_attachment()`) (#20) + + * Add functionality to infer the `object_name` argument, required for bulk + queries, if left blank. + + * Add `control` argument to most all package functions and dots (`...`) which + allows for more than a dozen different control parameters listed in + `sf_control()` to be fed into existing function calls to tweak the default + behavior. For example, if you would like to override duplicate rules then you + can adjust the `DuplicateRuleHeader`. If you would like to have certain + assignment rule run on newly created records, then pass in the + `AssignmentRuleHeader` (#4, #5) + + * Add new function `sf_undelete()` which will take records out of the Recycle Bin + + * Add new function `sf_empty_recycle_bin()` which will remove records + permanently from the Recycle Bin + + * Add new function `sf_merge()` which combines up to 3 records of the same + type into 1 record (#22) + +## Bug Fixes + + * Fix bug where Username/Password authenticated sessions where not working with + api_type = "Bulk 1.0" + + * Fix bug where Bulk 1.0 queries that timeout hit an error while trying to abort + since that only supported aborting Bulk 2.0 jobs (#13) + + * Fix bug that had only production environment logins possible because of hard + coding (@weckstm, #18) + + * Enhance `sf_describe_object_fields()` to be robust against nested list + elements and also return picklist labels and their values as a tibble (#16) + + * Fix bug where four of the bulk operation options (`content_type`, `concurrency_mode`, + `line_ending`, and `column_delimiter`) where not being passed down from + the top level generic functions like `sf_create()`, `sf_update()`, etc. However, + `line_ending` has now been moved into the `sf_control` function so it is no longer + explicitly listed for bulk operations as an argument. (@mitch-niche, #23) + + * Ensure that for SOAP, REST, and Bulk 2.0 APIs the verbose argument prints out + the XML or JSON along with the URL of the call so it can be replicated via cURL or + some other programming language (#8) + +--- + +# salesforcer 0.1.2 [release](https://github.com/StevenMMortimer/salesforcer/releases/tag/v0.1.2) + +## Features + + * Add support for Bulk 1.0 operations of "create", "update", "upsert", "delete" + and "hardDelete" + + * Bulk 2.0 operations, by default, now return a single `tbl_df` containing all + of the successful records, error records, and unprocessed records + + * Create internal functions that explicitly call each API for an operation. For + example, `sf_create()` routes into `sf_create_soap()`, `sf_create_rest()`, and + `sf_bulk_operation()`. + +--- + +# salesforcer 0.1.1 [release](https://github.com/StevenMMortimer/salesforcer/releases/tag/v0.1.1) + +## Features + + * Add `sf_search()` with REST and SOAP API support for SOSL and free text search + + * Add `sf_describe_objects()` with REST and SOAP API to return object metadata + + * Add REST API support for upsert (`sf_upsert()`) + + * Add SOAP API support for the following operations: + + * `sf_create()` + * `sf_update()` + * `sf_delete()` + * `sf_retrieve()` + + * Add Metadata API support for the following operations: + + * `sf_create_metadata()` + * `sf_read_metadata()` + * `sf_update_metadata()` + * `sf_upsert_metadata()` + * `sf_delete_metadata()` + * `sf_describe_metadata()` + * `sf_list_metadata()` + * `sf_rename_metadata()` + * `sf_retrieve_metdata()` + * `sf_deploy_metdata()` + + * Update the default file name for a cached token to `.httr-oauth-salesforcer` + so that it does not clash with other package token names. + +## Bug Fixes + + * `sf_user_info()` returning `argument is of length zero` because token is not +automatically refreshed before calling GET. + + * `sf_token()` ignoring basic authorized sessions since it was only looking + for a token using `token_avaiable()`. Replace with `sf_auth_check()` so now + it considers a session or a token to be "available" (#1). + +--- + +# salesforcer 0.1.0 [release](https://github.com/StevenMMortimer/salesforcer/releases/tag/v0.1.0) + +## Features + + * OAuth 2.0 and Basic authentication methods (`sf_auth()`) + + * Query operations via REST and Bulk APIs (`sf_query()`) + + * CRUD operations (Create, Retrieve, Update, Delete) for REST and Bulk APIs: + + * `sf_create()` + * `sf_retrieve()` + * `sf_update()` + * `sf_upsert()` + * `sf_delete()` + + * Backwards compatible versions of **RForcecom** package functions: + + * `rforcecom.login()` + * `rforcecom.getServerTimestamp()` + * `rforcecom.query()` + * `rforcecom.bulkQuery()` + * `rforcecom.create()` + * `rforcecom.update()` + * `rforcecom.upsert()` + * `rforcecom.delete()` + + * Basic utility calls: + + * `sf_user_info()` + * `sf_server_timestamp()` + * `sf_list_rest_api_versions()` + * `sf_list_resources()` + * `sf_list_api_limits()` + * `sf_list_objects()` diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/R/salesforcer b/revdep/library.noindex/salesforcer/old/salesforcer/R/salesforcer new file mode 100644 index 00000000..66861563 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/R/salesforcer @@ -0,0 +1,27 @@ +# File share/R/nspackloader.R +# Part of the R package, https://www.R-project.org +# +# Copyright (C) 1995-2012 The R Core Team +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# A copy of the GNU General Public License is available at +# https://www.r-project.org/Licenses/ + +local({ + info <- loadingNamespaceInfo() + pkg <- info$pkgname + ns <- .getNamespace(as.name(pkg)) + if (is.null(ns)) + stop("cannot find namespace environment for ", pkg, domain = NA); + dbbase <- file.path(info$libname, pkg, "R", pkg) + lazyLoad(dbbase, ns, filter = function(n) n != ".__NAMESPACE__.") +}) diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/R/salesforcer.rdb b/revdep/library.noindex/salesforcer/old/salesforcer/R/salesforcer.rdb new file mode 100644 index 00000000..7b5eab88 Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/R/salesforcer.rdb differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/R/salesforcer.rdx b/revdep/library.noindex/salesforcer/old/salesforcer/R/salesforcer.rdx new file mode 100644 index 00000000..b8f40978 Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/R/salesforcer.rdx differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/WORDLIST b/revdep/library.noindex/salesforcer/old/salesforcer/WORDLIST new file mode 100644 index 00000000..983ffcfb --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/WORDLIST @@ -0,0 +1,1961 @@ +AAC +Abessive +aboveOrBelow +acceptedDataType +acceptedValues +AccessMapping +AccessMethod +AccessResource +accountCreator +accountId +AccountInformation +AccountMaster +accountOwner +AccountSettings +AccountSharingRuleSettings +accountTeam +ACGI +ACTIONCALL +actionCallName +ActionEmailRecipientTypes +ActionEmailSenderType +ActionLink +ActionLinkExecutionsAllowed +ActionLinkGroupTemplate +ActionLinkHttpMethod +ActionLinkTemplate +ActionLinkType +ActionLinkUserVisibility +ActionOverride +ActionOverrideType +ActionPlan +ActionTaskAssignedToTypes +actionValue +activateSessionPermSet +ActivationFailed +ActivitiesSettings +ActivityEvent +AddItem +AddMember +AddRecord +AddressSettings +Adessive +adhoc +AdjustmentsSettings +AdminOnly +AdminOrCurrentApprover +AdminSetupEvent +AdvancedTextPost +AE +AED +AES +AFA +AgentConfigAssignments +AgentConfigButtons +AgentConfigProfileAssignments +AgentConfigSkills +AgentConfigUserAssignments +aggregateValue +Allative +AllChannels +AllCspUsers +allInternalUsers +AllOrNoneHeader +AllowAllFraming +ALLOWBACK +AllowFieldTruncationHeader +ALLOWFINISH +ALLOWPAUSE +AllPrmUsers +ALLTHUMBS +AllUpdates +AllUsers +AlphaNumeric +analytics +Analytics +AnalyticsCloudComponentLayoutItem +AnalyticSnapshot +AnalyticSnapshotMapping +ANG +AnimateMasculine +AnnouncementPost +AnnualRevenue +AOA +APEXCALLOUT +ApexClass +APEXCLASS +apexClassName +ApexCodeUnitStatus +ApexComponent +ApexPage +ApexTestSuite +ApexTrigger +api +Api +APIs +API's +APIAccessLevel +APIAsync +ApiEvent +AppActionOverride +AppBrand +AppComponentList +AppLauncher +AppMenu +AppMenuItem +AppPage +AppPreferences +AppProfileActionOverride +ApprovalAction +ApprovalEntryCriteria +ApprovalPageField +ApprovalPost +ApprovalProcess +ApprovalStep +ApprovalStepApprover +ApprovalStepRejectBehavior +ApprovalSubmitter +Approver +ApproveRecord +AppWorkspaceConfig +ar +Args +ARS +ArticleTypeChannelDisplay +ArticleTypeTemplate +Asc +ASF +AsIs +AssignedToMe +ASSIGNMENTITEM +assignmentName +AssignmentRule +AssignmentRuleHeader +AssignmentRules +ASSIGNNEXTVALUETO +AssignToLookupValueType +ASSIGNTOREFERENCE +AssistantRecommendationType +AssociativeBusinessOrPersonalData +async +Async +AttachArticleEvent +attributeName +AUD +AudienceCriteriaType +AuditTrail +AuraBundleType +AuraDefinitionBundle +auth +authenticaion +AuthenticationData +AuthenticationProtocol +AuthProvider +AuthProviderType +Autofill +AUTOLAUNCHED +AutoLaunchedFlow +AutoNumber +AutoResponseRule +AutoResponseRules +AWG +AZM +AZN +BackToPrevious +BAM +BannerPhoto +BarGrouped +BarStacked +BasicTemplateFeedItem +BBD +BDT +BEF +BestCase +bg +BGL +BGN +BH +BHD +BIF +BigObjectIngest +BinaryOnly +BlankAsBlank +BlankAsZero +BlankValueBehavior +BMD +BMP +bn +BND +BottomLeft +BottomLeftBottom +BottomLeftLeft +BottomRight +BottomRightBottom +BottomRightRight +BOV +BOXNOTE +BrandingSet +BrandingSetProperty +BRB +BRL +bs +BTN +BubbleGrouped +BuildCustom +BusinessHoursEntry +BusinessHoursSettings +BusinessHoursSourceType +BusinessProcess +BusinessSetupDataBusinessDataAndAggregates +busop +BWP +BYB +BYN +BypassSharingRules +BYR +BZD +CallCenter +CallCenterItem +CallCenterSection +CallLogPost +CallOptions +Callout +callouts +CampaignInfluenceModel +campaignMemberDerivedOwner +CanvasLocationOptions +CanvasOptions +CanvasPost +CaseCommentPost +CaseCreation +CaseInteraction +CaseLastModified +CaseSettings +CaseSubjectOption +CaseSubjectParticle +CaseSubjectParticleType +caseTeam +CaseType +CaseUnifiedFiles +CategoryGroupVisibility +Causalfinal +CenterDropDown +ChangeDueDate +ChangePriority +ChangeStatus +ChangeStatusPost +ChannelLayout +ChannelLayoutItem +ChannelProgramGroup +characterLimit +ChartAxis +ChartBackgroundDirection +ChartColorPalettes +ChartLegendPosition +ChartPosition +ChartRangeType +ChartSummary +ChartTheme +ChartType +ChartUnits +ChatterAnswersReputationLevel +ChatterAnswersSettings +ChatterExtension +ChatterExtensionType +ChatterFeed +ChatterMobileSettings +chatterPost +ChatTranscriptPost +CHF +ChildServiceReportTemplateStyle +CHOICEFIELD +CHOICELOOKUP +choiceLookupName +choiceName +CHOICETYPE +choosePricebook +CLASSNAME +CleanDataService +CleanRule +CleanRuleStatus +CLF +CLP +CN +CNY +CodeLocation +CollaborationGroupCreated +CollaborationGroupUnarchived +COLLECTIONTYPES +ColonSeparator +colorSafe +ColumnGrouped +ColumnLine +ColumnLineGrouped +ColumnLineStacked +ColumnStacked +Comitative +CommAppPage +CommForgotPasswordPage +CommGlobalSearchResultPage +CommLoginPage +CommObjectPage +CommQuickActionCreatePage +CommRecordPage +CommRelatedListPage +CommSearchResultPage +CommSelfRegisterPage +CommThemeLayoutPage +CommunityBaseTemplate +CommunityCustomThemeLayoutType +CommunityRoles +CommunityTemplateBundleInfo +CommunityTemplateBundleInfoType +CommunityTemplateCategory +CommunityTemplateDefinition +CommunityTemplatePageSetting +CommunityThemeDefinition +CommunityThemeLayoutType +CommunityThemeSetting +CompactLayout +CompanyName +CompanySettings +ComponentInstance +ComponentInstanceProperty +ComponentInstancePropertyTypeEnum +componentName +concurrencyMode +ConfigurationAndUsageData +ConnectedApp +ConnectedAppAttribute +ConnectedAppCanvasConfig +ConnectedAppIpRange +ConnectedAppMobileDetailConfig +ConnectedAppOauthAccessScope +ConnectedAppOauthConfig +ConnectedAppSamlConfig +constantName +contactId +contactLookup +ContentAsset +ContentAssetAccess +ContentAssetFormat +ContentAssetLink +ContentAssetRelationships +ContentAssetVersion +ContentAssetVersions +ContentPost +contentWorkspaceEnableFolders +ContractSettings +ControlledByParent +coordinateLimit +coordinateName +CorsWhitelistOrigin +CountriesAndStates +CPP +CRC +CreateNew +CreateNewRecordType +CreateRecordEvent +createResponseEventAction +createServiceReport +creditCard +criterionIndex +CSD +Csp +CspTrustedSite +css +CUC +CURFY +cURL +CURNEXT +CURNEXTFY +CURNEXTQ +CURNEXTY +CURPREV +CURPREVQ +CurrencyIsoCode +CURRENTQ +CurrentUser +CURY +CustomApexPolicy +CustomApplication +CustomApplicationComponent +CustomApplications +CustomApplicationTranslation +CustomAttribute +CustomButton +CustomButtons +CustomChannel +CustomConditionBuilderPolicy +CustomConsoleComponents +CustomDataType +CustomDataTypeComponent +CustomDataTypeComponentTranslation +CustomDataTypeTranslation +customerPortalUser +CustomerPortalUser +CustomerSuccess +CustomEvent +CUSTOMEVENT +CUSTOMEVENTS +CustomExcludedUser +CustomExperience +CustomExperienceBranding +CustomExperienceTabSet +CustomFeedFilter +CustomField +CustomFieldTranslation +CustomLabel +CustomLabels +CustomLabelTranslation +CustomLinks +CustomList +CustomMetadata +CustomMetadataValue +CustomNotificationType +CustomObject +CustomObjects +CustomObjectTranslation +CustomPageWebLink +CustomPageWebLinkTranslation +CustomPermission +CustomPermissionDependencyRequired +CustomPermissions +CustomSettingsType +CustomShortcut +CustomSite +CustomSummaryFormula +CustomTab +CustomTabTranslation +CustomUser +CustomValue +CVE +cy +CYP +CZK +da +DashboardComponent +DashboardComponentColumn +DashboardComponentColumnType +DashboardComponentFilter +DashboardComponentSection +DashboardComponentSize +DashboardComponentSnapshot +DashboardComponentSortInfo +DashboardComponentType +DashboardFilter +DashboardFilterColumn +DashboardFilterOperation +DashboardFilterOption +DashboardFlexTableComponentProperties +DashboardFolder +DashboardGridComponent +DashboardGridLayout +DashboardMobileSettings +DashboardTableColumn +DashboardType +DataCategory +DataCategoryFilterOperation +DataCategoryGroup +Datacloud +DataExport +DataIntendedToBePublic +Datajourney +DataPipeline +DataPipelineType +dataType +dataTypeFilterOperatorMap +datatypes +DATATYPES +datetime +Datetime +DateTime +DATETIME +Datetimes +DayInMonth +ddThh +de +deactivateSessionPermSet +DeactivationFailed +DefaultChannel +DefaultOff +DefaultOn +DefaultQuoteTemplate +DefaultServiceReportTemplate +DefaultShortcut +DEFAULTVALUE +DefaultWorkflowUser +Delative +DelegateGroup +DeleteConstraint +DELETEs +DeployDetails +DeploymentStatus +DeployMessage +DeployOptions +deployOrchestration +Des +Desc +DescribeMetadataObject +dev +DeveloperControlled +DevicePlatformType +DeviceType +df +DisableFeedTrackingHeader +DisplayCurrency +DisplayText +DJF +DKK +Dockable +DocumentFolder +DoesNotContainPassword +DOESNT +doNotCreateOpportunity +Donut +DOP +DownForMaintenance +dplyr +DropdownBox +DupeActionType +DupeSecurityOptionType +DuplicateRule +DuplicateRuleFilter +DuplicateRuleFilterItem +DuplicateRuleMatchRule +DWG +DZD +EclairGeoData +EclairMap +ECS +EditAllContents +EditDescription +EG +EGP +EightHours +el +Elative +Electoronics +elementName +elementType +EmailAddress +emailAlert +EmailFolder +EmailHeader +EmailMessageEvent +EmailServicesAddress +EmailServicesAttOptions +EmailServicesErrorAction +EmailServicesFunction +emailSimple +EmailTemplate +EmailTemplateStyle +EmailTemplateType +EmailTemplateUiType +EmailToCase +EmailToCaseOnFailureActionType +EmailToCaseRoutingAddress +EmailToCaseRoutingAddressType +EmailToCaseSettings +EmbeddedServiceBranding +EmbeddedServiceConfig +EmbeddedServiceFieldService +EmbeddedServiceFontSize +EmbeddedServiceLiveAgent +EmbeddedServiceQuickAction +EmbeddedServiceScenario +emptyRecycleBin +EncryptedFieldMaskChar +EncryptedFieldMaskType +EncryptedText +EndsWith +EnforceSharingRules +EntitlementProcess +EntitlementProcessMilestoneItem +EntitlementProcessMilestoneTimeTrigger +EntitlementSettings +EntitlementTemplate +eo +EO +EqualTo +Ergative +ERN +errorCode +errorIdentifier +errorParams +EscalateToRecord +EscalationAction +EscalationRule +EscalationRules +EscalationStartTimeType +Essive +Essiveformal +et +ETB +eu +EUC +EventDelivery +EventDeliveryType +EventParameterMap +eventParameterName +EventSubscription +EVENTTYPE +EveryoneButCreator +EXCELT +EXE +explicity +ExtendedErrorCode +ExtendedErrorDetails +extensionName +ExternalDataSource +ExternalDataSourceType +ExternalLookup +ExternalPrincipalType +ExternalServiceRegistration +FacebookPost +Factmap +failedResults +FederationId +FeedElement +FeedFilterCriterion +FeedItemDisplayFormat +FeedItemSettings +FeedItemType +FeedItemVisibility +FeedLayout +FeedLayoutComponent +FeedLayoutComponentType +FeedLayoutFilter +FeedLayoutFilterPosition +FeedLayoutFilterType +fi +FIELDASSIGNMENT +FieldManageability +FieldMapping +FieldMappingField +FieldMappingRow +fieldName +FieldOverride +fieldReference +FIELDREFERENCE +fieldRelationshipName +FIELDSERVICE +FieldServiceMobile +FieldServiceSettings +FieldServiceWeb +FieldSet +FieldSetItem +FieldSetTranslation +fieldType +FieldType +FieldUpdate +FieldUpdateOperation +fieldValue +FieldValue +FifteenMinutes +FileDownloadBehavior +FileProperties +filesystem +FileType +FileTypeDispositionAssignmentBean +FileUploadAndDownloadSecuritySettings +FilterItem +FilterOperation +FilterScope +filterValues +FIM +finaly +findDuplicatesByIds +FindSimilarOppFilter +FirstName +FirstResponse +FiscalPeriod +FISCALPERIOD +FiscalQuarter +FiscalWeek +FISCALWEEK +FiscalYear +FiscalYearSettings +FiveAttempts +FJD +FK +FKP +Flexipage +FlexiPage +FLEXIPAGE +FlexiPageRegion +FlexiPageRegionMode +FlexiPageRegionType +FlexiPageTemplateInstance +FlexiPageType +FlexTable +FlowAction +FlowActionCall +FlowActionCallInputParameter +FlowActionCallOutputParameter +FlowApexPluginCall +FlowApexPluginCallInputParameter +FlowApexPluginCallOutputParameter +FlowAssignment +FlowAssignmentItem +FlowAssignmentOperator +FlowBaseElement +FlowCategory +FlowCategoryItems +FlowChoice +FlowChoiceTranslation +FlowChoiceUserInput +FlowChoiceUserInputTranslation +FlowComparisonOperator +FlowCondition +FlowConnector +FlowConstant +FlowDataType +flowDecision +FlowDecision +FlowDefinition +FlowDefinitionTranslation +FlowDynamicChoiceSet +FlowElement +FlowElementReferenceOrValue +FlowFormula +FlowInputFieldAssignment +FlowInputValidationRule +FlowInputValidationRuleTranslation +FlowLoop +FlowMetadataValue +flowName +FlowNode +FlowOutputFieldAssignment +FlowProcessType +FlowRecordCreate +FlowRecordDelete +FlowRecordFilter +FlowRecordFilterOperator +FlowRecordLookup +FlowRecordUpdate +FlowRule +FlowScreen +FlowScreenField +FlowScreenFieldInputParameter +FlowScreenFieldOutputParameter +FlowScreenFieldTranslation +FlowScreenFieldType +FlowScreenRule +FlowScreenRuleAction +FlowScreenTranslation +FlowStage +FlowStep +FlowSubflow +FlowSubflowInputAssignment +FlowSubflowOutputAssignment +FlowTextTemplate +FlowTranslation +FLOWTYPE +FlowVariable +flowVersion +FlowWait +FlowWaitEvent +FlowWaitEventInputParameter +FlowWaitEventOutputParameter +FolderAccessTypes +FolderId +FolderShare +FolderShareAccessLevel +FolderSharedToType +ForecastCategories +ForecastingCategoryMapping +ForecastingDateType +ForecastingDisplayedFamilySettings +ForecastingSettings +ForecastingTypeSettings +ForecastRangeSettings +formalLetter +FormFactor +formulaExpression +FourHours +freeForm +FreezeAndNotify +FRF +FullAccess +fullName +fullScreen +ga +GBP +generateWorkOrders +geolocation +GEOLOCATION +GETs +GHC +GHS +GIP +github +GlobalPicklistValue +GlobalQuickActionTranslation +GlobalValueSet +GlobalValueSetTranslation +GMD +GNF +googlesheets +GotoNextStep +GRD +greaterOrEqual +greaterThan +GreaterThan +GreaterThanOrEqualTo +GTQ +GWP +GYD +GZIP +hardDelete +HelpAndToolLinks +hh +HideBlankLines +HideHeader +HideShare +HighVolume +hiratake +HistoryRetentionPolicy +HK +HKD +HKSCS +HN +HNL +HomePage +HomePageComponent +HomePageLayout +HorizontalBar +HorizontalBarGrouped +HorizontalBarStacked +HorizontalBarStackedTo +HRD +HRK +HTG +HTM +htmlArea +HttpDelete +HttpGet +HttpHead +HttpPatch +HttpPost +HttpPut +https +httr +HTX +hu +HUF +hy +HyphenSeparator +IDASSIGNMENT +idcol +IdeaReputationLevel +IdeasSettings +IdpInitiated +IDR +IEP +Illative +ILS +imageOrNote +incompatibleDataType +incompatibleValue +InDevelopment +IndexField +IndirectLookup +Inessive +INI +inputAssignmentNames +InputField +INPUTPARAM +inputParameterName +inputParameterNames +inputVariableName +INR +InsightParentType +InsightTrendType +InsightType +InstalledPackage +IntegrationHubSettings +IntegrationHubSettingsType +InternalUsers +invalidTokens +invalidValue +InvocableAction +InvocableActionType +InvocableProcess +io +ios +IpRange +IQD +IRR +ISK +IsNull +isPkChunkingEnabled +ISREQUIRED +IterationOrder +ITL +iw +ja +Janrain +javascript +jennybc +JFIF +JIS +JMD +JobComplete +jobType +JOD +JourneyBuilderIntegration +JPE +JPG +JPY +js +JS +JSON +ka +KES +KeyboardShortcuts +KeywordList +KGS +KHR +KMF +KnowledgeAnswerSettings +KnowledgeCaseEditor +KnowledgeCaseField +KnowledgeCaseFieldsSettings +KnowledgeCaseSettings +KnowledgeCommunitiesSettings +KnowledgeLanguage +KnowledgeLanguageLookupValueType +KnowledgeLanguageSettings +KnowledgePublish +KnowledgeSettings +KnowledgeSitesSettings +KnowledgeSuggestedArticlesSettings +KnowledgeWorkflowAction +KnowledgeWorkOrderField +KnowledgeWorkOrderFieldsSettings +KnowledgeWorkOrderLineItemField +KnowledgeWorkOrderLineItemFieldsSettings +ko +KPW +KRW +KWD +KYD +KZT +LAK +LargeTextArea +lastFour +LASTMONTH +LastName +LASTTHIS +LASTTHISMONTH +LASTWEEK +LayoutColumn +LayoutHeader +LayoutItem +LayoutSection +LayoutSectionStyle +LayoutSectionTranslation +LayoutTranslation +LazyData +LBP +LeadConvertSettings +LeadSource +LeadStatus +LeastActive +leftElementName +leftElementType +LeftFixed +LeftFloat +LEFTOPERAND +LeftToRight +lessOrEqual +lessThan +LessThan +LessThanOrEqualTo +LetterheadHeaderFooter +LetterheadHorizontalAlignment +LetterheadLine +LetterheadVerticalAlignment +LF +LFs +LicensedCustomPermissions +LicenseDefinition +lifecycle +Lifecycle +LightningBolt +LightningBoltCategory +LightningBoltFeatures +LightningBoltImages +LightningBoltItems +LightningComponent +LightningComponentBundle +LightningExperienceTheme +LimitInfoHeader +LineCumulative +LineCumulativeGrouped +LineGrouped +LineGroupedCumulative +LinkedIn +LinkPost +ListMetadataQuery +ListPlacement +ListView +ListViewDefinition +ListViewFilter +ListViewRecord +LiveAgentConfig +LiveAgentSettings +LiveChatAgentConfig +LiveChatButton +LiveChatButtonDeployments +LiveChatButtonInviteEndPosition +LiveChatButtonInviteStartPosition +LiveChatButtonPresentation +LiveChatButtonRoutingType +LiveChatButtonSkills +LiveChatButtonType +LiveChatDeployment +LiveChatDeploymentDomainWhitelist +LiveChatSensitiveDataRule +LiveMessageSettings +LKR +localAction +LocaleOptions +Locative +LockoutInterval +LogACall +LogANote +LogCategory +LogCategoryLevel +LoggedInUser +LoginEvent +LoginFlow +LogInfo +LoginScopeHeader +LongTextArea +LookupFilter +LookupFilterTranslation +LookupValue +LookupValueType +LRD +LSL +lt +LTL +LUF +lv +LVL +LY +LYD +MacroSettings +MailAppAppPage +ManageableState +ManagedTopic +ManagedTopics +ManagerAndSubordinatesInternal +MappingOperation +MarketingActionSettings +MarketingResourceType +massActionButton +MasterDetail +MASTERFLOW +MatchBlanks +MatchingMethod +MatchingRule +MatchingRuleItem +MatchingRules +MatchingRuleStatus +MaxDaysInCommunity +maxLength +maxLimit +MaxLoginAttempts +MDL +MDM +mergeFieldReference +MessageType +MetadataRelationship +metadataValue +METADATAVALUES +MetadataWithContent +metricRefresh +MGA +MGF +MHTM +MHTML +MicrosoftACS +MilestoneEvent +MilestoneTimeUnits +MilestoneType +MilestoneTypeRecurrenceType +MiniLayout +minitablet +MISTMATCHED +mk +MKD +MMK +MNT +MobileNav +MobileSettings +ModeratedEntityField +ModerationRule +ModerationRuleAction +ModerationRuleType +ModifiedDate +MonitoredEvents +MonthInYear +MostAvailable +MOV +MRO +MruHeader +MruList +MruRow +MTL +multiBatch +MultiBlock +Multipicklist +MultiSelectCheckboxes +MULTISELECTCHOICE +MULTISELECTFIELD +MultiselectPicklist +MultiSelectPicklist +MUR +MVR +MWK +MX +MXN +MXV +MYR +MyTeamTerritory +MyTeamUser +MyTerritory +MZM +MZN +NAD +NamedCredential +NamedUser +NameSettings +NavigationLinkSet +NavigationMenuItem +NavigationSubMenu +NavType +NetworkAccess +NetworkBranding +NetworkMemberGroup +NetworkPageOverride +NetworkPageOverrideSetting +NetworkStatus +NetworkTabSet +NetworkUserType +NewChild +NewChildRecordType +NewRecordType +newWindow +NextAutomatedApprover +NEXTFY +NEXTMONTH +NextOwnerType +NEXTQ +NextValue +NEXTWEEK +NEXTY +NGN +NinetyDays +nino +NIO +nl +NL +NLG +NoAuthentication +NoContent +nodeset +NoFraming +NOK +NoLimit +NONCOLLECTION +NONSURVEY +NONVARIABLE +NoRestriction +noSidebar +notContain +notEqual +NotEqualTo +NoTestRun +NOTFOUND +NotVisible +NullNotAllowed +NULLs +NZD +oauth +Oauth +OAuth +ObjectFilterOperator +ObjectHomeChart +ObjectMapping +ObjectMappingField +objectName +ObjectNameCaseValue +ObjectPage +ObjectRelationship +ObjectSearchSetting +objectType +OBJECTTYPE +ObjectUsage +OBJECTVARIABLE +objectVariableName +OData +ODP +ODT +OfferFeedback +OfflineAccess +OFFSETNUMBER +OFFSETUNIT +OGV +OLDOBJECTVARIABLE +oldObjectVariableName +OMR +onAllChanges +OncePerUser +OnChart +onClickJavaScript +onCreateOnly +onCreateOrTriggeringUpdate +OneColumn +OneYear +OnRecursiveUpdate +OpenCTI +OpenID +OpenIdConnect +OpenSearch +operatorName +OpportunityCloseDate +opportunityId +OpportunityListFieldsLabelMapping +OpportunityListFieldsSelectedSettings +OpportunityListFieldsUnselectedSettings +opportunityName +OpportunitySettings +opportunityTeam +OPX +OrchestrationContext +OrchestrationContextEvent +orchestrationDebugLog +OrchestrationFlow +orchestrationTimer +OrderSettings +Org's +OrganizationSettingsDetail +OrgPreferenceSettings +OrgWideEmailAddress +otherFieldName +OutboundMessage +outgoingemail +outputAssignment +outputAssignmentName +OUTPUTPARAM +outputParameter +outputParameterNames +outputVariableName +OwnerChangeOptions +ownerId +PAB +PackageTypeMembers +PackageVersion +PackageVersionHeader +PageComponentType +PageComponentWidth +PageLayout +PARAM +parameterName +Parametrized +parentFlowName +ParentId +ParentIds +parentScreenFieldName +partnerUser +PartnerUser +PasswordField +PasswordPolicies +PATCHs +PathAssistant +PathAssistantSettings +PathAssistantStep +PAUSEDTEXT +PeriodTypes +PermissionSet +PermissionSetApexClassAccess +PermissionSetApexPageAccess +PermissionSetApplicationVisibility +PermissionSetCustomPermissions +PermissionSetExternalDataSourceAccess +PermissionSetFieldPermissions +PermissionSetGroup +PermissionSetObjectPermissions +PermissionSetRecordTypeVisibility +PermissionSetTabSetting +PermissionSetTabVisibility +PermissionSetUserPermission +PersistentId +PersonAccount +PersonalEnabled +PersonalJourneySettings +PersonalTagging +PersonListSettings +PerUser +PGK +PhP +picklist +Picklist +PICKLIST +PicklistEntry +PICKLISTFIELD +PicklistValue +picklistValues +PicklistValueTranslation +PipeSeparator +PJP +PJPEG +Pkb +PKChunking +pkgdown +PKR +PlatformActionGroupCategory +PlatformActionList +PlatformActionListContext +PlatformActionListItem +PlatformActionType +PlatformCachePartition +PlatformCachePartitionType +PlatformCacheType +PlatformEventType +PLN +POINTT +PollPost +portalRole +PortalRole +PortalRoleAndSubordinates +PortalRoles +portalRoleSubordinates +PortalType +POSIXct +POSIXlt +POSIXt +PostBinding +POSTs +PostTemplate +PPSX +PREV +PREVCUR +PREVCURFY +PREVCURY +PREVFY +PreviewImage +PreviousValue +PREVQ +PREVY +PrimaryTabComponents +Prm +PROCESSMETADATAVALUE +PROCESSMETADATAVALUES +ProcessSubmitterType +processType +PROCESSTYPE +ProductDate +ProductivityAction +ProductSettings +ProfileActionOverride +ProfileApexClassAccess +ProfileApexPageAccess +ProfileApplicationVisibility +ProfileCategoryGroupVisibility +ProfileCustomPermissions +ProfileExternalDataSourceAccess +ProfileFieldLevelSecurity +ProfileLayoutAssignment +ProfileLoginHours +ProfileLoginIpRange +ProfileObjectPermissions +ProfilePasswordPolicy +ProfileRecordTypeVisibility +ProfileSessionSetting +ProfileSkillPost +ProfileTabVisibility +ProfileUserPermission +programmatically +promotionLeft +promotionRight +propertyName +propertyType +ProvidedString +PSD +PTE +PublicFolderAccess +PublicGroups +PublicInternal +PublicTagging +PublishAsNew +purrr +PushNotification +PUTs +PY +PYG +QAR +QIngest +queryall +QueryOptions +questionName +QuestionPost +QuestionRestriction +queueable +QueueMembers +QueueSobject +quickAction +QuickAction +QuickActionLabel +QuickActionLayout +QuickActionLayoutColumn +QuickActionLayoutItem +QuickActionLayoutLeftRight +QuickActionLayoutTopDown +QuickActionList +QuickActionListItem +QuickActionSendEmailOptions +QuickActionTranslation +QuickActionType +QuickRecordType +QUIPDOC +QUIPSHEET +QuotasSettings +QuoteSettings +QuoteTemplate +RadioButtons +RateLimitTimePeriod +RCurl +README +Readonly +ReadOnly +readr +ReadSelect +ReadWrite +ReadWriteTransfer +RealName +RecommendationAudience +RecommendationAudienceDetail +RecommendationChannel +RecommendationDefinition +RecommendationDefinitionDetail +RecommendationStrategy +RecordEdit +RecordEditabilityType +RECORDFILTER +RECORDLOOKUP +RecordPage +RecordPreview +recordset +recordsets +RecordType +RecordTypePicklistValue +RecordTypeTranslation +RECORDUPDATE +recursChained +recursIndependently +RECURSIVECOUNTVARIABLE +RedirectBinding +REFERENCEDFLOW +referenceTo +RefreshToken +RegionFlagStatus +RejectRecord +RejectRequest +RelatedContent +RelatedContentItem +RelatedList +RelatedListItem +RelatedListRecord +relatedUserField +RELATIVEALARM +RemoteSiteSetting +ReplyAll +ReplyPost +ReportAggregate +ReportAggregateDatatype +ReportAggregateReference +ReportAggrType +ReportBlockInfo +ReportBucketField +ReportBucketFieldSourceValue +ReportBucketFieldType +ReportBucketFieldValue +ReportChart +ReportChartComponentLayoutItem +ReportChartComponentSize +ReportChartSize +ReportColorRange +ReportColumn +ReportCrossFilter +ReportDataCategoryFilter +ReportEvent +reportFilter +ReportFilter +ReportFilterItem +reportFilters +ReportFolder +ReportFormat +ReportFormulaNullTreatment +ReportGrouping +ReportHistoricalSelector +ReportJobSourceTypes +ReportLayoutSection +ReportParam +ReportSortType +ReportSummaryType +ReportTimeFrameFilter +ReportType +ReportTypeCategory +ReportTypeColumn +ReportTypeColumnTranslation +ReportTypeSectionTranslation +ReportTypeTranslation +ReputationBranding +ReputationLevel +ReputationLevelDefinitions +ReputationLevels +ReputationPointsRule +ReputationPointsRules +RequestFeedback +Requeue +requiredField +REST +RESTful +resultset +ResumeFlow +retrieveMetadata +retrieveRequest +RetrieveRequest +RetrieveResult +RForcecom +rightElementName +rightElementType +RIGHTOPERAND +RMB +ro +ROL +RoleAndSubordinates +RoleAndSubordinatesInternal +RoleOrTerritory +roleSubordinates +roleSubordinatesInternal +ROLLUP +RoutingType +RowCount +RowLabelAscending +RowLabelDescending +RowValueAscending +RowValueDescending +RSD +RTF +ru +RuleAssociation +RuleEntry +RuleItem +ruleName +RunAllTestsInOrg +RunLocalTests +RunSpecifiedTests +RunTestsResult +RUR +RWF +RypplePost +salesforce +SameOriginOnly +SAML +SamlEncryptionType +SamlIdentityLocationType +SamlIdentityType +SamlIdpSLOBinding +SamlInitiationMethod +SamlNameIdFormatType +SamlSpSLOBinding +SamlSsoConfig +SamlSubjectType +SamlType +SAR +SBD +ScatterGrouped +ScheduleDate +ScheduledRecommendation +ScheduledRecommendationDetail +sControl +Scontrol +SControlContentSource +ScontrolTranslation +SCR +SCREENFIELD +screenFieldName +SCREENFIELDTYPE +SCREENRULE +screenRuleName +SDD +SDG +SearchLayouts +SearchSettings +SearchSettingsByObject +SecurityClassification +SecuritySettings +SEK +SendAction +SendEmail +SensitiveDataActionType +ServiceCloudConsoleConfig +ServiceDesk +ServiceReportTemplate +sessionId +SessionSecurityLevel +SessionSettings +SessionTimeout +SetNull +SettingsOpportunityFilter +SetupObjectVisibility +SFDC +SFDCMobileSettings +SfdcOrg +SFX +SG +SGD +SharedTo +SharingBaseRule +SharingCriteriaRule +SharingModel +SharingOwnerRule +SharingReason +SharingReasonTranslation +SharingRecalculation +SharingRules +SharingSet +SharingTerritoryRule +SHP +SHTM +SHTML +SidebarComponent +SimpleURL +SiteClickjackProtectionLevel +SiteDotCom +Siteforce +SiteRedirect +SiteRedirectMapping +SiteType +SiteWebAddress +SixMonths +SixtyDays +SixtyMinutes +SJIS +sk +SkillAssignments +SkillProfileAssignments +SkillUserAssignments +SKK +sl +SLL +SNOTE +sobject +SObject +SOBJECT +sobjectName +SocialCustomerServiceSettings +SocialHandle +SocialNetwork +SocialPost +SocialPostContent +SocialPostSource +SOQL +sortOrder +SortOrder +sosl +SOSL +SpecialCharacters +SpecifiedUser +SpInitiated +SpokeId +sr +SRD +SRG +ssn +SSO +SSP +ssZ +stageName +StandardButton +StandardFieldTranslation +StandardValue +StandardValueSet +StandardValueSetTranslation +StandardVolume +StartFlow +startsWith +StartsWith +StaticResource +StaticResourceCacheControl +StepCriteriaNotMetType +StepRejectBehaviorType +stevenmmortimer +StevenMMortimer +StrategyNode +STYPI +SUBFLOW +subflowName +SUBFLOWS +subflowType +subfolders +SubjectNameId +Sublative +SubscriberControlled +SubtabComponents +successfulResults +SummaryLayout +SummaryLayoutItem +SummaryLayoutStyle +SummaryOperations +Superessive +SupervisorAgentConfigSkills +SupervisorAgentStatusFilter +SUR +surveyName +sv +SV +SVC +SVGZ +SY +SynonymDictionary +SynonymGroup +SYP +SZL +TabLimitConfig +TabVisibility +teardown +tempdir +TenAttempts +Termanative +TerritoryAndSubordinates +TestLevel +TestTest +TextArea +TextOnly +TextPost +th +THB +ThirtyDays +ThirtyMinutes +THISMONTH +THISNEXT +THISNEXTMONTH +THISWEEK +ThreeAttempts +THTML +thunderResponse +tibble +tibbles +Tidelift +tidyverse +TIF +timeframe +Timeframe +timespan +TJR +TJS +tl +TMM +TMT +TND +Toc +TopicsForObjects +topLeft +TopLeft +TopLeftLeft +TopLeftTop +TopRight +TopRightRight +TopRightTop +TopToBottom +TouchMobileSettings +TPE +TrackedChange +trailhead +TransactionSecurityAction +TransactionSecurityEventName +TransactionSecurityFlow +TransactionSecurityNotification +TransactionSecurityPolicy +Translative +TreatBlanksAs +TRIGGERTYPE +TRL +TRTF +TTD +TW +TWD +TwelveHours +TwentyFourHours +TwoColumnsLeftToRight +TwoColumnsTopToBottom +TwoHours +TXML +TxnSecurityPolicyType +TZS +UAH +UGX +UI +UiBehavior +UiFormulaCriterion +UiFormulaRule +UiPlugin +UiType +uk +undelete +Undelete +undeleted +Undeletes +UnderConstruction +unlist +Unlist +unmanaged +unnest +unnested +unprocessedRecords +UpperLowerCaseNumeric +UpperLowerCaseNumericSpecialCharacters +upsert +Upsert +upserting +Upserting +upserts +Upserts +ur +URI +UserCriteria +UserDateGranularity +UserDateInterval +userHierarchyField +UserId +USERINPUT +userLookup +UserProfile +UserProvisioningFlow +UserStatus +UserTerritoryDeleteHeader +UseSystemDefault +UtilityBar +UY +UYU +UZS +ValidationRule +VALIDATIONRULE +ValidationRuleTranslation +Validator +ValueSet +ValueSettings +ValueSetValuesDefinition +ValueTranslation +ValueTypeField +variableName +vctrs +VE +VEB +VEF +VerticalColumn +VerticalColumnGrouped +VerticalColumnGroupedLine +VerticalColumnLine +VerticalColumnStacked +VerticalColumnStackedLine +VerticalColumnStackedTo +VisibleOptional +VisibleOrRequired +VisibleRequired +VISIO +visualforce +Visualforce +VisualForce +visualforcePage +VisualforcePage +VisualizationPlugin +VisualizationResource +VisualizationResourceType +VisualizationType +VND +VUV +WAITEVENT +waitEventName +WasSelected +WasSet +WasVisited +WAV +WaveApplication +WaveDashboard +WaveDataflow +WaveDataset +WaveLens +WaveRecipe +WaveTemplateBundle +WaveXmd +WaveXmdDate +WaveXmdDimension +WaveXmdDimensionCustomAction +WaveXmdDimensionMember +WaveXmdDimensionSalesforceAction +WaveXmdMeasure +WaveXmdOrganization +WaveXmdRecordDisplayLookup +wdc +WebLink +WebLinkAvailability +WebLinkDisplayType +WebLinkPosition +WebLinkTranslation +WebLinkType +WebLinkWindowType +WebToCaseSettings +WEBVIEW +WeightedSourceCategory +WMA +WMV +WORDT +WorkflowAction +WorkflowActionReference +WorkflowActionType +WorkflowAlert +WorkflowEmailRecipient +WorkflowFieldUpdate +WorkflowFlowAction +WorkflowFlowActionParameter +WorkflowKnowledgePublish +WorkflowOutboundMessage +WorkflowRule +WorkflowSend +WorkflowTask +WorkflowTaskTranslation +WorkflowTimeTrigger +WorkflowTimeUnits +WorkflowTriggerTypes +WorkspaceMapping +WRF +WST +XAF +XCD +XHTML +XJS +xmlToList +XOF +XPF +XPSD +XSN +xxxxxZZZ +XYZXYZXYZXYZ +XZIP +yyyy +ZA +ZAR +zh +ZippedVersions +ZMK +ZMW +ZWD +ZWL diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/getting-started.R b/revdep/library.noindex/salesforcer/old/salesforcer/doc/getting-started.R new file mode 100644 index 00000000..e82186c9 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/getting-started.R @@ -0,0 +1,105 @@ +## ---- echo = FALSE------------------------------------------------------------ +NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true") +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + purl = NOT_CRAN, + eval = NOT_CRAN +) +options(tibble.print_min = 5L, tibble.print_max = 5L) + +## ----auth, include = FALSE---------------------------------------------------- +suppressWarnings(suppressMessages(library(dplyr))) +suppressWarnings(suppressMessages(library(here))) +library(salesforcer) +token_path <- Sys.getenv("SALESFORCER_TOKEN_PATH") +sf_auth(token = paste0(token_path, "salesforcer_token.rds")) + +## ----load-package, eval=FALSE------------------------------------------------- +# library(dplyr, warn.conflicts = FALSE) +# library(salesforcer) +# sf_auth() + +## ----other-params1, eval=FALSE------------------------------------------------ +# options(salesforcer.consumer_key = "012345678901-99thisisatest99connected33app22key") +# options(salesforcer.consumer_secret = "Th1s1sMyConsumerS3cr3t") +# +# sf_auth() + +## ----other-params2, eval=FALSE------------------------------------------------ +# options(salesforcer.proxy_url = "64.251.21.73") # IP or a named domain +# options(salesforcer.proxy_port = 8080) +# options(salesforcer.proxy_username = "user") +# options(salesforcer.proxy_password = "pass") +# options(salesforcer.proxy_auth = "ntlm") +# +# sf_auth() + +## ----------------------------------------------------------------------------- +# pull down information of person logged in +# it's a simple easy call to get started +# and confirm a connection to the APIs +user_info <- sf_user_info() +sprintf("Organization Id: %s", user_info$organizationId) +sprintf("User Id: %s", user_info$userId) + +## ----------------------------------------------------------------------------- +n <- 2 +new_contacts <- tibble(FirstName = rep("Test", n), + LastName = paste0("Contact-Create-", 1:n)) +created_records <- sf_create(new_contacts, "Contact") +created_records + +## ----------------------------------------------------------------------------- +retrieved_records <- sf_retrieve(ids=created_records$id, + fields=c("FirstName", "LastName"), + object_name="Contact") +retrieved_records + +## ----query-records------------------------------------------------------------ +my_soql <- sprintf("SELECT Id, + Account.Name, + FirstName, + LastName + FROM Contact + WHERE Id in ('%s')", + paste0(created_records$id , collapse="','")) + +queried_records <- sf_query(my_soql) +queried_records + +## ----update-records----------------------------------------------------------- +# Update some of those records +queried_records <- queried_records %>% + mutate(FirstName = "TestTest") + +updated_records <- sf_update(queried_records, object_name="Contact") +updated_records + +## ----------------------------------------------------------------------------- +deleted_records <- sf_delete(updated_records$id) +deleted_records + +## ----------------------------------------------------------------------------- +n <- 2 +new_contacts <- tibble(FirstName = rep("Test", n), + LastName = paste0("Contact-Create-", 1:n), + My_External_Id__c=letters[1:n]) +created_records <- sf_create(new_contacts, "Contact") + +upserted_contacts <- tibble(FirstName = rep("Test", n), + LastName = paste0("Contact-Upsert-", 1:n), + My_External_Id__c=letters[1:n]) +new_record <- tibble(FirstName = "Test", + LastName = paste0("Contact-Upsert-", n+1), + My_External_Id__c=letters[n+1]) +upserted_contacts <- bind_rows(upserted_contacts, new_record) + +upserted_records <- sf_upsert(input_data=upserted_contacts, + object_name="Contact", + external_id_fieldname="My_External_Id__c") +upserted_records + +## ---- include = FALSE--------------------------------------------------------- +deleted_records <- sf_delete(upserted_records$id, object_name = "Contact") + diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/getting-started.Rmd b/revdep/library.noindex/salesforcer/old/salesforcer/doc/getting-started.Rmd new file mode 100644 index 00000000..4023c213 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/getting-started.Rmd @@ -0,0 +1,238 @@ +--- +title: "Getting Started" +author: "Steven M. Mortimer" +date: "2020-08-16" +output: + rmarkdown::html_vignette: + toc: true + toc_depth: 4 + keep_md: true +vignette: > + %\VignetteIndexEntry{Getting Started} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, echo = FALSE} +NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true") +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + purl = NOT_CRAN, + eval = NOT_CRAN +) +options(tibble.print_min = 5L, tibble.print_max = 5L) +``` + +## Authentication + +First, load the {salesforcer} package and log in. There are two ways to +authenticate: + +1. OAuth 2.0 +2. ~~Basic Username-Password~~ + +**NOTE**: Beginning February 1st, 2022, Salesforce will be requiring customers +to enable multi-factor authentication, which means that basic authentication +using password and security token will no longer work. The function `sf_auth()` +will return the error message: + +```sh +INVALID_LOGIN: Invalid username, password, security token; or user locked out. +``` + +Also, it is a best practice to use OAuth 2.0 so that passwords do not have to be +embedded within scripts. OAuth 2.0 credentials are stored locally in a cached +file titled `.httr-oauth-salesforcer` in the current working directory. The +package will automatically refresh this cached token when it expires so you will +not have to call `sf_auth()` during every R session if the +`.httr-oauth-salesforcer` file is present in the working directory. + +```{r auth, include = FALSE} +suppressWarnings(suppressMessages(library(dplyr))) +suppressWarnings(suppressMessages(library(here))) +library(salesforcer) +token_path <- Sys.getenv("SALESFORCER_TOKEN_PATH") +sf_auth(token = paste0(token_path, "salesforcer_token.rds")) +``` + +```{r load-package, eval=FALSE} +library(dplyr, warn.conflicts = FALSE) +library(salesforcer) +sf_auth() +``` + +**Setting up your own Connected App for OAuth** + +Just a note, that it's not necessary to setup your own Connected App in Salesforce +to use OAuth 2.0 authentication. The only difference is that the authentication +will be run through the client created and associated with the {salesforcer} +package. By using the package client, you will **NOT** be giving access to Salesforce +to anyone, the package is just the medium for you to connect to your own data. +If you wanted more control you would specify those options like so: + +```{r other-params1, eval=FALSE} +options(salesforcer.consumer_key = "012345678901-99thisisatest99connected33app22key") +options(salesforcer.consumer_secret = "Th1s1sMyConsumerS3cr3t") + +sf_auth() +``` + +**Using a proxy connection** + +If you are required to connect to Salesforce via proxy you are able to specify +all of those parameters as options, as well. For each call via **httr** these +proxy settings will be passed along with the Salesforce authentication. + +```{r other-params2, eval=FALSE} +options(salesforcer.proxy_url = "64.251.21.73") # IP or a named domain +options(salesforcer.proxy_port = 8080) +options(salesforcer.proxy_username = "user") +options(salesforcer.proxy_password = "pass") +options(salesforcer.proxy_auth = "ntlm") + +sf_auth() +``` + +After logging in with `sf_auth()`, you can check your connectivity by looking at +the information returned about the current user. It should be information about you! + +```{r} +# pull down information of person logged in +# it's a simple easy call to get started +# and confirm a connection to the APIs +user_info <- sf_user_info() +sprintf("Organization Id: %s", user_info$organizationId) +sprintf("User Id: %s", user_info$userId) +``` + +## Creating records + +Salesforce has objects and those objects contain records. One default object is the +"Contact" object. This example shows how to create two records in the Contact object. + +```{r} +n <- 2 +new_contacts <- tibble(FirstName = rep("Test", n), + LastName = paste0("Contact-Create-", 1:n)) +created_records <- sf_create(new_contacts, "Contact") +created_records +``` + +## Retrieving records + +Retrieve pulls down a specific set of records and fields. It's very similar to +running a query, but doesn't use SOQL. Here is an example where we retrieve the +data we just created. + +```{r} +retrieved_records <- sf_retrieve(ids=created_records$id, + fields=c("FirstName", "LastName"), + object_name="Contact") +retrieved_records +``` + +## Querying records + +Salesforce has proprietary form of SQL called SOQL (Salesforce Object Query +Language). SOQL is a powerful tool that allows you to return the fields of +records in almost any object in Salesforce including Accounts, Contacts, Tasks, +Opportunities, even Attachments! Below is an example where we grab the data we +just created including Account object information for which the Contact record +is associated with. + +```{r query-records} +my_soql <- sprintf("SELECT Id, + Account.Name, + FirstName, + LastName + FROM Contact + WHERE Id in ('%s')", + paste0(created_records$id , collapse="','")) + +queried_records <- sf_query(my_soql) +queried_records +``` + +**NOTE**: In the example above, you'll notice that the `"Account.Name"` column +does not appear in the results. This is because the SOAP and REST APIs only +return an empty Account object for the record if there is no relationship to an +account ( see #78). There +is no reliable way to extract and rebuild the empty columns based on the query +string. If there were Account information, an additional column titled +`"Account.Name"` would appear in the results. Note, that the Bulk 1.0 and Bulk +2.0 APIs will return `"Account.Name"` as a column of all `NA` values for this +query because they return results differently. + +## Updating records + +After creating records you can update them using `sf_update()`. Updating a record +requires you to pass the Salesforce `Id` of the record. Salesforce creates a unique +18-character identifier on each record and uses that to know which record to +attach the update information you provide. Simply include a field or column in your +update dataset called "Id" and the information will be matched. Here is an example +where we update each of the records we created earlier with a new first name +called "TestTest". + +```{r update-records} +# Update some of those records +queried_records <- queried_records %>% + mutate(FirstName = "TestTest") + +updated_records <- sf_update(queried_records, object_name="Contact") +updated_records +``` + +## Deleting records + +You can also delete records in Salesforce. The method implements a "soft" delete +meaning that the deleted records go to the Recycle Bin which can be emptied or +queried against later in the event that the record needed. + +```{r} +deleted_records <- sf_delete(updated_records$id) +deleted_records +``` + +## Upserting records + +Finally, Salesforce has a unique method called "upsert" that allows you to +create and/or update records at the same time. More specifically, if the record +is not found based an an "External Id" field, then Salesforce will create the +record instead of updating one. Below is an example where we create 2 records, +then upsert 3, where 2 are matched and updated and one is created. **NOTE**: You +will need to create a custom field on the target object and ensure it is labeled as +an "External Id" field. Read more at: https://blog.jeffdouglas.com/2010/05/07/using-exernal-id-fields-in-salesforce/. + +```{r} +n <- 2 +new_contacts <- tibble(FirstName = rep("Test", n), + LastName = paste0("Contact-Create-", 1:n), + My_External_Id__c=letters[1:n]) +created_records <- sf_create(new_contacts, "Contact") + +upserted_contacts <- tibble(FirstName = rep("Test", n), + LastName = paste0("Contact-Upsert-", 1:n), + My_External_Id__c=letters[1:n]) +new_record <- tibble(FirstName = "Test", + LastName = paste0("Contact-Upsert-", n+1), + My_External_Id__c=letters[n+1]) +upserted_contacts <- bind_rows(upserted_contacts, new_record) + +upserted_records <- sf_upsert(input_data=upserted_contacts, + object_name="Contact", + external_id_fieldname="My_External_Id__c") +upserted_records +``` + +```{r, include = FALSE} +deleted_records <- sf_delete(upserted_records$id, object_name = "Contact") +``` + +## Check out the Tests + +The {salesforcer} package has quite a bit of unit test coverage to track any +changes made between newly released versions of the Salesforce API (typically 4 +each year). These tests are an excellent source of examples because they cover +most all cases of utilizing the package functions. You can access them here: https://github.com/StevenMMortimer/salesforcer/tree/main/tests/testthat/ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/getting-started.html b/revdep/library.noindex/salesforcer/old/salesforcer/doc/getting-started.html new file mode 100644 index 00000000..b8a299af --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/getting-started.html @@ -0,0 +1,512 @@ + + + + + + + + + + + + + + + + +Getting Started + + + + + + + + + + + + + + + + + + + + + + + + + +

Getting Started

+

Steven M. Mortimer

+

2020-08-16

+ + +
+ +
+

Authentication

+

First, load the {salesforcer} package and log in. There are two ways to authenticate:

+
    +
  1. OAuth 2.0
  2. +
  3. Basic Username-Password
  4. +
+

NOTE: Beginning February 1st, 2022, Salesforce will be requiring customers to enable multi-factor authentication, which means that basic authentication using password and security token will no longer work. The function sf_auth() will return the error message:

+
INVALID_LOGIN: Invalid username, password, security token; or user locked out.
+

Also, it is a best practice to use OAuth 2.0 so that passwords do not have to be embedded within scripts. OAuth 2.0 credentials are stored locally in a cached file titled .httr-oauth-salesforcer in the current working directory. The package will automatically refresh this cached token when it expires so you will not have to call sf_auth() during every R session if the .httr-oauth-salesforcer file is present in the working directory.

+
library(dplyr, warn.conflicts = FALSE)
+library(salesforcer)
+sf_auth()
+

Setting up your own Connected App for OAuth

+

Just a note, that it’s not necessary to setup your own Connected App in Salesforce to use OAuth 2.0 authentication. The only difference is that the authentication will be run through the client created and associated with the {salesforcer} package. By using the package client, you will NOT be giving access to Salesforce to anyone, the package is just the medium for you to connect to your own data. If you wanted more control you would specify those options like so:

+
options(salesforcer.consumer_key = "012345678901-99thisisatest99connected33app22key")
+options(salesforcer.consumer_secret = "Th1s1sMyConsumerS3cr3t")
+
+sf_auth()
+

Using a proxy connection

+

If you are required to connect to Salesforce via proxy you are able to specify all of those parameters as options, as well. For each call via httr these proxy settings will be passed along with the Salesforce authentication.

+
options(salesforcer.proxy_url = "64.251.21.73") # IP or a named domain
+options(salesforcer.proxy_port = 8080)
+options(salesforcer.proxy_username = "user")
+options(salesforcer.proxy_password = "pass")
+options(salesforcer.proxy_auth = "ntlm")
+
+sf_auth()
+

After logging in with sf_auth(), you can check your connectivity by looking at the information returned about the current user. It should be information about you!

+
# pull down information of person logged in
+# it's a simple easy call to get started 
+# and confirm a connection to the APIs
+user_info <- sf_user_info()
+sprintf("Organization Id: %s", user_info$organizationId)
+#> [1] "Organization Id: 00D6A0000003dN3UAI"
+sprintf("User Id: %s", user_info$userId)
+#> [1] "User Id: 0056A000000MPRjQAO"
+
+
+

Creating records

+

Salesforce has objects and those objects contain records. One default object is the “Contact” object. This example shows how to create two records in the Contact object.

+
n <- 2
+new_contacts <- tibble(FirstName = rep("Test", n),
+                       LastName = paste0("Contact-Create-", 1:n))
+created_records <- sf_create(new_contacts, "Contact")
+created_records
+#> # A tibble: 2 × 2
+#>   id                 success
+#>   <chr>              <lgl>  
+#> 1 0033s00001BXetGAAT TRUE   
+#> 2 0033s00001BXetHAAT TRUE
+
+
+

Retrieving records

+

Retrieve pulls down a specific set of records and fields. It’s very similar to running a query, but doesn’t use SOQL. Here is an example where we retrieve the data we just created.

+
retrieved_records <- sf_retrieve(ids=created_records$id, 
+                                 fields=c("FirstName", "LastName"), 
+                                 object_name="Contact")
+retrieved_records
+#> # A tibble: 2 × 4
+#>   sObject Id                 FirstName LastName        
+#>   <chr>   <chr>              <chr>     <chr>           
+#> 1 Contact 0033s00001BXetGAAT Test      Contact-Create-1
+#> 2 Contact 0033s00001BXetHAAT Test      Contact-Create-2
+
+
+

Querying records

+

Salesforce has proprietary form of SQL called SOQL (Salesforce Object Query Language). SOQL is a powerful tool that allows you to return the fields of records in almost any object in Salesforce including Accounts, Contacts, Tasks, Opportunities, even Attachments! Below is an example where we grab the data we just created including Account object information for which the Contact record is associated with.

+
my_soql <- sprintf("SELECT Id, 
+                           Account.Name, 
+                           FirstName, 
+                           LastName 
+                    FROM Contact 
+                    WHERE Id in ('%s')", 
+                   paste0(created_records$id , collapse="','"))
+
+queried_records <- sf_query(my_soql)
+queried_records
+#> # A tibble: 2 × 3
+#>   Id                 FirstName LastName        
+#>   <chr>              <chr>     <chr>           
+#> 1 0033s00001BXetGAAT Test      Contact-Create-1
+#> 2 0033s00001BXetHAAT Test      Contact-Create-2
+

NOTE: In the example above, you’ll notice that the "Account.Name" column does not appear in the results. This is because the SOAP and REST APIs only return an empty Account object for the record if there is no relationship to an account ( see #78). There is no reliable way to extract and rebuild the empty columns based on the query string. If there were Account information, an additional column titled "Account.Name" would appear in the results. Note, that the Bulk 1.0 and Bulk 2.0 APIs will return "Account.Name" as a column of all NA values for this query because they return results differently.

+
+
+

Updating records

+

After creating records you can update them using sf_update(). Updating a record requires you to pass the Salesforce Id of the record. Salesforce creates a unique 18-character identifier on each record and uses that to know which record to attach the update information you provide. Simply include a field or column in your update dataset called “Id” and the information will be matched. Here is an example where we update each of the records we created earlier with a new first name called “TestTest”.

+
# Update some of those records
+queried_records <- queried_records %>%
+  mutate(FirstName = "TestTest")
+
+updated_records <- sf_update(queried_records, object_name="Contact")
+updated_records
+#> # A tibble: 2 × 2
+#>   id                 success
+#>   <chr>              <lgl>  
+#> 1 0033s00001BXetGAAT TRUE   
+#> 2 0033s00001BXetHAAT TRUE
+
+
+

Deleting records

+

You can also delete records in Salesforce. The method implements a “soft” delete meaning that the deleted records go to the Recycle Bin which can be emptied or queried against later in the event that the record needed.

+
deleted_records <- sf_delete(updated_records$id)
+deleted_records
+#> # A tibble: 2 × 2
+#>   id                 success
+#>   <chr>              <lgl>  
+#> 1 0033s00001BXetGAAT TRUE   
+#> 2 0033s00001BXetHAAT TRUE
+
+
+

Upserting records

+

Finally, Salesforce has a unique method called “upsert” that allows you to create and/or update records at the same time. More specifically, if the record is not found based an an “External Id” field, then Salesforce will create the record instead of updating one. Below is an example where we create 2 records, then upsert 3, where 2 are matched and updated and one is created. NOTE: You will need to create a custom field on the target object and ensure it is labeled as an “External Id” field. Read more at: https://blog.jeffdouglas.com/2010/05/07/using-exernal-id-fields-in-salesforce/.

+
n <- 2
+new_contacts <- tibble(FirstName = rep("Test", n),
+                       LastName = paste0("Contact-Create-", 1:n), 
+                       My_External_Id__c=letters[1:n])
+created_records <- sf_create(new_contacts, "Contact")
+
+upserted_contacts <- tibble(FirstName = rep("Test", n),
+                            LastName = paste0("Contact-Upsert-", 1:n), 
+                            My_External_Id__c=letters[1:n])
+new_record <- tibble(FirstName = "Test",
+                     LastName = paste0("Contact-Upsert-", n+1), 
+                     My_External_Id__c=letters[n+1])
+upserted_contacts <- bind_rows(upserted_contacts, new_record)
+
+upserted_records <- sf_upsert(input_data=upserted_contacts, 
+                              object_name="Contact", 
+                              external_id_fieldname="My_External_Id__c")
+upserted_records
+#> # A tibble: 3 × 3
+#>   id                 success created
+#>   <chr>              <lgl>   <lgl>  
+#> 1 0033s00001BXdbvAAD TRUE    FALSE  
+#> 2 0033s00001BXdbwAAD TRUE    FALSE  
+#> 3 0033s00001BXenmAAD TRUE    TRUE
+
+
+

Check out the Tests

+

The {salesforcer} package has quite a bit of unit test coverage to track any changes made between newly released versions of the Salesforce API (typically 4 each year). These tests are an excellent source of examples because they cover most all cases of utilizing the package functions. You can access them here: https://github.com/StevenMMortimer/salesforcer/tree/main/tests/testthat/

+
+ + + + + + + + + + + diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/index.html b/revdep/library.noindex/salesforcer/old/salesforcer/doc/index.html new file mode 100644 index 00000000..5be3e0c2 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/index.html @@ -0,0 +1,64 @@ + + +R: Vignettes and other documentation + + + +
+

Vignettes and other documentation + +

+
+
+[Top] +
+

Vignettes from package 'salesforcer'

+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
salesforcer::getting-startedGetting StartedHTMLsourceR code
salesforcer::passing-control-argsPassing Control ArgsHTMLsourceR code
salesforcer::supported-queriesSupported QueriesHTMLsourceR code
salesforcer::transitioning-from-RForcecomTransitioning from RForcecomHTMLsourceR code
salesforcer::working-with-attachmentsWorking with AttachmentsHTMLsourceR code
salesforcer::working-with-bulk-apisWorking with Bulk APIsHTMLsourceR code
salesforcer::working-with-metadataWorking with MetadataHTMLsourceR code
salesforcer::working-with-reportsWorking with ReportsHTMLsourceR code
+
diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/passing-control-args.R b/revdep/library.noindex/salesforcer/old/salesforcer/doc/passing-control-args.R new file mode 100644 index 00000000..dc834c79 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/passing-control-args.R @@ -0,0 +1,64 @@ +## ---- echo = FALSE------------------------------------------------------------ +NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true") +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + purl = NOT_CRAN, + eval = NOT_CRAN +) +options(tibble.print_min = 5L, tibble.print_max = 5L) + +## ----auth, include = FALSE---------------------------------------------------- +suppressWarnings(suppressMessages(library(dplyr))) +suppressWarnings(suppressMessages(library(here))) +library(salesforcer) +token_path <- Sys.getenv("SALESFORCER_TOKEN_PATH") +sf_auth(token = paste0(token_path, "salesforcer_token.rds")) + +## ----load-package, eval=FALSE------------------------------------------------- +# library(salesforcer) +# sf_auth() + +## ----sample-create------------------------------------------------------------ +new_contact <- c(FirstName = "Jenny", + LastName = "Williams", + Email = "jennyw@gmail.com") +record1 <- sf_create(new_contact, + object_name = "Contact", + DisableFeedTrackingHeader = list(disableFeedTracking = TRUE)) +record1 + +## ----sample-create-w-duplicate------------------------------------------------ +# override the duplicate rules ... +record2 <- sf_create(new_contact, + object_name = "Contact", + DuplicateRuleHeader = list(allowSave = TRUE, + includeRecordDetails = FALSE, + runAsCurrentUser = TRUE)) +record2 + +# ... or succumb to the duplicate rules +record3 <- sf_create(new_contact, + object_name = "Contact", + DuplicateRuleHeader = list(allowSave = FALSE, + includeRecordDetails = FALSE, + runAsCurrentUser = TRUE)) +record3 + +## ----sample-create-w-warning-------------------------------------------------- +record4 <- sf_create(new_contact, + object_name = "Contact", + DuplicateRuleHeader = list(allowSave = FALSE, + includeRecordDetails = FALSE, + runAsCurrentUser = TRUE), + api_type = "REST") +record4 + +## ---- include = FALSE--------------------------------------------------------- +deleted_records <- sf_delete(c(record1$id, record2$id)) + +## ----sample-query------------------------------------------------------------- +sf_query("SELECT Id, Name FROM Account LIMIT 1000", + object_name = "Account", + control = sf_control(QueryOptions = list(batchSize = 200))) + diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/passing-control-args.Rmd b/revdep/library.noindex/salesforcer/old/salesforcer/doc/passing-control-args.Rmd new file mode 100644 index 00000000..53357bfb --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/passing-control-args.Rmd @@ -0,0 +1,226 @@ +--- +title: "Passing Control Args" +author: "Steven M. Mortimer" +date: "2020-07-08" +output: + rmarkdown::html_vignette: + toc: true + toc_depth: 4 + keep_md: true +vignette: > + %\VignetteIndexEntry{Passing Control Args} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, echo = FALSE} +NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true") +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + purl = NOT_CRAN, + eval = NOT_CRAN +) +options(tibble.print_min = 5L, tibble.print_max = 5L) +``` + +If you're inserting records from R you may want to turn off the assignment rules +or even bypass duplicate rules and alerts to save records. Beginning in Version 0.1.3 of +the {salesforcer} package many functions have a `control` argument that will allow +you to fine tune the behavior of calls to the Salesforce APIs. This vignette will +introduce the different options you can control and how to pass them into the {salesforcer} +functions you're already familiar with. + +## The new control argument + +This new feature can be seen in the `sf_create` (and many other functions) as +`control=list(...)`. The dots mean that you can pass any number of controls directly +into the function. + +```{r auth, include = FALSE} +suppressWarnings(suppressMessages(library(dplyr))) +suppressWarnings(suppressMessages(library(here))) +library(salesforcer) +token_path <- Sys.getenv("SALESFORCER_TOKEN_PATH") +sf_auth(token = paste0(token_path, "salesforcer_token.rds")) +``` + +First, authenticate and load any required packages for your analysis. + +```{r load-package, eval=FALSE} +library(salesforcer) +sf_auth() +``` + +In the example below, we demonstrate how to create a record, but use the control +arguments to prevent its creation from showing up in the Chatter feeds by setting +the `DisableFeedTrackingHeader`. + +```{r sample-create} +new_contact <- c(FirstName = "Jenny", + LastName = "Williams", + Email = "jennyw@gmail.com") +record1 <- sf_create(new_contact, + object_name = "Contact", + DisableFeedTrackingHeader = list(disableFeedTracking = TRUE)) +record1 +``` + +You will notice that the argument `DisableFeedTrackingHeader` can be included +right into the function without any documentation existing for it in the +`sf_create` function. This is because the dots (`...`) allow you to pass over a +dozen different control parameters and that documentation would be tedious to +create and maintain over multiple functions in the package. However, you will +notice in the documentation entry for the `control` argument there is a link to +a function called `sf_control` which you can use to directly to pass into +`control` or simply to review its documentation of all the possible control +parameters and their defaults. This is where you can review the various control +options in more detail before trying to set them. + +You may have also noticed that the argument DisableFeedTrackingHeader was +formatted as a list with an element inside called `disableFeedTracking` set to +`TRUE`. This may seem redundant but there are two reasons for this. First, this +is exactly how the Salesforce APIs documents these options, which are typically +referred to as "headers" because they are passed as a named header of the HTTP +request and then the header fields and values are provided for that header. +Second, some headers have multiple fields and values so a list is the only way +to provide multiple named fields and values under a single header entity. + +## An example using the `DuplicateRuleHeader` + +The `DuplicateRuleHeader` that controls whether the duplicate rules are +followed when inserting records from the API, has three fields: + + 1. `allowSave` - For a duplicate rule, when the Alert option is enabled, bypass + alerts and save duplicate records by setting this property to true. Prevent + duplicate records from being saved by setting this property to false. + + 2. `includeRecordDetails` - Get fields and values for records detected as + duplicates by setting this property to true. Get only record IDs for records + detected as duplicates by setting this property to false. + + 3. `runAsCurrentUser` - Make sure that sharing rules for the current user are + enforced when duplicate rules run by setting this property to true. Use the sharing + rules specified in the class for the request by setting this property to false. + If no sharing rules are specified, Apex code runs in system context and sharing + rules for the current user are not enforced. + +Specifying these arguments requires a `list` structure in R, which may seem redundant +in some cases, but is necessary to follow in order to build the API request correctly. + +```{r sample-create-w-duplicate} +# override the duplicate rules ... +record2 <- sf_create(new_contact, + object_name = "Contact", + DuplicateRuleHeader = list(allowSave = TRUE, + includeRecordDetails = FALSE, + runAsCurrentUser = TRUE)) +record2 + +# ... or succumb to the duplicate rules +record3 <- sf_create(new_contact, + object_name = "Contact", + DuplicateRuleHeader = list(allowSave = FALSE, + includeRecordDetails = FALSE, + runAsCurrentUser = TRUE)) +record3 +``` + +Per the description above, note that setting `allowSave=TRUE` will not override +rules where the "Action on Create" for a rule is set to "Block". If the +duplicate rule's action is "Allow" with an alert, then setting `allowSave=TRUE` +means the record will be created with no warning message. If `allowSave=FALSE`, +then the record will be prevented from being created. For additional information +on the `DuplicateRuleHeader`, please see the Salesforce documentation at: +https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_header_duplicateruleheader.htm + +Finally, you may notice during your use that only certain control arguments are +permitted based on the API. For example, the `DuplicateRuleHeader` is not implemented +in the REST API like it is in the SOAP API. In the example below you should take +note of two things: + + 1. When using the REST API and setting the `DuplicateRuleHeader`, then you will + notice a warning that the header was ignored. You will receive warnings when + trying to set any control parameters for an API or operation that does not + recognize that particular control. + + 2. In this example, you cannot bypass the duplicate rule alert to create the + record if using the REST API like you can with the SOAP API. + +```{r sample-create-w-warning} +record4 <- sf_create(new_contact, + object_name = "Contact", + DuplicateRuleHeader = list(allowSave = FALSE, + includeRecordDetails = FALSE, + runAsCurrentUser = TRUE), + api_type = "REST") +record4 +``` + +```{r, include = FALSE} +deleted_records <- sf_delete(c(record1$id, record2$id)) +``` + +## Creating the control argument with sf_control + +If this type of control structure is new to you, take a look at the documentation for +the `glm` and `glm.control` functions. The way these two functions behave is exactly how +functions like `sf_create` and `sf_control` work with each other. As demonstrated above +you can pass any number of arbitrary controls into the function and they are all +gathered up into the control by `control = list(...)`. However, you can specify the +control directly like this: + +```{r sample-query} +sf_query("SELECT Id, Name FROM Account LIMIT 1000", + object_name = "Account", + control = sf_control(QueryOptions = list(batchSize = 200))) +``` + +## Backwards compatibility for all_or_none and other named arguments + +You may already be taking advantage of the `all_or_none` or `line_ending` arguments +which are control arguments that were explicity included in functions. These argument +essentially hard coded values to pass the `AllOrNoneHeader` and `LineEndingHeader` +control parameters. Starting with the 0.1.3 release it is no longer necessary and +preferable not to have an argument like `all_or_none` listed explicity as an argument +since it can be provided in the `control` argument. Note: the `all_or_none` argument +and other explicit control arguments will still be available in {salesforcer} 0.1.3 +but will provide a deprecated warning. They will be removed in the next CRAN release +of the package so it will be important to update your code now if you are explicitly +passing these arguments and see a deprecation warning. + +## Reference Links + +Below is a list of links that go directly to the control arguments (a.k.a headers) +for the different APIs. I highly recommend reading this documentation before setting +a control parameter in R so you know exactly what the behavior will be and how to +specify it in R. You may notice that some controls are not included in the R package. +Some may be added in the future if requested and some will not be added given the +scope of the package. One final note is that some arguments in the REST API, like the +"All or None" behavior is not a header, but a parameter in the API call. For this reason +you will not see it listed in the REST API Headers section, but it is set in this R package +using the `AllOrNoneHeader` argument in `sf_control` just to provide consistency between +the SOAP and REST APIs. It would be confusing to have two arguments named differently, +one for each API, but to do the exact same thing from R. For this reason, many of the +control arguments match exactly as they are listed in the SOAP API, but can be used +across other APIs even if not exactly written that way in the Salesforce documentation +referenced below. + + * **SOAP API Headers**: + + * https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/soap_headers.htm + + * **REST API Headers**: + + * https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/headers.htm + + * **Bulk 1.0 API Headers**: + + * https://developer.salesforce.com/docs/atlas.en-us.api_asynch.meta/api_asynch/async_api_headers.htm + + * **Metadata API Headers**: + + * https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_headers.htm + + * **Bulk 2.0 API Headers**: None + * **Reports and Dashboards REST API Headers**: None diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/passing-control-args.html b/revdep/library.noindex/salesforcer/old/salesforcer/doc/passing-control-args.html new file mode 100644 index 00000000..381de33f --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/passing-control-args.html @@ -0,0 +1,485 @@ + + + + + + + + + + + + + + + + +Passing Control Args + + + + + + + + + + + + + + + + + + + + + + + + + +

Passing Control Args

+

Steven M. Mortimer

+

2020-07-08

+ + + + +

If you’re inserting records from R you may want to turn off the assignment rules or even bypass duplicate rules and alerts to save records. Beginning in Version 0.1.3 of the {salesforcer} package many functions have a control argument that will allow you to fine tune the behavior of calls to the Salesforce APIs. This vignette will introduce the different options you can control and how to pass them into the {salesforcer} functions you’re already familiar with.

+
+

The new control argument

+

This new feature can be seen in the sf_create (and many other functions) as control=list(...). The dots mean that you can pass any number of controls directly into the function.

+

First, authenticate and load any required packages for your analysis.

+
library(salesforcer)
+sf_auth()
+

In the example below, we demonstrate how to create a record, but use the control arguments to prevent its creation from showing up in the Chatter feeds by setting the DisableFeedTrackingHeader.

+
new_contact <- c(FirstName = "Jenny", 
+                 LastName = "Williams", 
+                 Email = "jennyw@gmail.com")
+record1 <- sf_create(new_contact,
+                     object_name = "Contact",
+                     DisableFeedTrackingHeader = list(disableFeedTracking = TRUE))
+record1
+#> # A tibble: 1 × 2
+#>   success errors    
+#>   <lgl>   <list>    
+#> 1 FALSE   <list [1]>
+

You will notice that the argument DisableFeedTrackingHeader can be included right into the function without any documentation existing for it in the sf_create function. This is because the dots (...) allow you to pass over a dozen different control parameters and that documentation would be tedious to create and maintain over multiple functions in the package. However, you will notice in the documentation entry for the control argument there is a link to a function called sf_control which you can use to directly to pass into control or simply to review its documentation of all the possible control parameters and their defaults. This is where you can review the various control options in more detail before trying to set them.

+

You may have also noticed that the argument DisableFeedTrackingHeader was formatted as a list with an element inside called disableFeedTracking set to TRUE. This may seem redundant but there are two reasons for this. First, this is exactly how the Salesforce APIs documents these options, which are typically referred to as “headers” because they are passed as a named header of the HTTP request and then the header fields and values are provided for that header. Second, some headers have multiple fields and values so a list is the only way to provide multiple named fields and values under a single header entity.

+
+
+

An example using the DuplicateRuleHeader

+

The DuplicateRuleHeader that controls whether the duplicate rules are followed when inserting records from the API, has three fields:

+
    +
  1. allowSave - For a duplicate rule, when the Alert option is enabled, bypass alerts and save duplicate records by setting this property to true. Prevent duplicate records from being saved by setting this property to false.

  2. +
  3. includeRecordDetails - Get fields and values for records detected as duplicates by setting this property to true. Get only record IDs for records detected as duplicates by setting this property to false.

  4. +
  5. runAsCurrentUser - Make sure that sharing rules for the current user are enforced when duplicate rules run by setting this property to true. Use the sharing rules specified in the class for the request by setting this property to false. If no sharing rules are specified, Apex code runs in system context and sharing rules for the current user are not enforced.

  6. +
+

Specifying these arguments requires a list structure in R, which may seem redundant in some cases, but is necessary to follow in order to build the API request correctly.

+
# override the duplicate rules ...
+record2 <- sf_create(new_contact,
+                     object_name = "Contact",
+                     DuplicateRuleHeader = list(allowSave = TRUE, 
+                                                includeRecordDetails = FALSE, 
+                                                runAsCurrentUser = TRUE))
+record2
+#> # A tibble: 1 × 2
+#>   id                 success
+#>   <chr>              <lgl>  
+#> 1 0033s00001BXfB1AAL TRUE
+
+# ... or succumb to the duplicate rules
+record3 <- sf_create(new_contact,
+                     object_name = "Contact",
+                     DuplicateRuleHeader = list(allowSave = FALSE, 
+                                                includeRecordDetails = FALSE, 
+                                                runAsCurrentUser = TRUE))
+record3
+#> # A tibble: 1 × 2
+#>   success errors    
+#>   <lgl>   <list>    
+#> 1 FALSE   <list [1]>
+

Per the description above, note that setting allowSave=TRUE will not override rules where the “Action on Create” for a rule is set to “Block”. If the duplicate rule’s action is “Allow” with an alert, then setting allowSave=TRUE means the record will be created with no warning message. If allowSave=FALSE, then the record will be prevented from being created. For additional information on the DuplicateRuleHeader, please see the Salesforce documentation at: https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_header_duplicateruleheader.htm

+

Finally, you may notice during your use that only certain control arguments are permitted based on the API. For example, the DuplicateRuleHeader is not implemented in the REST API like it is in the SOAP API. In the example below you should take note of two things:

+
    +
  1. When using the REST API and setting the DuplicateRuleHeader, then you will notice a warning that the header was ignored. You will receive warnings when trying to set any control parameters for an API or operation that does not recognize that particular control.

  2. +
  3. In this example, you cannot bypass the duplicate rule alert to create the record if using the REST API like you can with the SOAP API.

  4. +
+
record4 <- sf_create(new_contact,
+                     object_name = "Contact",
+                     DuplicateRuleHeader = list(allowSave = FALSE, 
+                                                includeRecordDetails = FALSE, 
+                                                runAsCurrentUser = TRUE),
+                     api_type = "REST")
+#> Warning: Ignoring the following controls which are not used in the REST API:
+#> DuplicateRuleHeader
+record4
+#> # A tibble: 1 × 2
+#>   success errors    
+#>   <lgl>   <list>    
+#> 1 FALSE   <list [1]>
+
+
+

Creating the control argument with sf_control

+

If this type of control structure is new to you, take a look at the documentation for the glm and glm.control functions. The way these two functions behave is exactly how functions like sf_create and sf_control work with each other. As demonstrated above you can pass any number of arbitrary controls into the function and they are all gathered up into the control by control = list(...). However, you can specify the control directly like this:

+
sf_query("SELECT Id, Name FROM Account LIMIT 1000",
+         object_name = "Account",
+         control = sf_control(QueryOptions = list(batchSize = 200)))
+#> # A tibble: 15 × 2
+#>   Id                 Name                                
+#>   <chr>              <chr>                               
+#> 1 0013s00000zFgA6AAK KEEP Test Account With Child Records
+#> 2 0013s00000zFdugAAC KEEP Test Account With Child Records
+#> 3 0013s000014jF2vAAE Test Account For Performance Test   
+#> 4 0016A0000035mJEQAY GenePoint                           
+#> 5 0016A0000035mJCQAY United Oil & Gas, UK                
+#> # … with 10 more rows
+
+
+

Backwards compatibility for all_or_none and other named arguments

+

You may already be taking advantage of the all_or_none or line_ending arguments which are control arguments that were explicity included in functions. These argument essentially hard coded values to pass the AllOrNoneHeader and LineEndingHeader control parameters. Starting with the 0.1.3 release it is no longer necessary and preferable not to have an argument like all_or_none listed explicity as an argument since it can be provided in the control argument. Note: the all_or_none argument and other explicit control arguments will still be available in {salesforcer} 0.1.3 but will provide a deprecated warning. They will be removed in the next CRAN release of the package so it will be important to update your code now if you are explicitly passing these arguments and see a deprecation warning.

+
+ + + + + + + + + + + + diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/supported-queries.R b/revdep/library.noindex/salesforcer/old/salesforcer/doc/supported-queries.R new file mode 100644 index 00000000..98969647 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/supported-queries.R @@ -0,0 +1,200 @@ +## ---- echo = FALSE------------------------------------------------------------ +NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true") +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + purl = NOT_CRAN, + eval = NOT_CRAN +) +options(tibble.print_min = 5L, tibble.print_max = 5L) + +## ----auth, include = FALSE---------------------------------------------------- +suppressWarnings(suppressMessages(library(dplyr))) +suppressWarnings(suppressMessages(library(here))) +library(salesforcer) +token_path <- Sys.getenv("SALESFORCER_TOKEN_PATH") +sf_auth(token = paste0(token_path, "salesforcer_token.rds")) + +## ----load-package, eval=FALSE------------------------------------------------- +# library(dplyr, warn.conflicts = FALSE) +# library(salesforcer) +# sf_auth() + +## ----query-records------------------------------------------------------------ +soql <- "SELECT Id, + FirstName, + LastName + FROM Contact + LIMIT 10" + +queried_records <- sf_query(soql) # REST API is the default api_type +queried_records + +queried_records <- sf_query(soql, api_type = "SOAP") +queried_records + +## ----setup-performance-test--------------------------------------------------- +# create a new account +# (if replicating, you may or may not have an external id field in your Org) +prefix <- paste0("APerfTest-", as.integer(runif(1,1,99999))) +new_account <- sf_create( + tibble( + Name = "Test Account For Performance Test", + My_External_Id__c = prefix, + Description = paste0("This is a test account with 1,000 records for ", + "testing the performance differences between the ", + "SOAP and REST APIs.") + ), + object_name = "Account" +) + +# create and associate a thousand new contacts with that account +# (again, you may or may not have an external id field in your Org) +n <- 1000 +prefix <- paste0("CPerfTest-", as.integer(runif(1,1,99999)), "-") +new_contacts <- tibble(FirstName = rep("Test", n), + LastName = paste0("Query-Vignette", 1:n), + test_number__c = 999.9, + AccountId = rep(new_account$id, n), + My_External_Id__c=paste0(prefix, 1:n)) +new_contacts_res <- sf_create(new_contacts, "Contact", api_type = "Bulk 2.0") + +## ----run-performance-test, message=FALSE-------------------------------------- +qry <- function(api_type){ + sf_query( + sprintf("SELECT Id, Name, Owner.Id, + (SELECT Id, LastName, Owner.Id FROM Contacts) + FROM Account + WHERE Id = '%s'", + new_account$id), + api_type = api_type + ) +} +res <- microbenchmark::microbenchmark( + qry("REST"), + qry("SOAP"), + times = 5, + unit = "s" +) +res + +suppressWarnings(suppressMessages( + ggplot2::autoplot(res) + + ggplot2::scale_y_continuous(name="Time [seconds]", n.breaks=6) +)) + +## ----unsupported-bulk-queries------------------------------------------------- +# nested relationship query +# (supposed to return the id and first name of all contacts on each account) +try( + sf_query( + "SELECT Id, Name, + (SELECT Id, FirstName FROM Contacts) + FROM Account", + api_type = "Bulk 2.0" + ) +) + +# aggregate query +# (supposed to return the count of contacts per account) +try( + sf_query( + "SELECT Account.Id, Count(Name) contacts_n + FROM Contact + GROUP BY Account.Id", + api_type = "Bulk 2.0" + ) +) + +## ----------------------------------------------------------------------------- +contacts <- sf_query("SELECT Id, FirstName, Account.Id + FROM Contact", + api_type = "Bulk 2.0") + +accounts <- sf_query("SELECT Id, Name + FROM Account", + api_type = "Bulk 2.0") + +nested_query_recs <- accounts %>% + left_join(contacts %>% + rename(`Contact.Id` = Id, + `Contact.FirstName` = FirstName), + by = c("Id" = "Account.Id")) +nested_query_recs + +aggregate_query_recs <- nested_query_recs %>% + group_by(Id) %>% + summarize(.groups = 'drop', + contacts_n = sum(!is.na(Contact.Id))) +aggregate_query_recs + +## ----run-performance-test2, eval=FALSE---------------------------------------- +# qry_compare <- function(api_type){ +# soql <- sprintf("SELECT Id, LastName, Account.Id, Account.Name, Owner.Id +# FROM Contact +# WHERE Account.Id = '%s'", +# new_account$id) +# sf_query(soql, api_type = api_type) +# } +# +# res <- microbenchmark::microbenchmark( +# qry_compare("REST"), +# qry_compare("Bulk 1.0"), +# qry_compare("Bulk 2.0"), +# times = 5, +# unit = "s" +# ) + +## ----------------------------------------------------------------------------- +queried_records <- sf_query(soql, api_type = "Bulk 1.0") + +## ----cleanup-performance-test------------------------------------------------- +# cleanup performance test Contact records ... +contacts_to_delete <- sf_query( + sprintf("SELECT Id + FROM Contact + WHERE Account.Id = '%s'", + new_account$id) +) +sf_delete(contacts_to_delete$Id, "Contact", api_type="Bulk 2.0") + +# ... and finally delete the account +sf_delete(new_account$id) + +## ----------------------------------------------------------------------------- +# child-to-parent relationship (e.g. Account.Name from Contact record) +sf_query( + "SELECT Id, FirstName, Account.Name + FROM Contact + WHERE Account.Id != null" +) + +## ----------------------------------------------------------------------------- +# child-to-parent relationship (e.g. Account.Name from Contact record) +sf_query( + "SELECT Id, FirstName, Account.Name + FROM Contact + WHERE Account.Id = null" +) + +## ----------------------------------------------------------------------------- +try( + sf_query("SELECT Id, FirstName, Account.Owner.Id + FROM Contact", + api_type = "Bulk 2.0") +) + +## ----------------------------------------------------------------------------- +sf_query( + "SELECT Id, Name, + (SELECT Id, FirstName FROM Contacts) + FROM Account" +) + +## ----------------------------------------------------------------------------- +sf_query( + "SELECT Name, Owner.Id, + (SELECT Id, FirstName, Owner.Id FROM Contacts) + FROM Account" +) + diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/supported-queries.Rmd b/revdep/library.noindex/salesforcer/old/salesforcer/doc/supported-queries.Rmd new file mode 100644 index 00000000..f21331db --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/supported-queries.Rmd @@ -0,0 +1,432 @@ +--- +title: "Supported Queries" +author: "Steven M. Mortimer" +date: "2020-07-11" +output: + rmarkdown::html_vignette: + toc: true + toc_depth: 4 + keep_md: true +vignette: > + %\VignetteIndexEntry{Supported Queries} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, echo = FALSE} +NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true") +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + purl = NOT_CRAN, + eval = NOT_CRAN +) +options(tibble.print_min = 5L, tibble.print_max = 5L) +``` + +## Overview + +The following vignette outlines the different types of queries that have been +documented and tested. These are the "supported" query types that the {salesforcer} +package currently handles. If you run into an issue, please submit the issue +[HERE](https://github.com/StevenMMortimer/salesforcer/issues/new?assignees=StevenMMortimer&labels=&template=query-issue-template.md&title=) +in the GitHub repository so that we can fix or add your query type to this list. +Thank you! + +**Note**: Salesforce's proprietary form of SQL called SOQL (Salesforce Object +Query Language) is a powerful tool that allows you to return the fields of +records in almost any object in Salesforce. This includes standard objects like +Accounts, Contacts, and Tasks along with any custom objects and custom fields +created in your Org. You are encouraged to use Bulk APIs when: + + - You anticipate returning 10,000 records or more + - Your query does not involve a parent-to-child nested relationship query + - You would like to reduce the overall number of API calls to your Org + +If you are not familiar with SOQL, then please consider reading the following +resources: + + - Introduction to SOQL and SOSL + - SOQL SELECT Syntax + - Relationship Queries + - Async SOQL + - Overview of queries in Bulk 1.0 API + - Overview of queries in Bulk 2.0 API + +---- + +## Authentication + +First, load the {salesforcer} package and login. There are two ways to authenticate: +1) OAuth 2.0 (SSO) and 2) Basic Username-Password. It is recommended to use OAuth +2.0 so that passwords do not have to be embedded in scripts or environment variables. +By default, OAuth 2.0 stores the user's credentials in a locally cached file +entitled ".httr-oauth-salesforcer" in the current working directory and will be +refreshed automatically when the session expires. + +```{r auth, include = FALSE} +suppressWarnings(suppressMessages(library(dplyr))) +suppressWarnings(suppressMessages(library(here))) +library(salesforcer) +token_path <- Sys.getenv("SALESFORCER_TOKEN_PATH") +sf_auth(token = paste0(token_path, "salesforcer_token.rds")) +``` + +```{r load-package, eval=FALSE} +library(dplyr, warn.conflicts = FALSE) +library(salesforcer) +sf_auth() +``` + +## Default query behavior + +The default API for the `sf_query()` function is the REST API because it is both +fast and flexible. Every effort has been made so that the format of the results +from the REST and SOAP APIs is exactly the same. The only difference will be +speed. The REST API uses JSON, which can generally be processed more quickly +than XML used in the SOAP API. + +```{r query-records} +soql <- "SELECT Id, + FirstName, + LastName + FROM Contact + LIMIT 10" + +queried_records <- sf_query(soql) # REST API is the default api_type +queried_records + +queried_records <- sf_query(soql, api_type = "SOAP") +queried_records +``` + +## REST vs. SOAP API query performance test + +Below is a small example to roughly demonstrate the magnitude of the performance +difference between the REST and SOAP APIs when querying 1,000 records. + +**Setup performance test** + +```{r setup-performance-test} +# create a new account +# (if replicating, you may or may not have an external id field in your Org) +prefix <- paste0("APerfTest-", as.integer(runif(1,1,99999))) +new_account <- sf_create( + tibble( + Name = "Test Account For Performance Test", + My_External_Id__c = prefix, + Description = paste0("This is a test account with 1,000 records for ", + "testing the performance differences between the ", + "SOAP and REST APIs.") + ), + object_name = "Account" +) + +# create and associate a thousand new contacts with that account +# (again, you may or may not have an external id field in your Org) +n <- 1000 +prefix <- paste0("CPerfTest-", as.integer(runif(1,1,99999)), "-") +new_contacts <- tibble(FirstName = rep("Test", n), + LastName = paste0("Query-Vignette", 1:n), + test_number__c = 999.9, + AccountId = rep(new_account$id, n), + My_External_Id__c=paste0(prefix, 1:n)) +new_contacts_res <- sf_create(new_contacts, "Contact", api_type = "Bulk 2.0") +``` + +**Performance test** + +```{r run-performance-test, message=FALSE} +qry <- function(api_type){ + sf_query( + sprintf("SELECT Id, Name, Owner.Id, + (SELECT Id, LastName, Owner.Id FROM Contacts) + FROM Account + WHERE Id = '%s'", + new_account$id), + api_type = api_type + ) +} +res <- microbenchmark::microbenchmark( + qry("REST"), + qry("SOAP"), + times = 5, + unit = "s" +) +res + +suppressWarnings(suppressMessages( + ggplot2::autoplot(res) + + ggplot2::scale_y_continuous(name="Time [seconds]", n.breaks=6) +)) +``` + +As seen in the limited test above, the REST API can be anywhere from **4-6x** +faster than the SOAP API for a query on 1,000 contact records associated with a +single Account. Breaking up the number of records returned into smaller batches by setting +`QueryOptions = list(batchSize = 200)` typically does not affect this result very +much but it also depends on the number of fields in the query. For the REST API the +default is 2,000 records per batch with a minimum of 200 and maximum of 2,000. +For the SOAP API the default is 500 records per batch. For both APIs it is important +to note that there is no guarantee that the requested batch size is the actual +batch size. Changes are made as necessary to maximize performance. For example, +the SOAP API states "batch size will be no more than 200 if the SOQL statement +selects two or more custom fields of type long text". The REST API mentions that +the limit imposed by Salesforce's app servers is around 20,000 characters which +can cause batches to be smaller. In short, it's generally okay to use the default +batch sizes since Salesforce may optimize over your specified batch size anyways. + +## When to use the Bulk APIs for queries + +A general rule of thumb for using the Bulk APIs (Bulk 1.0 and Bulk 2.0) for +queries is anytime you need to retrieve more than 10,000 records. The main reasons +to not use the Bulk APIs are twofold. First, they do not support complex +relationship queries or aggregate queries. If you need to write a nested relationship +or aggregate query involving a large number of records you may be tempted to use +the REST API. However, it is recommended to perform two or more separate bulk +queries that retrieve the records you need and then join or aggregate the results +in R. + +```{r unsupported-bulk-queries} +# nested relationship query +# (supposed to return the id and first name of all contacts on each account) +try( + sf_query( + "SELECT Id, Name, + (SELECT Id, FirstName FROM Contacts) + FROM Account", + api_type = "Bulk 2.0" + ) +) + +# aggregate query +# (supposed to return the count of contacts per account) +try( + sf_query( + "SELECT Account.Id, Count(Name) contacts_n + FROM Contact + GROUP BY Account.Id", + api_type = "Bulk 2.0" + ) +) +``` + +The two queries above were trying to pull all the contacts for each account and +then get a count of how many contacts there are per account. If you have a lot +of records, using the REST API to return these results may not be feasible. Even +though the Bulk APIs cannot handle the same query, they can pull down massive +amounts of data quickly. In this case you can pull down all of the Contact records +and all of the Account records and then perform the calculation using **dplyr**, +like so: + +```{r} +contacts <- sf_query("SELECT Id, FirstName, Account.Id + FROM Contact", + api_type = "Bulk 2.0") + +accounts <- sf_query("SELECT Id, Name + FROM Account", + api_type = "Bulk 2.0") + +nested_query_recs <- accounts %>% + left_join(contacts %>% + rename(`Contact.Id` = Id, + `Contact.FirstName` = FirstName), + by = c("Id" = "Account.Id")) +nested_query_recs + +aggregate_query_recs <- nested_query_recs %>% + group_by(Id) %>% + summarize(.groups = 'drop', + contacts_n = sum(!is.na(Contact.Id))) +aggregate_query_recs +``` + +The second reason to not use the Bulk APIs is that there is a performance overhead +associated with every bulk (asynchronous) job that involves checking the status +of the job until it succeeds or fails before retrieving the results. + +The example below is provided so that you can take this code as an example to +run your own performance test of queries that return 10K, 100K, 1M+ records to +see where the Bulk APIs outperform the REST API. + +```{r run-performance-test2, eval=FALSE} +qry_compare <- function(api_type){ + soql <- sprintf("SELECT Id, LastName, Account.Id, Account.Name, Owner.Id + FROM Contact + WHERE Account.Id = '%s'", + new_account$id) + sf_query(soql, api_type = api_type) +} + +res <- microbenchmark::microbenchmark( + qry_compare("REST"), + qry_compare("Bulk 1.0"), + qry_compare("Bulk 2.0"), + times = 5, + unit = "s" +) +``` + +Note that the Bulk 1.0 API requires users to specify the target object along with +their submitted SOQL. This is because it is needed when creating the bulk job that +will manage and execute the query. + +```{r} +queried_records <- sf_query(soql, api_type = "Bulk 1.0") +``` + +As you can see above the {salesforcer} package will try to infer the object in +the query if not explicitly provided. If it does not guess correctly, then please +specify. + +**Cleanup after performance tests** + +By keeping track of the account ids used in our tests, it is fairly easy to find +and delete these test records from our Org to save space. + +```{r cleanup-performance-test} +# cleanup performance test Contact records ... +contacts_to_delete <- sf_query( + sprintf("SELECT Id + FROM Contact + WHERE Account.Id = '%s'", + new_account$id) +) +sf_delete(contacts_to_delete$Id, "Contact", api_type="Bulk 2.0") + +# ... and finally delete the account +sf_delete(new_account$id) +``` + +## Relationship queries + +Salesforce supports retrieving fields from related objects when querying another +object. This is similar to performing a JOIN in SQL, but without having to specify +the join keys because Salesforce already knows the relationship between the two +objects. There are two types of relationship queries (1. child-to-parent lookups +and 2. parent-to-child nested queries) detailed in the sections below. + +### child-to-parent "lookup" queries + +The first type of relationship query and the most common is child to parent. For +example, the Contact object (child) to their parent, the Account object. In order +to pull down parent object fields with your child record query, you just need to +prefix any fields from the related object by concatenating the name of the +object with the field name separated by a period. In the example below we are +retrieving all Contact object records that have a relationship to an Account. + +```{r} +# child-to-parent relationship (e.g. Account.Name from Contact record) +sf_query( + "SELECT Id, FirstName, Account.Name + FROM Contact + WHERE Account.Id != null" +) +``` + +Sometimes you may notice that the requested relationship fields do not appear in +the query results. This is because the SOAP and REST APIs do not return any +related object information if it does not exist on the record and there is no +reliable way to extract and rebuild the empty columns based on the query string. +In the example below, if there were Account information an additional column +titled `"Account.Name"` would appear in the results. + +```{r} +# child-to-parent relationship (e.g. Account.Name from Contact record) +sf_query( + "SELECT Id, FirstName, Account.Name + FROM Contact + WHERE Account.Id = null" +) +``` + +Note, that the Bulk 1.0 and Bulk 2.0 APIs will return `"Account.Name"` as a +column of all `NA` values for this query because they return results +differently. + +Finally, one aspect to note is that the Bulk 2.0 API does not support +child-to-parent-grandparent relationships as seen in the example below: + +```{r} +try( + sf_query("SELECT Id, FirstName, Account.Owner.Id + FROM Contact", + api_type = "Bulk 2.0") +) +``` + +### parent-to-child "nested" queries + +Instead of "looking up" a related field, users can write queries that retrieve the +individual records related to a parent. For example, if you would like all of the +Accounts and their Contacts you can write the query like so: + +```{r} +sf_query( + "SELECT Id, Name, + (SELECT Id, FirstName FROM Contacts) + FROM Account" +) +``` + +At first glance this query may appear the same as a lookup query on the Contact object +that includes the account id and name. However, the small difference is that every +Account is included, regardless of whether or not they have a Contact. This can be +helpful when you want to ensure a query contains all of the parent records and their +child records, if they exist. Also, note that the plural object name is used inside +the nested query ("Contacts" instead of "Contact"). + +Finally, a parent-to-child nested query can also contain a child-to-parent lookup +relationship within it. Below is an example where the Owner Id on the Contact is +included so you can know who is responsible for the Contacts under each Account. + +```{r} +sf_query( + "SELECT Name, Owner.Id, + (SELECT Id, FirstName, Owner.Id FROM Contacts) + FROM Account" +) +``` + +## Troubleshooting + +If you are having an issue with a query please submit in the {salesforcer} GitHub +repository at: https://github.com/StevenMMortimer/salesforcer/issues. As a maintainer, queries are tough to debug because every Salesforce +Org is unique. Custom objects or relationships created in your Salesforce Org may +be different or even impossible to test in another Org. When filing your issue please +make an attempt to understand the query and debug a little bit on your own. Here +are a few suggestions: + + 1. Slightly modify your function call to `sf_query()` to observe the results. Here + are a few prompting questions that may assist you: + + - What do you see when you set `verbose=TRUE` argument? + + - What happens if you change the `control` argument, specifically the batch size? + + - What happens if you try using a different API (e.g. "SOAP" vs "REST" or "Bulk 1.0" vs "Bulk 2.0")? + + - What happens if you change your query slightly? + + - Do you need a parent-to-child nested relationship query or will a child-to-parent lookup suffice? + + 2. Check out Salesforce's Workbench tool to see how it constructs specific + queries that you are debugging. The tool is available at + `https://workbench.developerforce.com` and requires a Salesforce login + (the same credentials as you normally would use). + + 3. Double check Salesforce's SOQL reference guide to see whether your query is supported or limited in some way. + + 4. Review query unit tests at: https://github.com/StevenMMortimer/salesforcer/blob/main/tests/testthat/test-query.R. + These unit tests were written to cover a variety of use cases and to track any + changes made between newly released versions of the Salesforce API (typically + 4 each year). These tests are an excellent source of examples that may be + helpful in troubleshooting your own query. + + 5. Roll up your sleeves and dive into the source code for the {salesforcer} + package. The main scripts to review are: + + - https://github.com/StevenMMortimer/salesforcer/blob/main/R/query.R + + - https://github.com/StevenMMortimer/salesforcer/blob/main/R/utils-query.R diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/supported-queries.html b/revdep/library.noindex/salesforcer/old/salesforcer/doc/supported-queries.html new file mode 100644 index 00000000..25a78b89 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/supported-queries.html @@ -0,0 +1,722 @@ + + + + + + + + + + + + + + + + +Supported Queries + + + + + + + + + + + + + + + + + + + + + + + + + +

Supported Queries

+

Steven M. Mortimer

+

2020-07-11

+ + + + +
+

Overview

+

The following vignette outlines the different types of queries that have been documented and tested. These are the “supported” query types that the {salesforcer} package currently handles. If you run into an issue, please submit the issue HERE in the GitHub repository so that we can fix or add your query type to this list. Thank you!

+

Note: Salesforce’s proprietary form of SQL called SOQL (Salesforce Object Query Language) is a powerful tool that allows you to return the fields of records in almost any object in Salesforce. This includes standard objects like Accounts, Contacts, and Tasks along with any custom objects and custom fields created in your Org. You are encouraged to use Bulk APIs when:

+
    +
  • You anticipate returning 10,000 records or more
  • +
  • Your query does not involve a parent-to-child nested relationship query
  • +
  • You would like to reduce the overall number of API calls to your Org
  • +
+

If you are not familiar with SOQL, then please consider reading the following resources:

+ +
+
+
+

Authentication

+

First, load the {salesforcer} package and login. There are two ways to authenticate: 1) OAuth 2.0 (SSO) and 2) Basic Username-Password. It is recommended to use OAuth 2.0 so that passwords do not have to be embedded in scripts or environment variables. By default, OAuth 2.0 stores the user’s credentials in a locally cached file entitled “.httr-oauth-salesforcer” in the current working directory and will be refreshed automatically when the session expires.

+
library(dplyr, warn.conflicts = FALSE)
+library(salesforcer)
+sf_auth()
+
+
+

Default query behavior

+

The default API for the sf_query() function is the REST API because it is both fast and flexible. Every effort has been made so that the format of the results from the REST and SOAP APIs is exactly the same. The only difference will be speed. The REST API uses JSON, which can generally be processed more quickly than XML used in the SOAP API.

+
soql <- "SELECT Id,
+                FirstName, 
+                LastName
+         FROM Contact
+         LIMIT 10"
+
+queried_records <- sf_query(soql) # REST API is the default api_type
+queried_records
+#> # A tibble: 10 × 3
+#>   Id                 FirstName LastName
+#>   <chr>              <chr>     <chr>   
+#> 1 0033s000014B3IZAA0 Rick      James   
+#> 2 0033s000014B3IaAAK Rick      James   
+#> 3 0033s000014B3IbAAK Rick      James   
+#> 4 0033s000012Nd6FAAS Jenny     Williams
+#> 5 0033s000012NdARAA0 Jenny     Williams
+#> # … with 5 more rows
+
+queried_records <- sf_query(soql, api_type = "SOAP")
+queried_records
+#> # A tibble: 10 × 3
+#>   Id                 FirstName LastName
+#>   <chr>              <chr>     <chr>   
+#> 1 0033s000014B3IZAA0 Rick      James   
+#> 2 0033s000014B3IaAAK Rick      James   
+#> 3 0033s000014B3IbAAK Rick      James   
+#> 4 0033s000012Nd6FAAS Jenny     Williams
+#> 5 0033s000012NdARAA0 Jenny     Williams
+#> # … with 5 more rows
+
+
+

REST vs. SOAP API query performance test

+

Below is a small example to roughly demonstrate the magnitude of the performance difference between the REST and SOAP APIs when querying 1,000 records.

+

Setup performance test

+
# create a new account 
+# (if replicating, you may or may not have an external id field in your Org)
+prefix <- paste0("APerfTest-", as.integer(runif(1,1,99999)))
+new_account <- sf_create(
+  tibble(
+    Name = "Test Account For Performance Test", 
+    My_External_Id__c = prefix,
+    Description = paste0("This is a test account with 1,000 records for ", 
+                         "testing the performance differences between the ", 
+                         "SOAP and REST APIs.")
+  ), 
+  object_name = "Account"
+)
+
+# create and associate a thousand new contacts with that account
+# (again, you may or may not have an external id field in your Org)
+n <- 1000
+prefix <- paste0("CPerfTest-", as.integer(runif(1,1,99999)), "-")
+new_contacts <- tibble(FirstName = rep("Test", n),
+                       LastName = paste0("Query-Vignette", 1:n), 
+                       test_number__c = 999.9,
+                       AccountId = rep(new_account$id, n),
+                       My_External_Id__c=paste0(prefix, 1:n))
+new_contacts_res <- sf_create(new_contacts, "Contact", api_type = "Bulk 2.0")
+

Performance test

+
qry <- function(api_type){
+  sf_query(
+    sprintf("SELECT Id, Name, Owner.Id, 
+               (SELECT Id, LastName, Owner.Id FROM Contacts) 
+            FROM Account
+            WHERE Id = '%s'", 
+            new_account$id), 
+    api_type = api_type
+  )
+}
+res <- microbenchmark::microbenchmark(
+  qry("REST"),
+  qry("SOAP"),
+  times = 5, 
+  unit = "s"
+)
+res
+#> Unit: seconds
+#>         expr       min        lq      mean   median        uq       max neval
+#>  qry("REST") 0.4483274 0.4602706 0.4873329 0.468575 0.4776343 0.5818573     5
+#>  qry("SOAP") 1.7547971 1.7608775 1.8419213 1.854589 1.8599604 1.9793821     5
+
+suppressWarnings(suppressMessages(
+  ggplot2::autoplot(res) + 
+    ggplot2::scale_y_continuous(name="Time [seconds]", n.breaks=6)
+))
+

+

As seen in the limited test above, the REST API can be anywhere from 4-6x faster than the SOAP API for a query on 1,000 contact records associated with a single Account. Breaking up the number of records returned into smaller batches by setting QueryOptions = list(batchSize = 200) typically does not affect this result very much but it also depends on the number of fields in the query. For the REST API the default is 2,000 records per batch with a minimum of 200 and maximum of 2,000. For the SOAP API the default is 500 records per batch. For both APIs it is important to note that there is no guarantee that the requested batch size is the actual batch size. Changes are made as necessary to maximize performance. For example, the SOAP API states “batch size will be no more than 200 if the SOQL statement selects two or more custom fields of type long text”. The REST API mentions that the limit imposed by Salesforce’s app servers is around 20,000 characters which can cause batches to be smaller. In short, it’s generally okay to use the default batch sizes since Salesforce may optimize over your specified batch size anyways.

+
+
+

When to use the Bulk APIs for queries

+

A general rule of thumb for using the Bulk APIs (Bulk 1.0 and Bulk 2.0) for queries is anytime you need to retrieve more than 10,000 records. The main reasons to not use the Bulk APIs are twofold. First, they do not support complex relationship queries or aggregate queries. If you need to write a nested relationship or aggregate query involving a large number of records you may be tempted to use the REST API. However, it is recommended to perform two or more separate bulk queries that retrieve the records you need and then join or aggregate the results in R.

+
# nested relationship query 
+# (supposed to return the id and first name of all contacts on each account)
+try(
+  sf_query(
+    "SELECT Id, Name, 
+      (SELECT Id, FirstName FROM Contacts)
+    FROM Account",
+    api_type = "Bulk 2.0"
+  )
+)
+#> Request failed [400]. Retrying in 1.9 seconds...
+#> Request failed [400]. Retrying in 3.4 seconds...
+#> Error : API_ERROR: Aggregate Relationships not supported in Bulk V2 Query with CSV content type
+
+# aggregate query
+# (supposed to return the count of contacts per account)
+try(
+  sf_query(
+    "SELECT Account.Id, Count(Name) contacts_n
+    FROM Contact
+    GROUP BY Account.Id",  
+    api_type = "Bulk 2.0"
+  )
+)
+#> Request failed [400]. Retrying in 1 seconds...
+#> Request failed [400]. Retrying in 2.2 seconds...
+#> Error : API_ERROR: Aggregate Relationships not supported in Bulk Query
+

The two queries above were trying to pull all the contacts for each account and then get a count of how many contacts there are per account. If you have a lot of records, using the REST API to return these results may not be feasible. Even though the Bulk APIs cannot handle the same query, they can pull down massive amounts of data quickly. In this case you can pull down all of the Contact records and all of the Account records and then perform the calculation using dplyr, like so:

+
contacts <- sf_query("SELECT Id, FirstName, Account.Id
+                     FROM Contact", 
+                     api_type = "Bulk 2.0")
+
+accounts <- sf_query("SELECT Id, Name 
+                     FROM Account", 
+                     api_type = "Bulk 2.0")
+
+nested_query_recs <- accounts %>% 
+  left_join(contacts %>% 
+              rename(`Contact.Id` = Id, 
+                     `Contact.FirstName` = FirstName), 
+            by = c("Id" = "Account.Id"))
+nested_query_recs
+#> # A tibble: 419 × 4
+#>   Id                 Name                            Contact.Id Contact.FirstNa…
+#>   <chr>              <chr>                           <chr>      <chr>           
+#> 1 0013s00000zFdugAAC KEEP Test Account With Child R… 0033s0000… KEEP            
+#> 2 0013s00000zFdugAAC KEEP Test Account With Child R… 0033s0000… KEEP            
+#> 3 0013s00000zFdugAAC KEEP Test Account With Child R… 0033s0000… KEEP            
+#> 4 0013s00000zFdugAAC KEEP Test Account With Child R… 0033s0000… KEEP            
+#> 5 0013s00000zFdugAAC KEEP Test Account With Child R… 0033s0000… KEEP            
+#> # … with 414 more rows
+
+aggregate_query_recs <- nested_query_recs %>% 
+  group_by(Id) %>%
+  summarize(.groups = 'drop', 
+            contacts_n = sum(!is.na(Contact.Id)))
+aggregate_query_recs
+#> # A tibble: 16 × 2
+#>   Id                 contacts_n
+#>   <chr>                   <int>
+#> 1 0013s00000zFdugAAC        300
+#> 2 0013s00000zFgA6AAK          0
+#> 3 0013s000014jF2HAAU          0
+#> 4 0013s000014jF2vAAE          0
+#> 5 0013s000014jFj6AAE          0
+#> # … with 11 more rows
+

The second reason to not use the Bulk APIs is that there is a performance overhead associated with every bulk (asynchronous) job that involves checking the status of the job until it succeeds or fails before retrieving the results.

+

The example below is provided so that you can take this code as an example to run your own performance test of queries that return 10K, 100K, 1M+ records to see where the Bulk APIs outperform the REST API.

+
qry_compare <- function(api_type){
+  soql <- sprintf("SELECT Id, LastName, Account.Id, Account.Name, Owner.Id
+                   FROM Contact
+                   WHERE Account.Id = '%s'", 
+                   new_account$id)
+  sf_query(soql, api_type = api_type)
+}
+
+res <- microbenchmark::microbenchmark(
+  qry_compare("REST"),
+  qry_compare("Bulk 1.0"),
+  qry_compare("Bulk 2.0"),
+  times = 5, 
+  unit = "s"
+)
+

Note that the Bulk 1.0 API requires users to specify the target object along with their submitted SOQL. This is because it is needed when creating the bulk job that will manage and execute the query.

+
queried_records <- sf_query(soql, api_type = "Bulk 1.0")
+#> Guessed 'Contact' as the object_name from supplied SOQL.
+#> Please set `object_name` explicitly if this is incorrect because it is required by the Bulk APIs.
+

As you can see above the {salesforcer} package will try to infer the object in the query if not explicitly provided. If it does not guess correctly, then please specify.

+

Cleanup after performance tests

+

By keeping track of the account ids used in our tests, it is fairly easy to find and delete these test records from our Org to save space.

+
# cleanup performance test Contact records ...
+contacts_to_delete <- sf_query(
+  sprintf("SELECT Id 
+          FROM Contact 
+          WHERE Account.Id = '%s'",
+          new_account$id)
+)
+sf_delete(contacts_to_delete$Id, "Contact", api_type="Bulk 2.0")
+#> # A tibble: 99 × 4
+#>   Id                 sf__Id             sf__Created sf__Error
+#>   <chr>              <chr>              <lgl>       <lgl>    
+#> 1 0033s00001BXfB6AAL 0033s00001BXfB6AAL FALSE       NA       
+#> 2 0033s00001BXfB7AAL 0033s00001BXfB7AAL FALSE       NA       
+#> 3 0033s00001BXfB8AAL 0033s00001BXfB8AAL FALSE       NA       
+#> 4 0033s00001BXfB9AAL 0033s00001BXfB9AAL FALSE       NA       
+#> 5 0033s00001BXfBAAA1 0033s00001BXfBAAA1 FALSE       NA       
+#> # … with 94 more rows
+
+# ... and finally delete the account
+sf_delete(new_account$id)
+#> # A tibble: 1 × 2
+#>   id                 success
+#>   <chr>              <lgl>  
+#> 1 0013s000019JU7NAAW TRUE
+
+
+

Relationship queries

+

Salesforce supports retrieving fields from related objects when querying another object. This is similar to performing a JOIN in SQL, but without having to specify the join keys because Salesforce already knows the relationship between the two objects. There are two types of relationship queries (1. child-to-parent lookups and 2. parent-to-child nested queries) detailed in the sections below.

+
+

child-to-parent “lookup” queries

+

The first type of relationship query and the most common is child to parent. For example, the Contact object (child) to their parent, the Account object. In order to pull down parent object fields with your child record query, you just need to prefix any fields from the related object by concatenating the name of the object with the field name separated by a period. In the example below we are retrieving all Contact object records that have a relationship to an Account.

+
# child-to-parent relationship (e.g. Account.Name from Contact record)
+sf_query(
+  "SELECT Id, FirstName, Account.Name
+  FROM Contact
+  WHERE Account.Id != null"
+)
+#> # A tibble: 315 × 3
+#>   Id                 FirstName Account.Name                        
+#>   <chr>              <chr>     <chr>                               
+#> 1 0033s000012NkzwAAC KEEP      KEEP Test Account With Child Records
+#> 2 0033s000012NkzxAAC KEEP      KEEP Test Account With Child Records
+#> 3 0033s000012NkzyAAC KEEP      KEEP Test Account With Child Records
+#> 4 0033s000012NkzzAAC KEEP      KEEP Test Account With Child Records
+#> 5 0033s000012Nl00AAC KEEP      KEEP Test Account With Child Records
+#> # … with 310 more rows
+

Sometimes you may notice that the requested relationship fields do not appear in the query results. This is because the SOAP and REST APIs do not return any related object information if it does not exist on the record and there is no reliable way to extract and rebuild the empty columns based on the query string. In the example below, if there were Account information an additional column titled "Account.Name" would appear in the results.

+
# child-to-parent relationship (e.g. Account.Name from Contact record)
+sf_query(
+  "SELECT Id, FirstName, Account.Name
+  FROM Contact
+  WHERE Account.Id = null"
+)
+#> # A tibble: 270 × 2
+#>   Id                 FirstName
+#>   <chr>              <chr>    
+#> 1 0033s000014B3IZAA0 Rick     
+#> 2 0033s000014B3IaAAK Rick     
+#> 3 0033s000014B3IbAAK Rick     
+#> 4 0033s000012Nd6FAAS Jenny    
+#> 5 0033s000012NdARAA0 Jenny    
+#> # … with 265 more rows
+

Note, that the Bulk 1.0 and Bulk 2.0 APIs will return "Account.Name" as a column of all NA values for this query because they return results differently.

+

Finally, one aspect to note is that the Bulk 2.0 API does not support child-to-parent-grandparent relationships as seen in the example below:

+
try(
+  sf_query("SELECT Id, FirstName, Account.Owner.Id
+            FROM Contact", 
+           api_type = "Bulk 2.0")
+)
+#> # A tibble: 585 × 3
+#>   Id                 FirstName Account.Owner.Id
+#>   <chr>              <chr>     <chr>           
+#> 1 0033s000012Nd60AAC Jenny     <NA>            
+#> 2 0033s000012Nd65AAC Jenny     <NA>            
+#> 3 0033s000012Nd6FAAS Jenny     <NA>            
+#> 4 0033s000012Nd6UAAS Jenny     <NA>            
+#> 5 0033s000012NdARAA0 Jenny     <NA>            
+#> # … with 580 more rows
+
+
+

parent-to-child “nested” queries

+

Instead of “looking up” a related field, users can write queries that retrieve the individual records related to a parent. For example, if you would like all of the Accounts and their Contacts you can write the query like so:

+
sf_query(
+  "SELECT Id, Name, 
+    (SELECT Id, FirstName FROM Contacts)
+  FROM Account"
+)
+#> # A tibble: 320 × 4
+#>   Id                 Name                            Contact.FirstNa… Contact.Id
+#>   <chr>              <chr>                           <chr>            <chr>     
+#> 1 0013s00000zFgA6AAK KEEP Test Account With Child R… <NA>             <NA>      
+#> 2 0013s00000zFdugAAC KEEP Test Account With Child R… KEEP             0033s0000…
+#> 3 0013s00000zFdugAAC KEEP Test Account With Child R… KEEP             0033s0000…
+#> 4 0013s00000zFdugAAC KEEP Test Account With Child R… KEEP             0033s0000…
+#> 5 0013s00000zFdugAAC KEEP Test Account With Child R… KEEP             0033s0000…
+#> # … with 315 more rows
+

At first glance this query may appear the same as a lookup query on the Contact object that includes the account id and name. However, the small difference is that every Account is included, regardless of whether or not they have a Contact. This can be helpful when you want to ensure a query contains all of the parent records and their child records, if they exist. Also, note that the plural object name is used inside the nested query (“Contacts” instead of “Contact”).

+

Finally, a parent-to-child nested query can also contain a child-to-parent lookup relationship within it. Below is an example where the Owner Id on the Contact is included so you can know who is responsible for the Contacts under each Account.

+
sf_query(
+  "SELECT Name, Owner.Id, 
+    (SELECT Id, FirstName, Owner.Id FROM Contacts)
+   FROM Account"
+)
+#> # A tibble: 320 × 5
+#>   Name                     Contact.FirstNa… Contact.Id Contact.Owner.Id Owner.Id
+#>   <chr>                    <chr>            <chr>      <chr>            <chr>   
+#> 1 KEEP Test Account With … <NA>             <NA>       <NA>             0056A00…
+#> 2 KEEP Test Account With … KEEP             0033s0000… 0056A000000MPRj… 0056A00…
+#> 3 KEEP Test Account With … KEEP             0033s0000… 0056A000000MPRj… 0056A00…
+#> 4 KEEP Test Account With … KEEP             0033s0000… 0056A000000MPRj… 0056A00…
+#> 5 KEEP Test Account With … KEEP             0033s0000… 0056A000000MPRj… 0056A00…
+#> # … with 315 more rows
+
+
+
+

Troubleshooting

+

If you are having an issue with a query please submit in the {salesforcer} GitHub repository at: https://github.com/StevenMMortimer/salesforcer/issues. As a maintainer, queries are tough to debug because every Salesforce Org is unique. Custom objects or relationships created in your Salesforce Org may be different or even impossible to test in another Org. When filing your issue please make an attempt to understand the query and debug a little bit on your own. Here are a few suggestions:

+
    +
  1. Slightly modify your function call to sf_query() to observe the results. Here are a few prompting questions that may assist you:

    +
      +
    • What do you see when you set verbose=TRUE argument?

    • +
    • What happens if you change the control argument, specifically the batch size?

    • +
    • What happens if you try using a different API (e.g. “SOAP” vs “REST” or “Bulk 1.0” vs “Bulk 2.0”)?

    • +
    • What happens if you change your query slightly?

    • +
    • Do you need a parent-to-child nested relationship query or will a child-to-parent lookup suffice?

    • +
  2. +
  3. Check out Salesforce’s Workbench tool to see how it constructs specific queries that you are debugging. The tool is available at https://workbench.developerforce.com and requires a Salesforce login (the same credentials as you normally would use).

  4. +
  5. Double check Salesforce’s SOQL reference guide to see whether your query is supported or limited in some way.

  6. +
  7. Review query unit tests at: https://github.com/StevenMMortimer/salesforcer/blob/main/tests/testthat/test-query.R. These unit tests were written to cover a variety of use cases and to track any changes made between newly released versions of the Salesforce API (typically 4 each year). These tests are an excellent source of examples that may be helpful in troubleshooting your own query.

  8. +
  9. Roll up your sleeves and dive into the source code for the {salesforcer} package. The main scripts to review are:

    +
  10. +
+
+ + + + + + + + + + + diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/transitioning-from-RForcecom.R b/revdep/library.noindex/salesforcer/old/salesforcer/doc/transitioning-from-RForcecom.R new file mode 100644 index 00000000..15fc81c3 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/transitioning-from-RForcecom.R @@ -0,0 +1,73 @@ +## ---- echo = FALSE------------------------------------------------------------ +NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true") +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + purl = NOT_CRAN, + eval = NOT_CRAN +) +options(tibble.print_min = 5L, tibble.print_max = 5L) + +## ----auth-background, include = FALSE----------------------------------------- +suppressWarnings(suppressMessages(library(dplyr))) +suppressWarnings(suppressMessages(library(here))) +library(salesforcer) +token_path <- Sys.getenv("SALESFORCER_TOKEN_PATH") +sf_auth(token = paste0(token_path, "salesforcer_token.rds")) + +## ----load-package, eval=FALSE------------------------------------------------- +# library(salesforcer) +# sf_auth() + +## ---- warning=FALSE, eval=FALSE----------------------------------------------- +# +# # Beginning February 1, 2022, basic authentication will no longer work. You must +# # log in to Salesforce using MFA (generating an OAuth 2.0 token typically from +# # the browser). +# +# # the RForcecom way +# # RForcecom::rforcecom.login(username, paste0(password, security_token), +# # apiVersion=getOption("salesforcer.api_version")) +# # replicated in salesforcer package +# session <- salesforcer::rforcecom.login(username, +# paste0(password, security_token), +# apiVersion = getOption("salesforcer.api_version")) +# session['sessionID'] <- "{MASKED}" +# session + +## ---- warning=FALSE----------------------------------------------------------- +n <- 2 +new_contacts <- tibble(FirstName = rep("Test", n), + LastName = paste0("Contact-Create-", 1:n)) + +# the RForcecom way (requires a loop) +# rforcecom_results <- NULL +# for(i in 1:nrow(new_contacts)){ +# temp <- RForcecom::rforcecom.create(session, +# objectName = "Contact", +# fields = unlist(slice(new_contacts,i))) +# rforcecom_results <- bind_rows(rforcecom_results, temp) +# } + +# the better way in salesforcer to do multiple records +salesforcer_results <- sf_create(new_contacts, object_name="Contact") +salesforcer_results + +## ---- warning=FALSE----------------------------------------------------------- +this_soql <- "SELECT Id, Email FROM Contact LIMIT 5" + +# the RForcecom way +# RForcecom::rforcecom.query(session, soqlQuery = this_soql) + +# the better way in salesforcer to query +salesforcer_results <- sf_query(this_soql) +salesforcer_results + +## ---- warning=FALSE----------------------------------------------------------- +# the RForcecom way +# RForcecom::rforcecom.getObjectDescription(session, objectName='Account') + +# the better way in salesforcer to get object fields +result2 <- salesforcer::sf_describe_object_fields('Account') +result2 + diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/transitioning-from-RForcecom.Rmd b/revdep/library.noindex/salesforcer/old/salesforcer/doc/transitioning-from-RForcecom.Rmd new file mode 100644 index 00000000..1cd0f249 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/transitioning-from-RForcecom.Rmd @@ -0,0 +1,157 @@ +--- +title: "Transitioning from RForcecom" +author: "Steven M. Mortimer" +date: "2021-07-03" +output: + rmarkdown::html_vignette: + toc: true + toc_depth: 4 + keep_md: true +vignette: > + %\VignetteIndexEntry{Transitioning from RForcecom} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, echo = FALSE} +NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true") +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + purl = NOT_CRAN, + eval = NOT_CRAN +) +options(tibble.print_min = 5L, tibble.print_max = 5L) +``` + +While writing the {salesforcer} package we were keenly aware that many folks +were already using the {RForcecom} package to connect to Salesforce. In order +to foster adoption and switching between the packages {salesforcer} replicates +the functionality of many {RForcecom} functions so that you will only need to swap +out `library(RForcecom)` for `library(salesforcer)` and still have +production scripts perform as expected. + +## RForcecom Removed from CRAN + +As of June 9, 2021, the {RForcecom} package was removed from CRAN. You can still +use it by installing from the archive, but we strongly recommend using +{salesforcer} instead. The existing functionality in {RForcecom} has been further +optimized within {salesforcer} and new functionality has been added too. + +## Salesforce Requires MFA Which Prevents RForcecom Basic Auth Log in + +Basic authentication (password and security token) will no longer work since +Salesforce announced that all customers will be migrated to MFA beginning +February 1st, 2022 +([link](https://admin.salesforce.com/blog/2021/everything-admins-need-to-know-about-the-mfa-requirement)). +As a result, the basic authentication routine used {RForcecom} and the legacy, +compatibility method written into {salesforcer} will no longer work. Please migrate +to {salesforcer} and use `sf_auth()` to generate an OAuth 2.0 token. The examples +below will no longer work. + +## Authentication + +{salesforcer} supports OAuth 2.0 authentication which is preferred, but for +backward compatibility provides the username-password authentication routine +implemented by {RForcecom}. Here is an example running the function from +each of the packages side-by-side and producing the same result. + +First, authenticate and load any required packages for your analysis. + +```{r auth-background, include = FALSE} +suppressWarnings(suppressMessages(library(dplyr))) +suppressWarnings(suppressMessages(library(here))) +library(salesforcer) +token_path <- Sys.getenv("SALESFORCER_TOKEN_PATH") +sf_auth(token = paste0(token_path, "salesforcer_token.rds")) +``` + +```{r load-package, eval=FALSE} +library(salesforcer) +sf_auth() +``` + +```{r, warning=FALSE, eval=FALSE} + +# Beginning February 1, 2022, basic authentication will no longer work. You must +# log in to Salesforce using MFA (generating an OAuth 2.0 token typically from +# the browser). + +# the RForcecom way +# RForcecom::rforcecom.login(username, paste0(password, security_token), +# apiVersion=getOption("salesforcer.api_version")) +# replicated in salesforcer package +session <- salesforcer::rforcecom.login(username, + paste0(password, security_token), + apiVersion = getOption("salesforcer.api_version")) +session['sessionID'] <- "{MASKED}" +session +``` + +Note that we must set the API version here because calls to session will not +create a new `sessionId` and then we are stuck with version 35.0 (the default from +`RForcecom::rforcecom.login()`). Some functions in {salesforcer} implement API +calls that are only available after version 35.0. + +## CRUD Operations + +"CRUD" operations (Create, Retrieve, Update, Delete) in the {RForcecom} package +only operate on one record at a time. One benefit to using the {salesforcer} +package is that these operations will accept a named vector (one record) or an +entire `data.frame` or `tbl_df` of records to churn through. However, rest +assured that the replicated functions behave exactly the same way if you are +hesitant to making the switch. + +Here is an example showing the reduction in code of using {salesforcer} if you +would like to create multiple records. + +```{r, warning=FALSE} +n <- 2 +new_contacts <- tibble(FirstName = rep("Test", n), + LastName = paste0("Contact-Create-", 1:n)) + +# the RForcecom way (requires a loop) +# rforcecom_results <- NULL +# for(i in 1:nrow(new_contacts)){ +# temp <- RForcecom::rforcecom.create(session, +# objectName = "Contact", +# fields = unlist(slice(new_contacts,i))) +# rforcecom_results <- bind_rows(rforcecom_results, temp) +# } + +# the better way in salesforcer to do multiple records +salesforcer_results <- sf_create(new_contacts, object_name="Contact") +salesforcer_results +``` + +## Query + +{salesforcer} also has better printing and type-casting when returning query +result thanks to features of the {readr} package. + +```{r, warning=FALSE} +this_soql <- "SELECT Id, Email FROM Contact LIMIT 5" + +# the RForcecom way +# RForcecom::rforcecom.query(session, soqlQuery = this_soql) + +# the better way in salesforcer to query +salesforcer_results <- sf_query(this_soql) +salesforcer_results +``` + +## Describe + +The {RForcecom} package has the function `rforcecom.getObjectDescription()` +which returns a `data.frame` with one row per field on an object. The same +function in {salesforcer} is named `sf_describe_object_fields()` and also has +better printing and datatype casting by using tibbles. + +```{r, warning=FALSE} +# the RForcecom way +# RForcecom::rforcecom.getObjectDescription(session, objectName='Account') + +# the better way in salesforcer to get object fields +result2 <- salesforcer::sf_describe_object_fields('Account') +result2 +``` diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/transitioning-from-RForcecom.html b/revdep/library.noindex/salesforcer/old/salesforcer/doc/transitioning-from-RForcecom.html new file mode 100644 index 00000000..0a643f4c --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/transitioning-from-RForcecom.html @@ -0,0 +1,469 @@ + + + + + + + + + + + + + + + + +Transitioning from RForcecom + + + + + + + + + + + + + + + + + + + + + + + + + +

Transitioning from RForcecom

+

Steven M. Mortimer

+

2021-07-03

+ + + + +

While writing the {salesforcer} package we were keenly aware that many folks were already using the {RForcecom} package to connect to Salesforce. In order to foster adoption and switching between the packages {salesforcer} replicates the functionality of many {RForcecom} functions so that you will only need to swap out library(RForcecom) for library(salesforcer) and still have production scripts perform as expected.

+
+

RForcecom Removed from CRAN

+

As of June 9, 2021, the {RForcecom} package was removed from CRAN. You can still use it by installing from the archive, but we strongly recommend using {salesforcer} instead. The existing functionality in {RForcecom} has been further optimized within {salesforcer} and new functionality has been added too.

+
+
+

Salesforce Requires MFA Which Prevents RForcecom Basic Auth Log in

+

Basic authentication (password and security token) will no longer work since Salesforce announced that all customers will be migrated to MFA beginning February 1st, 2022 (link). As a result, the basic authentication routine used {RForcecom} and the legacy, compatibility method written into {salesforcer} will no longer work. Please migrate to {salesforcer} and use sf_auth() to generate an OAuth 2.0 token. The examples below will no longer work.

+
+
+

Authentication

+

{salesforcer} supports OAuth 2.0 authentication which is preferred, but for backward compatibility provides the username-password authentication routine implemented by {RForcecom}. Here is an example running the function from each of the packages side-by-side and producing the same result.

+

First, authenticate and load any required packages for your analysis.

+
library(salesforcer)
+sf_auth()
+

+# Beginning February 1, 2022, basic authentication will no longer work. You must
+# log in to Salesforce using MFA (generating an OAuth 2.0 token typically from 
+# the browser).
+
+# the RForcecom way
+# RForcecom::rforcecom.login(username, paste0(password, security_token), 
+#                            apiVersion=getOption("salesforcer.api_version"))
+# replicated in salesforcer package
+session <- salesforcer::rforcecom.login(username, 
+                                         paste0(password, security_token), 
+                                         apiVersion = getOption("salesforcer.api_version"))
+session['sessionID'] <- "{MASKED}"
+session
+

Note that we must set the API version here because calls to session will not create a new sessionId and then we are stuck with version 35.0 (the default from RForcecom::rforcecom.login()). Some functions in {salesforcer} implement API calls that are only available after version 35.0.

+
+
+

CRUD Operations

+

“CRUD” operations (Create, Retrieve, Update, Delete) in the {RForcecom} package only operate on one record at a time. One benefit to using the {salesforcer} package is that these operations will accept a named vector (one record) or an entire data.frame or tbl_df of records to churn through. However, rest assured that the replicated functions behave exactly the same way if you are hesitant to making the switch.

+

Here is an example showing the reduction in code of using {salesforcer} if you would like to create multiple records.

+
n <- 2
+new_contacts <- tibble(FirstName = rep("Test", n),
+                       LastName = paste0("Contact-Create-", 1:n))
+
+# the RForcecom way (requires a loop)
+# rforcecom_results <- NULL
+# for(i in 1:nrow(new_contacts)){
+#   temp <- RForcecom::rforcecom.create(session, 
+#                                       objectName = "Contact", 
+#                                       fields = unlist(slice(new_contacts,i)))
+#   rforcecom_results <- bind_rows(rforcecom_results, temp)
+# }
+
+# the better way in salesforcer to do multiple records
+salesforcer_results <- sf_create(new_contacts, object_name="Contact")
+salesforcer_results
+#> # A tibble: 2 × 2
+#>   id                 success
+#>   <chr>              <lgl>  
+#> 1 0033s00001BXfGcAAL TRUE   
+#> 2 0033s00001BXfGdAAL TRUE
+
+
+

Query

+

{salesforcer} also has better printing and type-casting when returning query result thanks to features of the {readr} package.

+
this_soql <- "SELECT Id, Email FROM Contact LIMIT 5"
+
+# the RForcecom way
+# RForcecom::rforcecom.query(session, soqlQuery = this_soql)
+
+# the better way in salesforcer to query
+salesforcer_results <- sf_query(this_soql)
+salesforcer_results
+#> # A tibble: 5 × 2
+#>   Id                 Email               
+#>   <chr>              <chr>               
+#> 1 0033s000014B3IZAA0 rick.james@gmail.com
+#> 2 0033s000014B3IaAAK rick.james@gmail.com
+#> 3 0033s000014B3IbAAK rick.james@gmail.com
+#> 4 0033s000012Nd6FAAS jennyw@gmail.com    
+#> 5 0033s000012NdARAA0 jennyw@gmail.com
+
+
+

Describe

+

The {RForcecom} package has the function rforcecom.getObjectDescription() which returns a data.frame with one row per field on an object. The same function in {salesforcer} is named sf_describe_object_fields() and also has better printing and datatype casting by using tibbles.

+
# the RForcecom way
+# RForcecom::rforcecom.getObjectDescription(session, objectName='Account')
+
+# the better way in salesforcer to get object fields
+result2 <- salesforcer::sf_describe_object_fields('Account')
+result2
+#> # A tibble: 68 × 39
+#>   aggregatable aiPredictionField autoNumber byteLength calculated caseSensitive
+#>   <chr>        <chr>             <chr>      <chr>      <chr>      <chr>        
+#> 1 true         false             false      18         false      false        
+#> 2 false        false             false      0          false      false        
+#> 3 true         false             false      18         false      false        
+#> 4 true         false             false      765        false      false        
+#> 5 true         false             false      765        false      false        
+#> # … with 63 more rows, and 33 more variables: compoundFieldName <chr>,
+#> #   createable <chr>, custom <chr>, defaultValue <list>,
+#> #   defaultedOnCreate <chr>, deprecatedAndHidden <chr>, digits <chr>,
+#> #   externalId <chr>, extraTypeInfo <chr>, filterable <chr>, groupable <chr>,
+#> #   idLookup <chr>, label <chr>, length <chr>, name <chr>, nameField <chr>,
+#> #   namePointing <chr>, nillable <chr>, permissionable <chr>,
+#> #   picklistValues <list>, polymorphicForeignKey <chr>, precision <chr>, …
+
+ + + + + + + + + + + diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-attachments.R b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-attachments.R new file mode 100644 index 00000000..3ab80fce --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-attachments.R @@ -0,0 +1,145 @@ +## ---- echo = FALSE------------------------------------------------------------ +NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true") +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + purl = NOT_CRAN, + eval = NOT_CRAN +) +options(tibble.print_min = 5L, tibble.print_max = 5L) + +## ----auth, include = FALSE---------------------------------------------------- +suppressWarnings(suppressMessages(library(dplyr))) +suppressWarnings(suppressMessages(library(here))) +library(salesforcer) +token_path <- Sys.getenv("SALESFORCER_TOKEN_PATH") +sf_auth(token = paste0(token_path, "salesforcer_token.rds")) + +## ----load-package, eval=FALSE------------------------------------------------- +# library(dplyr, warn.conflicts = FALSE) +# library(salesforcer) +# sf_auth() + +## ----------------------------------------------------------------------------- +# define the ParentIds where the attachments will be shown in Salesforce +parent_record_id1 <- "0016A0000035mJ4" +parent_record_id2 <- "0016A0000035mJ5" + +# provide the file paths of where the attachments exist locally on your machine +# in this case we are referencing images included within the salesforcer package, +# but any absolute or relative path locally will work +file_path1 <- system.file("extdata", "cloud.png", package="salesforcer") +file_path2 <- system.file("extdata", "logo.png", package="salesforcer") +file_path3 <- system.file("extdata", "old-logo.png", package="salesforcer") + +# create a data.frame or tbl_df out of this information +attachment_details <- tibble(Body = rep(c(file_path1, + file_path2, + file_path3), + times=2), + ParentId = rep(c(parent_record_id1, + parent_record_id2), + each=3)) + +# create the attachments! +result <- sf_create_attachment(attachment_details) +result + +## ----------------------------------------------------------------------------- +# pull down all attachments associated with a particular record +queried_attachments <- sf_query(sprintf("SELECT Id, Body, Name, ParentId + FROM Attachment + WHERE ParentId IN ('%s', '%s')", + parent_record_id1, parent_record_id2)) +queried_attachments + +## ----------------------------------------------------------------------------- +# create a new folder for each ParentId in the dataset +temp_dir <- tempdir() +for (pid in unique(queried_attachments$ParentId)){ + dir.create(file.path(temp_dir, pid), showWarnings = FALSE) # ignore if already exists +} + +# create a new columns in the queried data so that we can pass this information +# on to the function `sf_download_attachment()` that will actually perform the download +queried_attachments <- queried_attachments %>% + # Strategy 1: Unique file names (ununsed here, but shown as an example) + mutate(unique_name = paste(Id, Name, sep='___')) %>% + # Strategy 2: Separate folders per parent + mutate(Path = file.path(temp_dir, ParentId)) + +# download all of the attachments for a single ParentId record to their own folder +download_result <- mapply(sf_download_attachment, + body = queried_attachments$Body, + name = queried_attachments$Name, + path = queried_attachments$Path) +download_result + +## ----cleanup-1, include = FALSE----------------------------------------------- +sf_delete(queried_attachments$Id) + +## ----------------------------------------------------------------------------- +# upload a PDF to a particular record as an Attachment +file_path <- system.file("extdata", + "data-wrangling-cheatsheet.pdf", + package = "salesforcer") +parent_record_id <- "0036A000002C6MmQAK" # replace with your own ParentId! +attachment_details <- tibble(Body = file_path, ParentId = parent_record_id) +create_result <- sf_create_attachment(attachment_details) + +# download, zip, and re-upload the PDF +pdf_path <- sf_download_attachment(sf_id = create_result$id[1]) +zipped_path <- paste0(pdf_path, ".zip") +zip(zipped_path, pdf_path, flags = "-qq") # quiet zipping messages +attachment_details <- tibble(Id = create_result$id, Body = zipped_path) +sf_update_attachment(attachment_details) + +## ----cleanup-2---------------------------------------------------------------- +sf_delete_attachment(ids = create_result$id) +# sf_delete(ids = create_result$id) # would also work + +## ----------------------------------------------------------------------------- +# create the attachment metadata required (Name, Body, ParentId) +attachment_details <- queried_attachments %>% + mutate(Body = file.path(Path, Name)) %>% + select(Name, Body, ParentId) + +## ----------------------------------------------------------------------------- +result <- sf_create_attachment(attachment_details, api_type="Bulk 1.0") +result + +## ----cleanup-3, include = FALSE----------------------------------------------- +for (pid in unique(queried_attachments$ParentId)){ + unlink(file.path(temp_dir, pid), recursive=TRUE) # remove directories... +} +sf_delete(result$Id) #... and records in Salesforce + +## ----------------------------------------------------------------------------- +# the function supports inserting all types of blob content, just update the +# object_name argument to add the PDF as a Document instead of an Attachment +document_details <- tibble(Name = "Data Wrangling Cheatsheet - Test 1", + Description = "RStudio cheatsheet covering dplyr and tidyr.", + Body = system.file("extdata", + "data-wrangling-cheatsheet.pdf", + package="salesforcer"), + FolderId = "00l6A000001EgIwQAK", + Keywords = "test,cheatsheet,document") +result <- sf_create_attachment(document_details, object_name = "Document") +result + +## ----cleanup-4, include = FALSE----------------------------------------------- +sf_delete(result$id) + +## ----------------------------------------------------------------------------- +cheatsheet_url <- "https://rstudio.com/wp-content/uploads/2015/02/data-wrangling-cheatsheet.pdf" +document_details <- tibble(Name = "Data Wrangling Cheatsheet - Test 2", + Description = "RStudio cheatsheet covering dplyr and tidyr.", + Url = cheatsheet_url, + FolderId = "00l6A000001EgIwQAK", + Keywords = "test,cheatsheet,document") +result <- sf_create_attachment(document_details, object_name = "Document") +result + +## ----cleanup-5, include = FALSE----------------------------------------------- +sf_delete(result$id) + diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-attachments.Rmd b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-attachments.Rmd new file mode 100644 index 00000000..e44bc328 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-attachments.Rmd @@ -0,0 +1,286 @@ +--- +title: "Working with Attachments" +author: "Steven M. Mortimer" +date: "2020-08-16" +output: + rmarkdown::html_vignette: + toc: true + toc_depth: 4 + keep_md: true +vignette: > + %\VignetteIndexEntry{Working with Attachments} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, echo = FALSE} +NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true") +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + purl = NOT_CRAN, + eval = NOT_CRAN +) +options(tibble.print_min = 5L, tibble.print_max = 5L) +``` + +## Attachments in Salesforce + +Almost all records in Salesforce support attachments. Attachments are just blob data +storage for an associated ParentId. A ParentId is the 18-character Salesforcer Id +of the record that the attachment belongs to. To get started creating and updating +attachments, first, load the {salesforcer} and {dplyr} packages and login, if needed. + +```{r auth, include = FALSE} +suppressWarnings(suppressMessages(library(dplyr))) +suppressWarnings(suppressMessages(library(here))) +library(salesforcer) +token_path <- Sys.getenv("SALESFORCER_TOKEN_PATH") +sf_auth(token = paste0(token_path, "salesforcer_token.rds")) +``` + +```{r load-package, eval=FALSE} +library(dplyr, warn.conflicts = FALSE) +library(salesforcer) +sf_auth() +``` + +The Attachment data, for example, the attachment's Id, ParentId, Name, Body, ModifiedDate, +and other attributes are stored in the Attachment object, a Standard Object in Salesforce. + +## Creating (Uploading) Attachments + +Below we will cover 2 different methods of creating attachments: + +1. Uploading local files as Attachments one at a time using the SOAP and REST API (most common usage) +2. Uploading large batches of files using the Bulk API, which zips the files before upload + +**Uploading local files as Attachments (SOAP and REST)** + +When uploading an attachment stored locally (i.e. on your computer), you can provide +an absolute or relative path to the current working directory. If the `Name` column +is omitted, then the name of the attachment as it appears in Salesforce will be +the same as the base file name and extension. For example, if the path provided is +"/Documents/attachments/doc1.pdf", then the `Name` field will be set to "doc1.pdf". + +In the example below, we upload three attachments to two different parent records. +Note: Make sure to replace the paths and ParentIds in the example below with file +paths that exist on your local machine and Ids of records in your Salesforce org. + +```{r} +# define the ParentIds where the attachments will be shown in Salesforce +parent_record_id1 <- "0016A0000035mJ4" +parent_record_id2 <- "0016A0000035mJ5" + +# provide the file paths of where the attachments exist locally on your machine +# in this case we are referencing images included within the salesforcer package, +# but any absolute or relative path locally will work +file_path1 <- system.file("extdata", "cloud.png", package="salesforcer") +file_path2 <- system.file("extdata", "logo.png", package="salesforcer") +file_path3 <- system.file("extdata", "old-logo.png", package="salesforcer") + +# create a data.frame or tbl_df out of this information +attachment_details <- tibble(Body = rep(c(file_path1, + file_path2, + file_path3), + times=2), + ParentId = rep(c(parent_record_id1, + parent_record_id2), + each=3)) + +# create the attachments! +result <- sf_create_attachment(attachment_details) +result +``` + +## Downloading Attachments + +After uploading attachments to Salesforce you can download them by first querying +the metadata in the Attachment object. This metadata provides the Id for the blob +data attachment for download. A convenience function, `sf_download_attachment()`, +has been created to download attachments quickly. The example below shows how to +query the metadata of attachments belonging to particular ParentId. + +```{r} +# pull down all attachments associated with a particular record +queried_attachments <- sf_query(sprintf("SELECT Id, Body, Name, ParentId + FROM Attachment + WHERE ParentId IN ('%s', '%s')", + parent_record_id1, parent_record_id2)) +queried_attachments +``` + +Before downloading the attachments using the Body it is important to consider +whether the attachment names are repeated or duplicates. If so, then the attachments +with the same exact name will be overwritten on the local filesystem as they are +downloaded. To avoid this problem there are two common strategies: + +1. Create a new column (e.g. `unique_name`) that is the concatenation of the +Attachment Id and the Attachment's name which is guaranteed to be unique. +2. Save the attachments in separate folders for each ParentId record. + +As long as the same ParentId record doesn't name attachments with the same name, then +Strategy #2 above will work. In addition, it may help better organize the documents +if you are planning to download many and then upload again to Salesforce using the +Bulk API as demonstrated later in this script. + +```{r} +# create a new folder for each ParentId in the dataset +temp_dir <- tempdir() +for (pid in unique(queried_attachments$ParentId)){ + dir.create(file.path(temp_dir, pid), showWarnings = FALSE) # ignore if already exists +} + +# create a new columns in the queried data so that we can pass this information +# on to the function `sf_download_attachment()` that will actually perform the download +queried_attachments <- queried_attachments %>% + # Strategy 1: Unique file names (ununsed here, but shown as an example) + mutate(unique_name = paste(Id, Name, sep='___')) %>% + # Strategy 2: Separate folders per parent + mutate(Path = file.path(temp_dir, ParentId)) + +# download all of the attachments for a single ParentId record to their own folder +download_result <- mapply(sf_download_attachment, + body = queried_attachments$Body, + name = queried_attachments$Name, + path = queried_attachments$Path) +download_result +``` +```{r cleanup-1, include = FALSE} +sf_delete(queried_attachments$Id) +``` + +## Updating Attachments + +Once an Attachment record is created, you are still able to update the content +and metadata (`Name`, `IsPrivate`, and `OwnerId`) for the record. The +`sf_update_attachment()` function works just like `sf_update()` except that you +will need to include the `Body` column where the content of the attachment is +help. **NOTE**: If you just want to update the metadata and not the Attachment +content itself, you can simply use `sf_update()` to modify fields other than the +`Body` field on the record. + +The example below demonstrates how to add an attachment to a record, then +download it, zip it, re-upload to the record in order to save disk space in your +Org. + +```{r} +# upload a PDF to a particular record as an Attachment +file_path <- system.file("extdata", + "data-wrangling-cheatsheet.pdf", + package = "salesforcer") +parent_record_id <- "0036A000002C6MmQAK" # replace with your own ParentId! +attachment_details <- tibble(Body = file_path, ParentId = parent_record_id) +create_result <- sf_create_attachment(attachment_details) + +# download, zip, and re-upload the PDF +pdf_path <- sf_download_attachment(sf_id = create_result$id[1]) +zipped_path <- paste0(pdf_path, ".zip") +zip(zipped_path, pdf_path, flags = "-qq") # quiet zipping messages +attachment_details <- tibble(Id = create_result$id, Body = zipped_path) +sf_update_attachment(attachment_details) +``` + +There is a function `sf_delete_attachment()`, which simply wraps `sf_delete()` +so feel free to use for clarity in your code that you're working with attachments +use `sf_delete()`. + +```{r cleanup-2} +sf_delete_attachment(ids = create_result$id) +# sf_delete(ids = create_result$id) # would also work +``` + +**Uploading large batches of attachments using the Bulk API** + +The SOAP and REST APIs are good for working with a few attachments at a time. +However, the Bulk API can be invoked using api_type="Bulk 1.0" to automatically +take a `data.frame` or `tbl_df` of Attachment field data and create a ZIP file +with CSV manifest that is required by that API to upload. In the example above, +we downloaded the three attachments each belonging to two different parent +records. Assuming that I have run that code and the files are in that my computer +I can demonstrate that all of them can be uploaded at once using the Bulk 1.0 API. + +```{r} +# create the attachment metadata required (Name, Body, ParentId) +attachment_details <- queried_attachments %>% + mutate(Body = file.path(Path, Name)) %>% + select(Name, Body, ParentId) +``` +```{r} +result <- sf_create_attachment(attachment_details, api_type="Bulk 1.0") +result +``` +```{r cleanup-3, include = FALSE} +for (pid in unique(queried_attachments$ParentId)){ + unlink(file.path(temp_dir, pid), recursive=TRUE) # remove directories... +} +sf_delete(result$Id) #... and records in Salesforce +``` + +**NOTE**: As of v48.0 (Spring '20), it does not appear that the Bulk 2.0 API +supports working with Attachments, so the Bulk 1.0 API must be used for bulk +functionality. + +Finally, you are able to update Attachments with the Bulk API just as shown +above in the REST/SOAP API examples. + +## Extending to Documents and Other Blob Data + +The commands for working with Attachments also work for uploading documents and +other blob data as well. Documents are just like Attachments in Salesforce except +instead of having an associated ParentId they have an associated FolderId where +the blob will be associated with upon creation. Here is a brief example of uploading +a PDF ("Document") to a Folder + +```{r} +# the function supports inserting all types of blob content, just update the +# object_name argument to add the PDF as a Document instead of an Attachment +document_details <- tibble(Name = "Data Wrangling Cheatsheet - Test 1", + Description = "RStudio cheatsheet covering dplyr and tidyr.", + Body = system.file("extdata", + "data-wrangling-cheatsheet.pdf", + package="salesforcer"), + FolderId = "00l6A000001EgIwQAK", + Keywords = "test,cheatsheet,document") +result <- sf_create_attachment(document_details, object_name = "Document") +result +``` +```{r cleanup-4, include = FALSE} +sf_delete(result$id) +``` + +With Documents, users are also able to save storage by specifying a `Url` instead +of a a file path where the `Body` content is stored locally. Specifying the `Url` +field will reference the URL instead of uploading into the Salesforce org, thereby +saving space if limited in your organization. + +```{r} +cheatsheet_url <- "https://rstudio.com/wp-content/uploads/2015/02/data-wrangling-cheatsheet.pdf" +document_details <- tibble(Name = "Data Wrangling Cheatsheet - Test 2", + Description = "RStudio cheatsheet covering dplyr and tidyr.", + Url = cheatsheet_url, + FolderId = "00l6A000001EgIwQAK", + Keywords = "test,cheatsheet,document") +result <- sf_create_attachment(document_details, object_name = "Document") +result +``` +```{r cleanup-5, include = FALSE} +sf_delete(result$id) +``` + +## Reference Links + +Below is a list of links to existing Salesforce documentation that provide more +detail into how Attachments, Documents, and other blob data are handled via their +APIs. As with many functions in {salesforcer}, we have tried to translate these +functions exactly as they are described in the Salesforce documentation so that +they are flexible enough to handle most all cases that the APIs were intended to +support. + + * **Attachment Object**: https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_attachment.htm + + * **Document Object**: https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_document.htm + + * **REST API Upload Attachment**: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_sobject_insert_update_blob.htm + + * **Bulk API Upload Attachments**: https://developer.salesforce.com/docs/atlas.en-us.api_asynch.meta/api_asynch/binary_intro.htm diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-attachments.html b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-attachments.html new file mode 100644 index 00000000..363a6989 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-attachments.html @@ -0,0 +1,566 @@ + + + + + + + + + + + + + + + + +Working with Attachments + + + + + + + + + + + + + + + + + + + + + + + + + +

Working with Attachments

+

Steven M. Mortimer

+

2020-08-16

+ + + + +
+

Attachments in Salesforce

+

Almost all records in Salesforce support attachments. Attachments are just blob data storage for an associated ParentId. A ParentId is the 18-character Salesforcer Id of the record that the attachment belongs to. To get started creating and updating attachments, first, load the {salesforcer} and {dplyr} packages and login, if needed.

+
library(dplyr, warn.conflicts = FALSE)
+library(salesforcer)
+sf_auth()
+

The Attachment data, for example, the attachment’s Id, ParentId, Name, Body, ModifiedDate, and other attributes are stored in the Attachment object, a Standard Object in Salesforce.

+
+
+

Creating (Uploading) Attachments

+

Below we will cover 2 different methods of creating attachments:

+
    +
  1. Uploading local files as Attachments one at a time using the SOAP and REST API (most common usage)
  2. +
  3. Uploading large batches of files using the Bulk API, which zips the files before upload
  4. +
+

Uploading local files as Attachments (SOAP and REST)

+

When uploading an attachment stored locally (i.e. on your computer), you can provide an absolute or relative path to the current working directory. If the Name column is omitted, then the name of the attachment as it appears in Salesforce will be the same as the base file name and extension. For example, if the path provided is “/Documents/attachments/doc1.pdf”, then the Name field will be set to “doc1.pdf”.

+

In the example below, we upload three attachments to two different parent records. Note: Make sure to replace the paths and ParentIds in the example below with file paths that exist on your local machine and Ids of records in your Salesforce org.

+
# define the ParentIds where the attachments will be shown in Salesforce
+parent_record_id1 <- "0016A0000035mJ4"
+parent_record_id2 <- "0016A0000035mJ5"
+
+# provide the file paths of where the attachments exist locally on your machine
+# in this case we are referencing images included within the salesforcer package, 
+# but any absolute or relative path locally will work
+file_path1 <- system.file("extdata", "cloud.png", package="salesforcer")
+file_path2 <- system.file("extdata", "logo.png", package="salesforcer")
+file_path3 <- system.file("extdata", "old-logo.png", package="salesforcer")
+
+# create a data.frame or tbl_df out of this information
+attachment_details <- tibble(Body = rep(c(file_path1, 
+                                          file_path2, 
+                                          file_path3), 
+                                        times=2),
+                             ParentId = rep(c(parent_record_id1, 
+                                              parent_record_id2), 
+                                            each=3))
+
+# create the attachments!
+result <- sf_create_attachment(attachment_details)
+result
+#> # A tibble: 6 × 2
+#>   id                 success
+#>   <chr>              <lgl>  
+#> 1 00P3s00000gWuEqEAK TRUE   
+#> 2 00P3s00000gWuEvEAK TRUE   
+#> 3 00P3s00000gWuF0EAK TRUE   
+#> 4 00P3s00000gWuF5EAK TRUE   
+#> 5 00P3s00000gWuFAEA0 TRUE   
+#> # … with 1 more row
+
+
+

Downloading Attachments

+

After uploading attachments to Salesforce you can download them by first querying the metadata in the Attachment object. This metadata provides the Id for the blob data attachment for download. A convenience function, sf_download_attachment(), has been created to download attachments quickly. The example below shows how to query the metadata of attachments belonging to particular ParentId.

+
# pull down all attachments associated with a particular record
+queried_attachments <- sf_query(sprintf("SELECT Id, Body, Name, ParentId
+                                         FROM Attachment
+                                         WHERE ParentId IN ('%s', '%s')", 
+                                         parent_record_id1, parent_record_id2))
+queried_attachments
+#> # A tibble: 6 × 4
+#>   Id                 Body                                         Name  ParentId
+#>   <chr>              <chr>                                        <chr> <chr>   
+#> 1 00P3s00000gWuEvEAK /services/data/v54.0/sobjects/Attachment/00… logo… 0016A00…
+#> 2 00P3s00000gWuF0EAK /services/data/v54.0/sobjects/Attachment/00… old-… 0016A00…
+#> 3 00P3s00000gWuEqEAK /services/data/v54.0/sobjects/Attachment/00… clou… 0016A00…
+#> 4 00P3s00000gWuFFEA0 /services/data/v54.0/sobjects/Attachment/00… old-… 0016A00…
+#> 5 00P3s00000gWuF5EAK /services/data/v54.0/sobjects/Attachment/00… clou… 0016A00…
+#> # … with 1 more row
+

Before downloading the attachments using the Body it is important to consider whether the attachment names are repeated or duplicates. If so, then the attachments with the same exact name will be overwritten on the local filesystem as they are downloaded. To avoid this problem there are two common strategies:

+
    +
  1. Create a new column (e.g. unique_name) that is the concatenation of the Attachment Id and the Attachment’s name which is guaranteed to be unique.
  2. +
  3. Save the attachments in separate folders for each ParentId record.
  4. +
+

As long as the same ParentId record doesn’t name attachments with the same name, then Strategy #2 above will work. In addition, it may help better organize the documents if you are planning to download many and then upload again to Salesforce using the Bulk API as demonstrated later in this script.

+
# create a new folder for each ParentId in the dataset
+temp_dir <- tempdir()
+for (pid in unique(queried_attachments$ParentId)){
+  dir.create(file.path(temp_dir, pid), showWarnings = FALSE) # ignore if already exists
+}
+
+# create a new columns in the queried data so that we can pass this information 
+# on to the function `sf_download_attachment()` that will actually perform the download
+queried_attachments <- queried_attachments %>% 
+  # Strategy 1: Unique file names (ununsed here, but shown as an example)
+  mutate(unique_name = paste(Id, Name, sep='___')) %>% 
+  # Strategy 2: Separate folders per parent
+  mutate(Path = file.path(temp_dir, ParentId))
+
+# download all of the attachments for a single ParentId record to their own folder
+download_result <- mapply(sf_download_attachment, 
+                          body = queried_attachments$Body, 
+                          name = queried_attachments$Name, 
+                          path = queried_attachments$Path)
+download_result
+#>                               /services/data/v54.0/sobjects/Attachment/00P3s00000gWuEvEAK/Body 
+#>     "/var/folders/s2/1mxmzrg52tx7l0pg8lq1320w0000gn/T//RtmpFlHRfy/0016A0000035mJ4QAI/logo.png" 
+#>                               /services/data/v54.0/sobjects/Attachment/00P3s00000gWuF0EAK/Body 
+#> "/var/folders/s2/1mxmzrg52tx7l0pg8lq1320w0000gn/T//RtmpFlHRfy/0016A0000035mJ4QAI/old-logo.png" 
+#>                               /services/data/v54.0/sobjects/Attachment/00P3s00000gWuEqEAK/Body 
+#>    "/var/folders/s2/1mxmzrg52tx7l0pg8lq1320w0000gn/T//RtmpFlHRfy/0016A0000035mJ4QAI/cloud.png" 
+#>                               /services/data/v54.0/sobjects/Attachment/00P3s00000gWuFFEA0/Body 
+#> "/var/folders/s2/1mxmzrg52tx7l0pg8lq1320w0000gn/T//RtmpFlHRfy/0016A0000035mJ5QAI/old-logo.png" 
+#>                               /services/data/v54.0/sobjects/Attachment/00P3s00000gWuF5EAK/Body 
+#>    "/var/folders/s2/1mxmzrg52tx7l0pg8lq1320w0000gn/T//RtmpFlHRfy/0016A0000035mJ5QAI/cloud.png" 
+#>                               /services/data/v54.0/sobjects/Attachment/00P3s00000gWuFAEA0/Body 
+#>     "/var/folders/s2/1mxmzrg52tx7l0pg8lq1320w0000gn/T//RtmpFlHRfy/0016A0000035mJ5QAI/logo.png"
+
+
+

Updating Attachments

+

Once an Attachment record is created, you are still able to update the content and metadata (Name, IsPrivate, and OwnerId) for the record. The sf_update_attachment() function works just like sf_update() except that you will need to include the Body column where the content of the attachment is help. NOTE: If you just want to update the metadata and not the Attachment content itself, you can simply use sf_update() to modify fields other than the Body field on the record.

+

The example below demonstrates how to add an attachment to a record, then download it, zip it, re-upload to the record in order to save disk space in your Org.

+
# upload a PDF to a particular record as an Attachment
+file_path <- system.file("extdata",
+                         "data-wrangling-cheatsheet.pdf",
+                         package = "salesforcer")
+parent_record_id <- "0036A000002C6MmQAK" # replace with your own ParentId!
+attachment_details <- tibble(Body = file_path, ParentId = parent_record_id)
+create_result <- sf_create_attachment(attachment_details)
+
+# download, zip, and re-upload the PDF
+pdf_path <- sf_download_attachment(sf_id = create_result$id[1])
+zipped_path <- paste0(pdf_path, ".zip")
+zip(zipped_path, pdf_path, flags = "-qq") # quiet zipping messages
+attachment_details <- tibble(Id = create_result$id, Body = zipped_path)
+sf_update_attachment(attachment_details)
+#> # A tibble: 1 × 2
+#>   id                 success
+#>   <chr>              <lgl>  
+#> 1 00P3s00000gWuFKEA0 TRUE
+

There is a function sf_delete_attachment(), which simply wraps sf_delete() so feel free to use for clarity in your code that you’re working with attachments use sf_delete().

+
sf_delete_attachment(ids = create_result$id)
+#> # A tibble: 1 × 2
+#>   id                 success
+#>   <chr>              <lgl>  
+#> 1 00P3s00000gWuFKEA0 TRUE
+# sf_delete(ids = create_result$id) # would also work
+

Uploading large batches of attachments using the Bulk API

+

The SOAP and REST APIs are good for working with a few attachments at a time. However, the Bulk API can be invoked using api_type=“Bulk 1.0” to automatically take a data.frame or tbl_df of Attachment field data and create a ZIP file with CSV manifest that is required by that API to upload. In the example above, we downloaded the three attachments each belonging to two different parent records. Assuming that I have run that code and the files are in that my computer I can demonstrate that all of them can be uploaded at once using the Bulk 1.0 API.

+
# create the attachment metadata required (Name, Body, ParentId)
+attachment_details <- queried_attachments %>% 
+  mutate(Body = file.path(Path, Name)) %>% 
+  select(Name, Body, ParentId) 
+
result <- sf_create_attachment(attachment_details, api_type="Bulk 1.0")
+result
+#> # A tibble: 6 × 4
+#>   Id                 Success Created Error
+#>   <chr>              <lgl>   <lgl>   <lgl>
+#> 1 00P3s00000gWuFPEA0 TRUE    TRUE    NA   
+#> 2 00P3s00000gWuFQEA0 TRUE    TRUE    NA   
+#> 3 00P3s00000gWuFREA0 TRUE    TRUE    NA   
+#> 4 00P3s00000gWuFSEA0 TRUE    TRUE    NA   
+#> 5 00P3s00000gWuFTEA0 TRUE    TRUE    NA   
+#> # … with 1 more row
+

NOTE: As of v48.0 (Spring ’20), it does not appear that the Bulk 2.0 API supports working with Attachments, so the Bulk 1.0 API must be used for bulk functionality.

+

Finally, you are able to update Attachments with the Bulk API just as shown above in the REST/SOAP API examples.

+
+
+

Extending to Documents and Other Blob Data

+

The commands for working with Attachments also work for uploading documents and other blob data as well. Documents are just like Attachments in Salesforce except instead of having an associated ParentId they have an associated FolderId where the blob will be associated with upon creation. Here is a brief example of uploading a PDF (“Document”) to a Folder

+
# the function supports inserting all types of blob content, just update the 
+# object_name argument to add the PDF as a Document instead of an Attachment
+document_details <- tibble(Name = "Data Wrangling Cheatsheet - Test 1",
+                           Description = "RStudio cheatsheet covering dplyr and tidyr.",
+                           Body = system.file("extdata", 
+                                              "data-wrangling-cheatsheet.pdf",
+                                              package="salesforcer"),
+                           FolderId = "00l6A000001EgIwQAK",
+                           Keywords = "test,cheatsheet,document")
+result <- sf_create_attachment(document_details, object_name = "Document")
+result
+#> # A tibble: 1 × 2
+#>   id                 success
+#>   <chr>              <lgl>  
+#> 1 0153s000002btxkAAA TRUE
+

With Documents, users are also able to save storage by specifying a Url instead of a a file path where the Body content is stored locally. Specifying the Url field will reference the URL instead of uploading into the Salesforce org, thereby saving space if limited in your organization.

+
cheatsheet_url <- "https://rstudio.com/wp-content/uploads/2015/02/data-wrangling-cheatsheet.pdf"
+document_details <- tibble(Name = "Data Wrangling Cheatsheet - Test 2",
+                           Description = "RStudio cheatsheet covering dplyr and tidyr.",
+                           Url = cheatsheet_url,  
+                           FolderId = "00l6A000001EgIwQAK",
+                           Keywords = "test,cheatsheet,document")
+result <- sf_create_attachment(document_details, object_name = "Document")
+result
+#> # A tibble: 1 × 2
+#>   id                 success
+#>   <chr>              <lgl>  
+#> 1 0153s000002btxpAAA TRUE
+
+ + + + + + + + + + + + diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-bulk-apis.R b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-bulk-apis.R new file mode 100644 index 00000000..e9e1c307 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-bulk-apis.R @@ -0,0 +1,109 @@ +## ---- echo = FALSE------------------------------------------------------------ +NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true") +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + purl = NOT_CRAN, + eval = NOT_CRAN +) +options(tibble.print_min = 5L, tibble.print_max = 5L) + +## ----auth, include = FALSE---------------------------------------------------- +suppressWarnings(suppressMessages(library(dplyr))) +suppressWarnings(suppressMessages(library(here))) +library(salesforcer) +token_path <- Sys.getenv("SALESFORCER_TOKEN_PATH") +sf_auth(token = paste0(token_path, "salesforcer_token.rds")) + +## ----load-package, eval=FALSE------------------------------------------------- +# library(dplyr, warn.conflicts = FALSE) +# library(salesforcer) +# sf_auth() + +## ----------------------------------------------------------------------------- +n <- 4 +prefix <- paste0("Bulk-", as.integer(runif(1,1,100000)), "-") +new_contacts <- tibble(FirstName = rep("Test", n), + LastName = paste0("Contact-Create-", 1:n), + My_External_Id__c=paste0(prefix, letters[1:n])) + +## ----------------------------------------------------------------------------- +# REST +rest_created_records <- sf_create(new_contacts[1:2,], + object_name="Contact", + api_type="REST") +rest_created_records + +# Bulk +bulk_created_records <- sf_create(new_contacts[3:4,], + object_name="Contact", + api_type="Bulk 1.0") +bulk_created_records + +## ---- include=FALSE----------------------------------------------------------- +n <- 2 +prefix <- paste0("Bulk-", as.integer(runif(1,1,100000)), "-") +new_contacts <- tibble(FirstName = rep("Test", n), + LastName = paste0("Contact-Create-", 1:n), + My_External_Id__c=paste0(prefix, letters[1:n])) + +## ----------------------------------------------------------------------------- +object <- "Contact" +created_records <- sf_create(new_contacts, object_name=object, api_type="Bulk 1.0") +created_records + +# query bulk +my_soql <- sprintf("SELECT Id, + FirstName, + LastName + FROM Contact + WHERE Id in ('%s')", + paste0(created_records$Id , collapse="','")) + +queried_records <- sf_query(my_soql, object_name=object, api_type="Bulk 1.0") +queried_records + +# delete bulk +deleted_records <- sf_delete(queried_records$Id, object_name=object, api_type="Bulk 1.0") +deleted_records + +## ----------------------------------------------------------------------------- +n <- 20 +prefix <- paste0("Bulk-", as.integer(runif(1,1,100000)), "-") +new_contacts <- tibble(FirstName = rep("Test", n), + LastName = paste0("Contact-Create-", 1:n), + test_number__c = 1:n, + My_External_Id__c=paste0(prefix, letters[1:n])) + +created_records_v1 <- sf_create(new_contacts[1:10,], + object_name = "Contact", + api_type = "Bulk 1.0") +created_records_v1 + +created_records_v2 <- sf_create(new_contacts[11:20,], + object_name = "Contact", + api_type = "Bulk 2.0") +created_records_v2 + +## ---- warning=FALSE, message=FALSE-------------------------------------------- +soql <- "SELECT Id, Name FROM Contact" +bulk1_query <- function(){sf_query(soql, "Contact", api_type="Bulk 1.0")} +bulk2_query <- function(){sf_query(soql, api_type="Bulk 2.0")} # Bulk 2.0 doesn't need object name + +res <- microbenchmark::microbenchmark( + bulk1_query(), + bulk2_query(), + times=8, + unit = "s" +) +res + +suppressWarnings(suppressMessages( + ggplot2::autoplot(res) + + ggplot2::scale_y_continuous(name="Time [seconds]", n.breaks=6) +)) + +## ---- include=FALSE----------------------------------------------------------- +sf_delete(c(created_records_v1$Id, created_records_v2$sf__Id), + object_name = "Contact", api_type="Bulk 2.0") + diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-bulk-apis.Rmd b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-bulk-apis.Rmd new file mode 100644 index 00000000..ba7d2104 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-bulk-apis.Rmd @@ -0,0 +1,194 @@ +--- +title: "Working with Bulk APIs" +author: "Steven M. Mortimer" +date: "2020-07-12" +output: + rmarkdown::html_vignette: + toc: true + toc_depth: 4 + keep_md: true +vignette: > + %\VignetteIndexEntry{Working with Bulk APIs} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, echo = FALSE} +NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true") +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + purl = NOT_CRAN, + eval = NOT_CRAN +) +options(tibble.print_min = 5L, tibble.print_max = 5L) +``` + +## Using the Bulk API + +First, load the {salesforcer} and {dplyr} packages and login, if needed. + +```{r auth, include = FALSE} +suppressWarnings(suppressMessages(library(dplyr))) +suppressWarnings(suppressMessages(library(here))) +library(salesforcer) +token_path <- Sys.getenv("SALESFORCER_TOKEN_PATH") +sf_auth(token = paste0(token_path, "salesforcer_token.rds")) +``` + +```{r load-package, eval=FALSE} +library(dplyr, warn.conflicts = FALSE) +library(salesforcer) +sf_auth() +``` + +For really large inserts, updates, deletes, upserts, and queries you can just add +`api_type = "Bulk 1.0"` to most functions to get the benefits of using the Bulk API +instead of the SOAP or REST APIs. The change you have to make from using the REST +API to the Bulk 1.0 API as simple as adding `api_type="Bulk 1.0"` to your function +arguments. First, let's build a `tbl_df` with two new records to be created. + +```{r} +n <- 4 +prefix <- paste0("Bulk-", as.integer(runif(1,1,100000)), "-") +new_contacts <- tibble(FirstName = rep("Test", n), + LastName = paste0("Contact-Create-", 1:n), + My_External_Id__c=paste0(prefix, letters[1:n])) +``` + +There are some differences in the way the REST API returns response information vs. +the Bulk 1.0 API. However, the changes in Salesforce are exactly the same for these +two calls. + +```{r} +# REST +rest_created_records <- sf_create(new_contacts[1:2,], + object_name="Contact", + api_type="REST") +rest_created_records + +# Bulk +bulk_created_records <- sf_create(new_contacts[3:4,], + object_name="Contact", + api_type="Bulk 1.0") +bulk_created_records +``` + +## A Complete Bulk API Workflow + +To show a more lengthy example of using the Bulk 1.0 API, below is a workflow of +that creates 2 records, queries them, and deletes them. This is just an example. +Typically, you'd want to use the Bulk APIs over the REST or SOAP APIs when dealing +with over 10,000 records. + +```{r, include=FALSE} +n <- 2 +prefix <- paste0("Bulk-", as.integer(runif(1,1,100000)), "-") +new_contacts <- tibble(FirstName = rep("Test", n), + LastName = paste0("Contact-Create-", 1:n), + My_External_Id__c=paste0(prefix, letters[1:n])) +``` +```{r} +object <- "Contact" +created_records <- sf_create(new_contacts, object_name=object, api_type="Bulk 1.0") +created_records + +# query bulk +my_soql <- sprintf("SELECT Id, + FirstName, + LastName + FROM Contact + WHERE Id in ('%s')", + paste0(created_records$Id , collapse="','")) + +queried_records <- sf_query(my_soql, object_name=object, api_type="Bulk 1.0") +queried_records + +# delete bulk +deleted_records <- sf_delete(queried_records$Id, object_name=object, api_type="Bulk 1.0") +deleted_records +``` + +## Query Limitations + +There is one limitation to Bulk queries is that it does not support the following +operations or structures of SOQL: + + - COUNT + - ROLLUP + - SUM + - GROUP BY CUBE + - OFFSET + - Nested SOQL queries + - Relationship fields + - Compound address fields + - Compound geolocation fields + +## Using the Bulk 2.0 API + +Salesforce has more recently introduced the Bulk 2.0 API which is supposed to be +faster and have a more consistent JSON/REST based API than the Bulk 1.0 API. In +some cases I have noticed that the ordering of the result records will differ +from the order of the input data because the data is batched and processed asynchronously. +by Salesforce instead of R. However, The Bulk 2.0 API returns every single field +that was included in the call so if you have an identifying key your dataset, +then it should not be a problem to join on that key with your original data to +bring in the newly assigned Salesforce Id that is generated when the record was +created in Salesforce. However, I have find it just seems wasteful to transfer +all of the field information back after the query and have not found a significant +performance improvement between the Bulk 1.0 and Bulk 2.0. Finally, note that +the status field names ("Success", "Created", "Error") are different from the +Bulk 2.0 API. + +```{r} +n <- 20 +prefix <- paste0("Bulk-", as.integer(runif(1,1,100000)), "-") +new_contacts <- tibble(FirstName = rep("Test", n), + LastName = paste0("Contact-Create-", 1:n), + test_number__c = 1:n, + My_External_Id__c=paste0(prefix, letters[1:n])) + +created_records_v1 <- sf_create(new_contacts[1:10,], + object_name = "Contact", + api_type = "Bulk 1.0") +created_records_v1 + +created_records_v2 <- sf_create(new_contacts[11:20,], + object_name = "Contact", + api_type = "Bulk 2.0") +created_records_v2 +``` + +## Performance Benchmarks for Bulk Queries + +Below is a simple performance benchmark between the Bulk 1.0 and Bulk 2.0 +APIs for a small query. In general, the Bulk 2.0 should be faster. One potential +reason for the implementation in R to be faster is that the entire recordset is +parsed at once from a downloaded CSV of the results when using the Bulk 1.0 API. +The Bulk 2.0 retrieves the same data in large batches (typically 50,000 records +at a time). I would encourage users to experiment to see what works best in their +Salesforce Org. + +```{r, warning=FALSE, message=FALSE} +soql <- "SELECT Id, Name FROM Contact" +bulk1_query <- function(){sf_query(soql, "Contact", api_type="Bulk 1.0")} +bulk2_query <- function(){sf_query(soql, api_type="Bulk 2.0")} # Bulk 2.0 doesn't need object name + +res <- microbenchmark::microbenchmark( + bulk1_query(), + bulk2_query(), + times=8, + unit = "s" +) +res + +suppressWarnings(suppressMessages( + ggplot2::autoplot(res) + + ggplot2::scale_y_continuous(name="Time [seconds]", n.breaks=6) +)) +``` + +```{r, include=FALSE} +sf_delete(c(created_records_v1$Id, created_records_v2$sf__Id), + object_name = "Contact", api_type="Bulk 2.0") +``` diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-bulk-apis.html b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-bulk-apis.html new file mode 100644 index 00000000..7233743f --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-bulk-apis.html @@ -0,0 +1,516 @@ + + + + + + + + + + + + + + + + +Working with Bulk APIs + + + + + + + + + + + + + + + + + + + + + + + + + +

Working with Bulk APIs

+

Steven M. Mortimer

+

2020-07-12

+ + + + +
+

Using the Bulk API

+

First, load the {salesforcer} and {dplyr} packages and login, if needed.

+
library(dplyr, warn.conflicts = FALSE)
+library(salesforcer)
+sf_auth()
+

For really large inserts, updates, deletes, upserts, and queries you can just add api_type = "Bulk 1.0" to most functions to get the benefits of using the Bulk API instead of the SOAP or REST APIs. The change you have to make from using the REST API to the Bulk 1.0 API as simple as adding api_type="Bulk 1.0" to your function arguments. First, let’s build a tbl_df with two new records to be created.

+
n <- 4
+prefix <- paste0("Bulk-", as.integer(runif(1,1,100000)), "-")
+new_contacts <- tibble(FirstName = rep("Test", n),
+                       LastName = paste0("Contact-Create-", 1:n),
+                       My_External_Id__c=paste0(prefix, letters[1:n]))
+

There are some differences in the way the REST API returns response information vs.  the Bulk 1.0 API. However, the changes in Salesforce are exactly the same for these two calls.

+
# REST
+rest_created_records <- sf_create(new_contacts[1:2,], 
+                                  object_name="Contact", 
+                                  api_type="REST")
+rest_created_records
+#> # A tibble: 2 × 2
+#>   id                 success
+#>   <chr>              <lgl>  
+#> 1 0033s00001BXfH1AAL TRUE   
+#> 2 0033s00001BXfH2AAL TRUE
+
+# Bulk
+bulk_created_records <- sf_create(new_contacts[3:4,], 
+                                  object_name="Contact", 
+                                  api_type="Bulk 1.0")
+bulk_created_records
+#> # A tibble: 2 × 4
+#>   Id                 Success Created Error
+#>   <chr>              <lgl>   <lgl>   <lgl>
+#> 1 0033s00001BXfH6AAL TRUE    TRUE    NA   
+#> 2 0033s00001BXfH7AAL TRUE    TRUE    NA
+
+
+

A Complete Bulk API Workflow

+

To show a more lengthy example of using the Bulk 1.0 API, below is a workflow of that creates 2 records, queries them, and deletes them. This is just an example. Typically, you’d want to use the Bulk APIs over the REST or SOAP APIs when dealing with over 10,000 records.

+
object <- "Contact"
+created_records <- sf_create(new_contacts, object_name=object, api_type="Bulk 1.0")
+created_records
+#> # A tibble: 2 × 4
+#>   Id                 Success Created Error
+#>   <chr>              <lgl>   <lgl>   <lgl>
+#> 1 0033s00001BXfHBAA1 TRUE    TRUE    NA   
+#> 2 0033s00001BXfHCAA1 TRUE    TRUE    NA
+
+# query bulk
+my_soql <- sprintf("SELECT Id,
+                           FirstName, 
+                           LastName
+                    FROM Contact 
+                    WHERE Id in ('%s')", 
+                   paste0(created_records$Id , collapse="','"))
+
+queried_records <- sf_query(my_soql, object_name=object, api_type="Bulk 1.0")
+queried_records
+#> # A tibble: 2 × 3
+#>   Id                 FirstName LastName        
+#>   <chr>              <chr>     <chr>           
+#> 1 0033s00001BXfHBAA1 Test      Contact-Create-1
+#> 2 0033s00001BXfHCAA1 Test      Contact-Create-2
+
+# delete bulk
+deleted_records <- sf_delete(queried_records$Id, object_name=object, api_type="Bulk 1.0")
+deleted_records
+#> # A tibble: 2 × 4
+#>   Id                 Success Created Error
+#>   <chr>              <lgl>   <lgl>   <lgl>
+#> 1 0033s00001BXfHBAA1 TRUE    FALSE   NA   
+#> 2 0033s00001BXfHCAA1 TRUE    FALSE   NA
+
+
+

Query Limitations

+

There is one limitation to Bulk queries is that it does not support the following operations or structures of SOQL:

+
    +
  • COUNT
  • +
  • ROLLUP
  • +
  • SUM
  • +
  • GROUP BY CUBE
  • +
  • OFFSET
  • +
  • Nested SOQL queries
  • +
  • Relationship fields
  • +
  • Compound address fields
  • +
  • Compound geolocation fields
  • +
+
+
+

Using the Bulk 2.0 API

+

Salesforce has more recently introduced the Bulk 2.0 API which is supposed to be faster and have a more consistent JSON/REST based API than the Bulk 1.0 API. In some cases I have noticed that the ordering of the result records will differ from the order of the input data because the data is batched and processed asynchronously. by Salesforce instead of R. However, The Bulk 2.0 API returns every single field that was included in the call so if you have an identifying key your dataset, then it should not be a problem to join on that key with your original data to bring in the newly assigned Salesforce Id that is generated when the record was created in Salesforce. However, I have find it just seems wasteful to transfer all of the field information back after the query and have not found a significant performance improvement between the Bulk 1.0 and Bulk 2.0. Finally, note that the status field names (“Success”, “Created”, “Error”) are different from the Bulk 2.0 API.

+
n <- 20
+prefix <- paste0("Bulk-", as.integer(runif(1,1,100000)), "-")
+new_contacts <- tibble(FirstName = rep("Test", n),
+                       LastName = paste0("Contact-Create-", 1:n),
+                       test_number__c = 1:n,
+                       My_External_Id__c=paste0(prefix, letters[1:n]))
+
+created_records_v1 <- sf_create(new_contacts[1:10,], 
+                                object_name = "Contact", 
+                                api_type = "Bulk 1.0")
+created_records_v1
+#> # A tibble: 10 × 4
+#>   Id                 Success Created Error
+#>   <chr>              <lgl>   <lgl>   <lgl>
+#> 1 0033s00001BXefxAAD TRUE    TRUE    NA   
+#> 2 0033s00001BXefyAAD TRUE    TRUE    NA   
+#> 3 0033s00001BXefzAAD TRUE    TRUE    NA   
+#> 4 0033s00001BXeg0AAD TRUE    TRUE    NA   
+#> 5 0033s00001BXfJ9AAL TRUE    TRUE    NA   
+#> # … with 5 more rows
+
+created_records_v2 <- sf_create(new_contacts[11:20,],
+                                object_name = "Contact", 
+                                api_type = "Bulk 2.0")
+created_records_v2
+#> # A tibble: 10 × 7
+#>   sf__Id             sf__Created sf__Error FirstName LastName   My_External_Id_…
+#>   <chr>              <lgl>       <lgl>     <chr>     <chr>      <chr>           
+#> 1 0033s00001BXe6cAAD TRUE        NA        Test      Contact-C… Bulk-89152-k    
+#> 2 0033s00001BXe6dAAD TRUE        NA        Test      Contact-C… Bulk-89152-l    
+#> 3 0033s00001BXe6eAAD TRUE        NA        Test      Contact-C… Bulk-89152-m    
+#> 4 0033s00001BXfJTAA1 TRUE        NA        Test      Contact-C… Bulk-89152-n    
+#> 5 0033s00001BXfJUAA1 TRUE        NA        Test      Contact-C… Bulk-89152-o    
+#> # … with 5 more rows, and 1 more variable: test_number__c <dbl>
+
+
+

Performance Benchmarks for Bulk Queries

+

Below is a simple performance benchmark between the Bulk 1.0 and Bulk 2.0 APIs for a small query. In general, the Bulk 2.0 should be faster. One potential reason for the implementation in R to be faster is that the entire recordset is parsed at once from a downloaded CSV of the results when using the Bulk 1.0 API. The Bulk 2.0 retrieves the same data in large batches (typically 50,000 records at a time). I would encourage users to experiment to see what works best in their Salesforce Org.

+
soql <- "SELECT Id, Name FROM Contact"
+bulk1_query <- function(){sf_query(soql, "Contact", api_type="Bulk 1.0")}
+bulk2_query <- function(){sf_query(soql, api_type="Bulk 2.0")} # Bulk 2.0 doesn't need object name
+
+res <- microbenchmark::microbenchmark(
+  bulk1_query(),
+  bulk2_query(), 
+  times=8, 
+  unit = "s"
+)
+res
+#> Unit: seconds
+#>           expr      min       lq     mean   median       uq       max neval
+#>  bulk1_query() 8.437328 8.636501 8.927289 8.822989 9.201657  9.658687     8
+#>  bulk2_query() 6.821483 6.914214 7.785570 7.019215 8.636023 10.324171     8
+
+suppressWarnings(suppressMessages(
+  ggplot2::autoplot(res) + 
+    ggplot2::scale_y_continuous(name="Time [seconds]", n.breaks=6)
+))
+

+
+ + + + + + + + + + + diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-metadata.R b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-metadata.R new file mode 100644 index 00000000..dee57024 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-metadata.R @@ -0,0 +1,111 @@ +## ---- echo = FALSE------------------------------------------------------------ +NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true") +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + purl = NOT_CRAN, + eval = NOT_CRAN +) +options(tibble.print_min = 5L, tibble.print_max = 5L) + +## ----auth, include = FALSE---------------------------------------------------- +suppressWarnings(suppressMessages(library(dplyr))) +suppressWarnings(suppressMessages(library(purrr))) +suppressWarnings(suppressMessages(library(here))) +library(salesforcer) +token_path <- Sys.getenv("SALESFORCER_TOKEN_PATH") +sf_auth(token = paste0(token_path, "salesforcer_token.rds")) + +## ----load-package, eval=FALSE------------------------------------------------- +# library(dplyr, warn.conflicts = FALSE) +# library(purrr) +# library(salesforcer) +# sf_auth() + +## ----metadata-read------------------------------------------------------------ +read_obj_result <- sf_read_metadata(metadata_type = "CustomObject", + object_names = c("Account", "Contact")) + +read_obj_result[[1]][c("fullName", "label", "sharingModel", "enableHistory")] + +first_two_fields_idx <- head(which(names(read_obj_result[[1]]) == "fields"), 2) + +# show the first two returned fields of the Account object +read_obj_result[[1]][first_two_fields_idx] + +## ----soap-describe-object-fields---------------------------------------------- +acct_fields <- sf_describe_object_fields("Account") +acct_fields %>% select(name, label, length, soapType, type) + +# show the picklist selection options for the Account Type field +acct_fields %>% + filter(label == "Account Type") %>% + .$picklistValues + +## ----rest-describe-objects---------------------------------------------------- +describe_obj_result <- sf_describe_objects(object_names=c('Account', 'Contact')) + +# confirm that the Account object is queryable +describe_obj_result[[1]][c('label', 'queryable')] + +# now show the different picklist values for the Account Type field +all_fields <- describe_obj_result[[1]][names(describe_obj_result[[1]]) == "fields"] + +acct_type_field_idx <- which(sapply(all_fields, + FUN=function(x){x$label}) == "Account Type") +acct_type_field <- all_fields[[acct_type_field_idx]] +acct_type_field[which(names(acct_type_field) == "picklistValues")] %>% + map_df(as_tibble) + +## ----metadata-crud------------------------------------------------------------ +# create an object +base_obj_name <- "Custom_Account1" +custom_object <- list() +custom_object$fullName <- paste0(base_obj_name, "__c") +custom_object$label <- paste0(gsub("_", " ", base_obj_name)) +custom_object$pluralLabel <- paste0(base_obj_name, "s") +custom_object$nameField <- list(displayFormat = 'AN-{0000}', + label = paste0(base_obj_name, ' Number'), + type = 'AutoNumber') +custom_object$deploymentStatus <- 'Deployed' +custom_object$sharingModel <- 'ReadWrite' +custom_object$enableActivities <- 'true' +custom_object$description <- paste0(base_obj_name, " created by the Metadata API") +custom_object_result <- sf_create_metadata(metadata_type = 'CustomObject', + metadata = custom_object) + +# add fields to the object +custom_fields <- tibble(fullName=c(paste0(base_obj_name, '__c.CustomField3__c'), + paste0(base_obj_name, '__c.CustomField4__c')), + label=c('Test Field3', 'Test Field4'), + length=c(100, 100), + type=c('Text', 'Text')) +create_fields_result <- sf_create_metadata(metadata_type = 'CustomField', + metadata = custom_fields) + +# delete the object +delete_obj_result <- sf_delete_metadata(metadata_type = 'CustomObject', + object_names = c('Custom_Account1__c')) + +## ----metadata-crud-field-security, eval=FALSE--------------------------------- +# # get list of user proviles in order to get the "fullName" +# # parameter correct in the next call +# my_queries <- list(list(type = 'Profile')) +# profiles_list <- sf_list_metadata(queries = my_queries) +# +# admin_editable <- list(fullName = 'Admin', +# fieldPermissions=list(field=paste0(custom_object$fullName, +# '.CustomField3__c'), +# editable='true'), +# fieldPermissions=list(field=paste0(custom_object$fullName, +# '.CustomField4__c'), +# editable='true')) +# +# # update the field level security to "editable" for your fields +# prof_update <- sf_update_metadata(metadata_type = 'Profile', +# metadata = admin_editable) +# +# # now try inserting values into that custom object's fields +# my_new_data = tibble(CustomField3__c = "Hello World", CustomField4__c = "Hello World") +# added_record <- sf_create(my_new_data, object_name = custom_object$fullName) + diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-metadata.Rmd b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-metadata.Rmd new file mode 100644 index 00000000..f6c14cf0 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-metadata.Rmd @@ -0,0 +1,176 @@ +--- +title: "Working with Metadata" +author: "Steven M. Mortimer" +date: "2019-07-26" +output: + rmarkdown::html_vignette: + toc: true + toc_depth: 4 + keep_md: true +vignette: > + %\VignetteIndexEntry{Working with Metadata} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, echo = FALSE} +NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true") +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + purl = NOT_CRAN, + eval = NOT_CRAN +) +options(tibble.print_min = 5L, tibble.print_max = 5L) +``` + +Salesforce is a very flexible platform in that it provides the +[Metadata API](https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_intro.htm) +for users to create, read, update and delete their entire Salesforce environment from +objects to page layouts and more. This makes it very easy to programmatically setup +and teardown the Salesforce environment. + +## Retrieving Object Metadata + +One common use case for the Metadata API is retrieving information about an object +(fields, permissions, etc.). First, load the {salesforcer}, {dplyr}, and {purrr} +packages and login, if needed. + +```{r auth, include = FALSE} +suppressWarnings(suppressMessages(library(dplyr))) +suppressWarnings(suppressMessages(library(purrr))) +suppressWarnings(suppressMessages(library(here))) +library(salesforcer) +token_path <- Sys.getenv("SALESFORCER_TOKEN_PATH") +sf_auth(token = paste0(token_path, "salesforcer_token.rds")) +``` + +```{r load-package, eval=FALSE} +library(dplyr, warn.conflicts = FALSE) +library(purrr) +library(salesforcer) +sf_auth() +``` + +You can use the `sf_read_metadata()` function to return a list of objects and +their metadata. In the example below we retrieve the metadata for the Account and +Contact objects. Note that the `metadata_type` argument is "CustomObject". Standard +Objects are an implementation of CustomObjects, so they are returned using that +metadata type. + +```{r metadata-read} +read_obj_result <- sf_read_metadata(metadata_type = "CustomObject", + object_names = c("Account", "Contact")) + +read_obj_result[[1]][c("fullName", "label", "sharingModel", "enableHistory")] + +first_two_fields_idx <- head(which(names(read_obj_result[[1]]) == "fields"), 2) + +# show the first two returned fields of the Account object +read_obj_result[[1]][first_two_fields_idx] +``` + +The data is returned as a list because object definitions are highly nested representations. +You may notice that we are missing some really specific details, such as, the picklist +values of a field with type "Picklist". You can get that information using +`sf_describe_object_fields()`. Here is an example using `sf_describe_object_fields()` +where we get a `tbl_df` with one row for each field on the Account object: + +```{r soap-describe-object-fields} +acct_fields <- sf_describe_object_fields("Account") +acct_fields %>% select(name, label, length, soapType, type) + +# show the picklist selection options for the Account Type field +acct_fields %>% + filter(label == "Account Type") %>% + .$picklistValues +``` + +If you prefer to be more precise about collecting and formatting the field data you +can work directly with the nested lists that the APIs return. In this example we +look at the picklist values of fields on the Account object. + +```{r rest-describe-objects} +describe_obj_result <- sf_describe_objects(object_names=c('Account', 'Contact')) + +# confirm that the Account object is queryable +describe_obj_result[[1]][c('label', 'queryable')] + +# now show the different picklist values for the Account Type field +all_fields <- describe_obj_result[[1]][names(describe_obj_result[[1]]) == "fields"] + +acct_type_field_idx <- which(sapply(all_fields, + FUN=function(x){x$label}) == "Account Type") +acct_type_field <- all_fields[[acct_type_field_idx]] +acct_type_field[which(names(acct_type_field) == "picklistValues")] %>% + map_df(as_tibble) +``` + +It is recommended that you try out the various metadata functions `sf_read_metadata()`, +`sf_list_metadata()`, `sf_describe_metadata()`, and `sf_describe_objects()` in order +to see which information best suits your use case. + +## Modifying Metadata + +Where the Metadata API really shines is when it comes to CRUD operations on metadata. +In this example we will create an object, add fields to it, then delete that object. + +```{r metadata-crud} +# create an object +base_obj_name <- "Custom_Account1" +custom_object <- list() +custom_object$fullName <- paste0(base_obj_name, "__c") +custom_object$label <- paste0(gsub("_", " ", base_obj_name)) +custom_object$pluralLabel <- paste0(base_obj_name, "s") +custom_object$nameField <- list(displayFormat = 'AN-{0000}', + label = paste0(base_obj_name, ' Number'), + type = 'AutoNumber') +custom_object$deploymentStatus <- 'Deployed' +custom_object$sharingModel <- 'ReadWrite' +custom_object$enableActivities <- 'true' +custom_object$description <- paste0(base_obj_name, " created by the Metadata API") +custom_object_result <- sf_create_metadata(metadata_type = 'CustomObject', + metadata = custom_object) + +# add fields to the object +custom_fields <- tibble(fullName=c(paste0(base_obj_name, '__c.CustomField3__c'), + paste0(base_obj_name, '__c.CustomField4__c')), + label=c('Test Field3', 'Test Field4'), + length=c(100, 100), + type=c('Text', 'Text')) +create_fields_result <- sf_create_metadata(metadata_type = 'CustomField', + metadata = custom_fields) + +# delete the object +delete_obj_result <- sf_delete_metadata(metadata_type = 'CustomObject', + object_names = c('Custom_Account1__c')) +``` + +Note that newly created custom fields are not editable by default, meaning that you +will not be able to insert records into them until updating the field level security +of your user profile. Run the following code to determine the user profiles in your +org and updating the field permissions on an object that you may have created with the +example code above. + +```{r metadata-crud-field-security, eval=FALSE} +# get list of user proviles in order to get the "fullName" +# parameter correct in the next call +my_queries <- list(list(type = 'Profile')) +profiles_list <- sf_list_metadata(queries = my_queries) + +admin_editable <- list(fullName = 'Admin', + fieldPermissions=list(field=paste0(custom_object$fullName, + '.CustomField3__c'), + editable='true'), + fieldPermissions=list(field=paste0(custom_object$fullName, + '.CustomField4__c'), + editable='true')) + +# update the field level security to "editable" for your fields +prof_update <- sf_update_metadata(metadata_type = 'Profile', + metadata = admin_editable) + +# now try inserting values into that custom object's fields +my_new_data = tibble(CustomField3__c = "Hello World", CustomField4__c = "Hello World") +added_record <- sf_create(my_new_data, object_name = custom_object$fullName) +``` diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-metadata.html b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-metadata.html new file mode 100644 index 00000000..cfc7afad --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-metadata.html @@ -0,0 +1,520 @@ + + + + + + + + + + + + + + + + +Working with Metadata + + + + + + + + + + + + + + + + + + + + + + + + + +

Working with Metadata

+

Steven M. Mortimer

+

2019-07-26

+ + + + +

Salesforce is a very flexible platform in that it provides the Metadata API for users to create, read, update and delete their entire Salesforce environment from objects to page layouts and more. This makes it very easy to programmatically setup and teardown the Salesforce environment.

+
+

Retrieving Object Metadata

+

One common use case for the Metadata API is retrieving information about an object (fields, permissions, etc.). First, load the {salesforcer}, {dplyr}, and {purrr} packages and login, if needed.

+
library(dplyr, warn.conflicts = FALSE)
+library(purrr)
+library(salesforcer)
+sf_auth()
+

You can use the sf_read_metadata() function to return a list of objects and their metadata. In the example below we retrieve the metadata for the Account and Contact objects. Note that the metadata_type argument is “CustomObject”. Standard Objects are an implementation of CustomObjects, so they are returned using that metadata type.

+
read_obj_result <- sf_read_metadata(metadata_type = "CustomObject",
+                                    object_names = c("Account", "Contact"))
+
+read_obj_result[[1]][c("fullName", "label", "sharingModel", "enableHistory")]
+#> $fullName
+#> [1] "Account"
+#> 
+#> $label
+#> [1] "Account"
+#> 
+#> $sharingModel
+#> [1] "ReadWrite"
+#> 
+#> $enableHistory
+#> [1] "false"
+
+first_two_fields_idx <- head(which(names(read_obj_result[[1]]) == "fields"), 2)
+
+# show the first two returned fields of the Account object
+read_obj_result[[1]][first_two_fields_idx]
+#> $fields
+#> $fields$fullName
+#> [1] "AccountNumber"
+#> 
+#> $fields$trackFeedHistory
+#> [1] "false"
+#> 
+#> 
+#> $fields
+#> $fields$fullName
+#> [1] "AccountSource"
+#> 
+#> $fields$trackFeedHistory
+#> [1] "false"
+#> 
+#> $fields$type
+#> [1] "Picklist"
+

The data is returned as a list because object definitions are highly nested representations. You may notice that we are missing some really specific details, such as, the picklist values of a field with type “Picklist”. You can get that information using
+sf_describe_object_fields(). Here is an example using sf_describe_object_fields() where we get a tbl_df with one row for each field on the Account object:

+
acct_fields <- sf_describe_object_fields("Account")
+acct_fields %>% select(name, label, length, soapType, type)
+#> # A tibble: 68 × 5
+#>   name           label            length soapType    type     
+#>   <chr>          <chr>            <chr>  <chr>       <chr>    
+#> 1 Id             Account ID       18     tns:ID      id       
+#> 2 IsDeleted      Deleted          0      xsd:boolean boolean  
+#> 3 MasterRecordId Master Record ID 18     tns:ID      reference
+#> 4 Name           Account Name     255    xsd:string  string   
+#> 5 Type           Account Type     255    xsd:string  picklist 
+#> # … with 63 more rows
+
+# show the picklist selection options for the Account Type field
+acct_fields %>% 
+  filter(label == "Account Type") %>% 
+  .$picklistValues
+#> [[1]]
+#> # A tibble: 7 × 4
+#>   active defaultValue label                      value                     
+#>   <chr>  <chr>        <chr>                      <chr>                     
+#> 1 true   false        Prospect                   Prospect                  
+#> 2 true   false        Customer - Direct          Customer - Direct         
+#> 3 true   false        Customer - Channel         Customer - Channel        
+#> 4 true   false        Channel Partner / Reseller Channel Partner / Reseller
+#> 5 true   false        Installation Partner       Installation Partner      
+#> # … with 2 more rows
+

If you prefer to be more precise about collecting and formatting the field data you can work directly with the nested lists that the APIs return. In this example we look at the picklist values of fields on the Account object.

+
describe_obj_result <- sf_describe_objects(object_names=c('Account', 'Contact'))
+
+# confirm that the Account object is queryable
+describe_obj_result[[1]][c('label', 'queryable')]
+#> $label
+#> [1] "Account"
+#> 
+#> $queryable
+#> [1] "true"
+
+# now show the different picklist values for the Account Type field
+all_fields <- describe_obj_result[[1]][names(describe_obj_result[[1]]) == "fields"]
+
+acct_type_field_idx <- which(sapply(all_fields, 
+                                    FUN=function(x){x$label}) == "Account Type")
+acct_type_field <- all_fields[[acct_type_field_idx]]
+acct_type_field[which(names(acct_type_field) == "picklistValues")] %>% 
+  map_df(as_tibble)
+#> # A tibble: 7 × 4
+#>   active defaultValue label                      value                     
+#>   <chr>  <chr>        <chr>                      <chr>                     
+#> 1 true   false        Prospect                   Prospect                  
+#> 2 true   false        Customer - Direct          Customer - Direct         
+#> 3 true   false        Customer - Channel         Customer - Channel        
+#> 4 true   false        Channel Partner / Reseller Channel Partner / Reseller
+#> 5 true   false        Installation Partner       Installation Partner      
+#> # … with 2 more rows
+

It is recommended that you try out the various metadata functions sf_read_metadata(), sf_list_metadata(), sf_describe_metadata(), and sf_describe_objects() in order to see which information best suits your use case.

+
+
+

Modifying Metadata

+

Where the Metadata API really shines is when it comes to CRUD operations on metadata. In this example we will create an object, add fields to it, then delete that object.

+
# create an object
+base_obj_name <- "Custom_Account1"
+custom_object <- list()
+custom_object$fullName <- paste0(base_obj_name, "__c")
+custom_object$label <- paste0(gsub("_", " ", base_obj_name))
+custom_object$pluralLabel <- paste0(base_obj_name, "s")
+custom_object$nameField <- list(displayFormat = 'AN-{0000}', 
+                                label = paste0(base_obj_name, ' Number'), 
+                                type = 'AutoNumber')
+custom_object$deploymentStatus <- 'Deployed'
+custom_object$sharingModel <- 'ReadWrite'
+custom_object$enableActivities <- 'true'
+custom_object$description <- paste0(base_obj_name, " created by the Metadata API")
+custom_object_result <- sf_create_metadata(metadata_type = 'CustomObject',
+                                           metadata = custom_object)
+
+# add fields to the object
+custom_fields <- tibble(fullName=c(paste0(base_obj_name, '__c.CustomField3__c'), 
+                                   paste0(base_obj_name, '__c.CustomField4__c')), 
+                        label=c('Test Field3', 'Test Field4'), 
+                        length=c(100, 100), 
+                        type=c('Text', 'Text'))
+create_fields_result <- sf_create_metadata(metadata_type = 'CustomField', 
+                                           metadata = custom_fields)
+
+# delete the object
+delete_obj_result <- sf_delete_metadata(metadata_type = 'CustomObject', 
+                                        object_names = c('Custom_Account1__c'))
+

Note that newly created custom fields are not editable by default, meaning that you will not be able to insert records into them until updating the field level security of your user profile. Run the following code to determine the user profiles in your org and updating the field permissions on an object that you may have created with the example code above.

+
# get list of user proviles in order to get the "fullName" 
+# parameter correct in the next call
+my_queries <- list(list(type = 'Profile'))
+profiles_list <- sf_list_metadata(queries = my_queries)
+
+admin_editable <- list(fullName = 'Admin', 
+                       fieldPermissions=list(field=paste0(custom_object$fullName, 
+                                                          '.CustomField3__c'),
+                                             editable='true'), 
+                       fieldPermissions=list(field=paste0(custom_object$fullName, 
+                                                          '.CustomField4__c'),
+                                             editable='true'))
+
+# update the field level security to "editable" for your fields
+prof_update <- sf_update_metadata(metadata_type = 'Profile', 
+                                  metadata = admin_editable)
+
+# now try inserting values into that custom object's fields
+my_new_data = tibble(CustomField3__c = "Hello World", CustomField4__c = "Hello World")
+added_record <- sf_create(my_new_data, object_name = custom_object$fullName)
+
+ + + + + + + + + + + diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-reports.R b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-reports.R new file mode 100644 index 00000000..a7279ef9 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-reports.R @@ -0,0 +1,109 @@ +## ---- echo = FALSE------------------------------------------------------------ +NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true") +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + purl = NOT_CRAN, + eval = NOT_CRAN +) +options(tibble.print_min = 5L, tibble.print_max = 5L) + +## ----auth, include = FALSE---------------------------------------------------- +suppressWarnings(suppressMessages(library(dplyr))) +suppressWarnings(suppressMessages(library(here))) +library(salesforcer) +token_path <- Sys.getenv("SALESFORCER_TOKEN_PATH") +sf_auth(token = paste0(token_path, "salesforcer_token.rds")) + +## ----load-package, eval=FALSE------------------------------------------------- +# library(dplyr, warn.conflicts = FALSE) +# library(salesforcer) +# sf_auth() + +## ----simple-report------------------------------------------------------------ +my_report_id <- "00O3s000006tE7zEAE" +results <- sf_run_report(my_report_id) +results + +## ----filtered-report1--------------------------------------------------------- +# filter records that was created before this month +filter1 <- list(column = "CREATED_DATE", + operator = "lessThan", + value = "THIS_MONTH") + +# filter records where the account billing address city is not empty +filter2 <- list(column = "ACCOUNT.ADDRESS1_CITY", + operator = "notEqual", + value = "") + +# combine filter1 and filter2 using 'AND' which means that records must meet both filters +results_using_AND <- sf_run_report(my_report_id, + report_boolean_logic = "1 AND 2", + report_filters = list(filter1, filter2)) +results_using_AND + +## ----filtered-report2--------------------------------------------------------- +# combine filter1 and filter2 using 'OR' which means that records must meet one +# of the filters but also throw in a row limit based on a specific sort order +results_using_OR <- sf_run_report(my_report_id, + report_boolean_logic = "1 OR 2", + report_filters = list(filter1, filter2), + sort_by = "Contact.test_number__c", + decreasing = TRUE, + top_n = 5) +results_using_OR + +## ----describe-report---------------------------------------------------------- +report_details <- sf_describe_report(my_report_id) +report_details$reportMetadata$reportType$type +report_details$reportMetadata$reportFilters + +## ----report-type-metadata----------------------------------------------------- +report_details$reportTypeMetadata$standardDateFilterDurationGroups[[6]]$standardDateFilterDurations[[1]] + +## ----report-filter-operators-------------------------------------------------- +# report fields +report_fields <- sf_list_report_fields(my_report_id) +head(names(report_fields$equivalentFieldIndices)) + +report_filters <- sf_list_report_filter_operators() +unique_supported_fields <- report_filters %>% + distinct(supported_field_type) %>% + unlist() +unique_supported_fields + +# operators to filter a picklist field +picklist_field_operators <- report_filters %>% + filter(supported_field_type == "picklist") +picklist_field_operators + +## ----admin-example------------------------------------------------------------ +# first, grab all possible reports in your Org +all_reports <- sf_query("SELECT Id, Name FROM Report") + +# second, get the id of the report to update +this_report_id <- all_reports$Id[1] + +new_report <- sf_copy_report(this_report_id) + +# third, update the report (2 ways shown) +my_updated_report <- sf_update_report(new_report$reportMetadata$id, + report_metadata = + list(reportMetadata = + list(name = "Updated Name!"))) +my_updated_report$reportMetadata$name + +# alternatively, pull down its metadata and update the name +report_details <- sf_describe_report(new_report$reportMetadata$id) +report_details$reportMetadata$name <- paste0(report_details$reportMetadata$name, + " - UPDATED AGAIN!") + +# update the report by passing the metadata +my_updated_report <- sf_update_report(new_report$reportMetadata$id, + report_metadata = report_details) +my_updated_report$reportMetadata$name + +# fourth, delete that report using its Id +success <- sf_delete_report(new_report$reportMetadata$id) +success + diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-reports.Rmd b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-reports.Rmd new file mode 100644 index 00000000..855b990e --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-reports.Rmd @@ -0,0 +1,257 @@ +--- +title: "Working with Reports" +author: "Steven M. Mortimer" +date: "2020-07-19" +output: + rmarkdown::html_vignette: + toc: true + toc_depth: 4 + keep_md: true +vignette: > + %\VignetteIndexEntry{Working with Reports} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, echo = FALSE} +NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true") +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + purl = NOT_CRAN, + eval = NOT_CRAN +) +options(tibble.print_min = 5L, tibble.print_max = 5L) +``` + +## Overview + +The following vignette outlines how to execute and manage reports in your Org. +**Note**: These features are still experimental and are likely to change and/or +have bugs. Please take this into account, and if you run into any issues please +consider submitting an issue [HERE](https://github.com/StevenMMortimer/salesforcer/issues/new?assignees=StevenMMortimer&labels=&template=default-issue-template.md&title=) in the GitHub repository so that we can help troubleshoot and fix, if needed. Thank you! + +In order to pull down the results of a report created within Salesforce all you +need to know and have is the report's Salesforce Id. If you want to fully leverage +the features of the Reports and Dashboards REST API I recommend reading the following +so that you are better equipped to understand and use the functions within {salesforcer}. + + - Running a Report Synchronously or Asynchronously + - Understanding a Report Fact Map + - Filter Reports on Demand + - Reports and Dashboards REST API Documentation Home Page + +---- + +## Authenticate + +First, load the {salesforcer} package and login either by OAuth 2.0 (SSO) or +using your username, password, and security key. + +```{r auth, include = FALSE} +suppressWarnings(suppressMessages(library(dplyr))) +suppressWarnings(suppressMessages(library(here))) +library(salesforcer) +token_path <- Sys.getenv("SALESFORCER_TOKEN_PATH") +sf_auth(token = paste0(token_path, "salesforcer_token.rds")) +``` + +```{r load-package, eval=FALSE} +library(dplyr, warn.conflicts = FALSE) +library(salesforcer) +sf_auth() +``` + +## Running a Report in your Org + +In Salesforce there is a dedicated page to displaying the list of reports in your +Org. It typically follows the pattern: `https://na1.salesforce.com/00O/o` +(replace `na1` with your server instance). When you click on a report in the GUI +you should see the results. Below is a screenshot of how a report may look in +your Org. Note the report Id in the URL bar. + +![](./working-with-reports_files/report-screenshot.png) + +The report Id above (`"00O3s000006tE7zEAE"`) is the only information needed to pull +those same results from an R session, like so: + +```{r simple-report} +my_report_id <- "00O3s000006tE7zEAE" +results <- sf_run_report(my_report_id) +results +``` + +Note that the `sf_run_report()` function will, by default, run the report +asynchronously. This means that a report instance will be requested and then the +function will wait to retrieve the results. The advantage to using an +asynchronous report is that the results of such a report are stored for 24 hours +and can be retrieved again saving CPU resources, if needed. A more in-depth +discussion on synchronous vs. asynchronous reports is available here https://developer.salesforce.com/docs/atlas.en-us.api_analytics.meta/api_analytics/sforce_analytics_rest_api_get_reportdata.htm. However, for reports +with a relatively small number of records a synchronous report may be faster without +having to do the round trip of creating then querying a report instance. + +## Filtering a Report on the Fly + +The neat thing about using the API is that you can retrieve the results of a +report with different filters applied. This allows you to obtain exactly the +results needed without having to create separate copies of the same +report. It takes some basic understanding of how report operators need to be +supplied to the API, but it is not too difficult. Below is an example that only +includes contact records created prior to this month and belong to an Account +with a non-NULL Billing City. + +```{r filtered-report1} +# filter records that was created before this month +filter1 <- list(column = "CREATED_DATE", + operator = "lessThan", + value = "THIS_MONTH") + +# filter records where the account billing address city is not empty +filter2 <- list(column = "ACCOUNT.ADDRESS1_CITY", + operator = "notEqual", + value = "") + +# combine filter1 and filter2 using 'AND' which means that records must meet both filters +results_using_AND <- sf_run_report(my_report_id, + report_boolean_logic = "1 AND 2", + report_filters = list(filter1, filter2)) +results_using_AND +``` + +This second example shows how to return only the Top N number of records and +combine the filter using the logical "OR" instead of "AND". + +```{r filtered-report2} +# combine filter1 and filter2 using 'OR' which means that records must meet one +# of the filters but also throw in a row limit based on a specific sort order +results_using_OR <- sf_run_report(my_report_id, + report_boolean_logic = "1 OR 2", + report_filters = list(filter1, filter2), + sort_by = "Contact.test_number__c", + decreasing = TRUE, + top_n = 5) +results_using_OR +``` + +I was able to determine some of the potential ways to filter by first reviewing +the `reportFilters` element in the existing report metadata and also reviewing +the list of report filter operators. + +First, you can always take the report filter specification from the report +metadata and tailor it to your needs. Below is an example showing how to get +that metadata for our report. You can select specific elements to better +understand the structure of the report. + +```{r describe-report} +report_details <- sf_describe_report(my_report_id) +report_details$reportMetadata$reportType$type +report_details$reportMetadata$reportFilters +``` + +Second, Salesforce has a few API endpoints that tell you the fields on the report +or the report type, more generally, and all the ways you can declare a filter on +a particular field type and. The `reportTypeMetadata` element returned on the report +description also has detailed information on how to filter the report. For example, it +already contains the start and end dates that would be applied when using the +"LAST_MONTH" filter value on a date field. + +```{r report-type-metadata} +report_details$reportTypeMetadata$standardDateFilterDurationGroups[[6]]$standardDateFilterDurations[[1]] +``` + +Digging into the metadata of the report will allow you to better understand what +filters you can set when filtering on the fly. In the example below you should +notice that the field names on the report do not match the names of the typical +API field names for the object, so please review carefully the fields on the +report. For example, the `CREATED_DATE` report field is based on the +`CreatedDate` object field. + +```{r report-filter-operators} +# report fields +report_fields <- sf_list_report_fields(my_report_id) +head(names(report_fields$equivalentFieldIndices)) + +report_filters <- sf_list_report_filter_operators() +unique_supported_fields <- report_filters %>% + distinct(supported_field_type) %>% + unlist() +unique_supported_fields + +# operators to filter a picklist field +picklist_field_operators <- report_filters %>% + filter(supported_field_type == "picklist") +picklist_field_operators +``` + +## Managing your Reports + +The API also allows you to perform many admin functions like creating, copying, +updating, or deleting reports and report instances. Take advantage of these functions +as needed to keep your Org's report list well-maintained. Below is a simple flow +of creating, updating, and deleting a single report, but the amount you're able to +customize is completely up to you. The {salesforcer} package should support any +operation that the Reports and Dashboards REST API supports. + +```{r admin-example} +# first, grab all possible reports in your Org +all_reports <- sf_query("SELECT Id, Name FROM Report") + +# second, get the id of the report to update +this_report_id <- all_reports$Id[1] + +new_report <- sf_copy_report(this_report_id) + +# third, update the report (2 ways shown) +my_updated_report <- sf_update_report(new_report$reportMetadata$id, + report_metadata = + list(reportMetadata = + list(name = "Updated Name!"))) +my_updated_report$reportMetadata$name + +# alternatively, pull down its metadata and update the name +report_details <- sf_describe_report(new_report$reportMetadata$id) +report_details$reportMetadata$name <- paste0(report_details$reportMetadata$name, + " - UPDATED AGAIN!") + +# update the report by passing the metadata +my_updated_report <- sf_update_report(new_report$reportMetadata$id, + report_metadata = report_details) +my_updated_report$reportMetadata$name + +# fourth, delete that report using its Id +success <- sf_delete_report(new_report$reportMetadata$id) +success +``` + +## Troubleshooting + +If you are having an issue with a report please submit in the {salesforcer} GitHub +repository at: https://github.com/StevenMMortimer/salesforcer/issues. As a maintainer, reports can be are tough to debug because every Salesforce +Org is unique. When filing your issue please make an attempt to understand the +query and debug a little bit on your own. Here are a few suggestions: + + 1. Slightly modify your function call to `sf_run_report()` to observe the results. Here + are a few prompting questions that may assist you: + + - What do you see when you set `verbose=TRUE` argument? + + - What happens if you run sync. vs. async. (e.g. async=TRUE vs. FALSE)? + + - What happens if you try running a different type of report? + + 2. Double check Salesforce's Reports and Dashboards REST API Developer Guide to see whether if your report type would be supported or limited in some way. + + 3. Review report unit tests at: https://github.com/StevenMMortimer/salesforcer/blob/main/tests/testthat/test-report.R. + These unit tests were written to cover a variety of use cases and to track any + changes made between newly released versions of the Salesforce API (typically + 4 each year). These tests are an excellent source of examples that may be + helpful in troubleshooting your own case. + + 4. Roll up your sleeves and dive into the source code for the {salesforcer} + package. The main scripts to review are: + + - https://github.com/StevenMMortimer/salesforcer/blob/main/R/analytics-report.R + + - https://github.com/StevenMMortimer/salesforcer/blob/main/R/utils-report.R diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-reports.html b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-reports.html new file mode 100644 index 00000000..bd458dad --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/doc/working-with-reports.html @@ -0,0 +1,613 @@ + + + + + + + + + + + + + + + + +Working with Reports + + + + + + + + + + + + + + + + + + + + + + + + + +

Working with Reports

+

Steven M. Mortimer

+

2020-07-19

+ + + + +
+

Overview

+

The following vignette outlines how to execute and manage reports in your Org. Note: These features are still experimental and are likely to change and/or have bugs. Please take this into account, and if you run into any issues please consider submitting an issue HERE in the GitHub repository so that we can help troubleshoot and fix, if needed. Thank you!

+

In order to pull down the results of a report created within Salesforce all you need to know and have is the report’s Salesforce Id. If you want to fully leverage the features of the Reports and Dashboards REST API I recommend reading the following so that you are better equipped to understand and use the functions within {salesforcer}.

+ +
+
+
+

Authenticate

+

First, load the {salesforcer} package and login either by OAuth 2.0 (SSO) or using your username, password, and security key.

+
library(dplyr, warn.conflicts = FALSE)
+library(salesforcer)
+sf_auth()
+
+
+

Running a Report in your Org

+

In Salesforce there is a dedicated page to displaying the list of reports in your Org. It typically follows the pattern: https://na1.salesforce.com/00O/o (replace na1 with your server instance). When you click on a report in the GUI you should see the results. Below is a screenshot of how a report may look in your Org. Note the report Id in the URL bar.

+

+

The report Id above ("00O3s000006tE7zEAE") is the only information needed to pull those same results from an R session, like so:

+
my_report_id <- "00O3s000006tE7zEAE"
+results <- sf_run_report(my_report_id)
+results
+#> # A tibble: 14 × 8
+#>   `Contact ID`    `First Name` `test number` `Contact Owner` `Account ID`   
+#>   <chr>           <chr>                <dbl> <chr>           <chr>          
+#> 1 0036A000002C6MW Rose                    NA Steven Mortimer 0016A0000035mJ4
+#> 2 0036A000002C6MX Sean                    NA Steven Mortimer 0016A0000035mJ4
+#> 3 0036A000002C6MY Jack                    99 Steven Mortimer 0016A0000035mJ5
+#> 4 0036A000002C6Mb Tim                     NA Steven Mortimer 0016A0000035mJ8
+#> 5 0036A000002C6Mc John                    23 Steven Mortimer 0016A0000035mJ8
+#> # … with 9 more rows, and 3 more variables: `Account Name` <chr>,
+#> #   `Billing City` <chr>, `Account Owner` <chr>
+

Note that the sf_run_report() function will, by default, run the report asynchronously. This means that a report instance will be requested and then the function will wait to retrieve the results. The advantage to using an asynchronous report is that the results of such a report are stored for 24 hours and can be retrieved again saving CPU resources, if needed. A more in-depth discussion on synchronous vs. asynchronous reports is available here https://developer.salesforce.com/docs/atlas.en-us.api_analytics.meta/api_analytics/sforce_analytics_rest_api_get_reportdata.htm. However, for reports with a relatively small number of records a synchronous report may be faster without having to do the round trip of creating then querying a report instance.

+
+
+

Filtering a Report on the Fly

+

The neat thing about using the API is that you can retrieve the results of a report with different filters applied. This allows you to obtain exactly the results needed without having to create separate copies of the same report. It takes some basic understanding of how report operators need to be supplied to the API, but it is not too difficult. Below is an example that only includes contact records created prior to this month and belong to an Account with a non-NULL Billing City.

+
# filter records that was created before this month
+filter1 <- list(column = "CREATED_DATE",
+                        operator = "lessThan", 
+                        value = "THIS_MONTH")
+
+# filter records where the account billing address city is not empty
+filter2 <-  list(column = "ACCOUNT.ADDRESS1_CITY",
+                        operator = "notEqual", 
+                        value = "")
+
+# combine filter1 and filter2 using 'AND' which means that records must meet both filters
+results_using_AND <- sf_run_report(my_report_id, 
+                                   report_boolean_logic = "1 AND 2",
+                                   report_filters = list(filter1, filter2))
+results_using_AND
+#> # A tibble: 14 × 8
+#>   `Contact ID`    `First Name` `test number` `Contact Owner` `Account ID`   
+#>   <chr>           <chr>                <dbl> <chr>           <chr>          
+#> 1 0036A000002C6Mm Edna                    NA Steven Mortimer 0016A0000035mJE
+#> 2 0036A000002C6Mk Tom                     NA Steven Mortimer 0016A0000035mJD
+#> 3 0036A000002C6Ml Liz                     NA Steven Mortimer 0016A0000035mJD
+#> 4 0036A000002C6MW Rose                    NA Steven Mortimer 0016A0000035mJ4
+#> 5 0036A000002C6MX Sean                    NA Steven Mortimer 0016A0000035mJ4
+#> # … with 9 more rows, and 3 more variables: `Account Name` <chr>,
+#> #   `Billing City` <chr>, `Account Owner` <chr>
+

This second example shows how to return only the Top N number of records and combine the filter using the logical “OR” instead of “AND”.

+
# combine filter1 and filter2 using 'OR' which means that records must meet one 
+# of the filters but also throw in a row limit based on a specific sort order
+results_using_OR <- sf_run_report(my_report_id, 
+                                  report_boolean_logic = "1 OR 2",
+                                  report_filters = list(filter1, filter2), 
+                                  sort_by = "Contact.test_number__c", 
+                                  decreasing = TRUE, 
+                                  top_n = 5)
+results_using_OR
+#> # A tibble: 5 × 8
+#>   `Contact ID`    `First Name` `test number` `Contact Owner` `Account ID`   
+#>   <chr>           <chr>                <dbl> <chr>           <chr>          
+#> 1 0033s000012Nl0r KEEP                  1000 Steven Mortimer 0013s00000zFdug
+#> 2 0033s000012Nl0s KEEP                  1000 Steven Mortimer 0013s00000zFdug
+#> 3 0033s000012Nl0v KEEP                  1000 Steven Mortimer 0013s00000zFdug
+#> 4 0033s000012Nl0u KEEP                  1000 Steven Mortimer 0013s00000zFdug
+#> 5 0033s000012Nl0t KEEP                  1000 Steven Mortimer 0013s00000zFdug
+#> # … with 3 more variables: `Account Name` <chr>, `Billing City` <chr>,
+#> #   `Account Owner` <chr>
+

I was able to determine some of the potential ways to filter by first reviewing the reportFilters element in the existing report metadata and also reviewing the list of report filter operators.

+

First, you can always take the report filter specification from the report metadata and tailor it to your needs. Below is an example showing how to get that metadata for our report. You can select specific elements to better understand the structure of the report.

+
report_details <- sf_describe_report(my_report_id)
+report_details$reportMetadata$reportType$type
+#> [1] "ContactList"
+report_details$reportMetadata$reportFilters
+#> [[1]]
+#> [[1]]$column
+#> [1] "CREATED_DATE"
+#> 
+#> [[1]]$filterType
+#> [1] "fieldValue"
+#> 
+#> [[1]]$isRunPageEditable
+#> [1] TRUE
+#> 
+#> [[1]]$operator
+#> [1] "lessThan"
+#> 
+#> [[1]]$value
+#> [1] "2019-07-19T04:00:00Z"
+#> 
+#> 
+#> [[2]]
+#> [[2]]$column
+#> [1] "ACCOUNT.ADDRESS1_CITY"
+#> 
+#> [[2]]$filterType
+#> [1] "fieldValue"
+#> 
+#> [[2]]$isRunPageEditable
+#> [1] TRUE
+#> 
+#> [[2]]$operator
+#> [1] "notEqual"
+#> 
+#> [[2]]$value
+#> [1] ""
+

Second, Salesforce has a few API endpoints that tell you the fields on the report or the report type, more generally, and all the ways you can declare a filter on a particular field type and. The reportTypeMetadata element returned on the report description also has detailed information on how to filter the report. For example, it already contains the start and end dates that would be applied when using the “LAST_MONTH” filter value on a date field.

+
report_details$reportTypeMetadata$standardDateFilterDurationGroups[[6]]$standardDateFilterDurations[[1]]
+#> $endDate
+#> [1] "2022-02-28"
+#> 
+#> $label
+#> [1] "Last Month"
+#> 
+#> $startDate
+#> [1] "2022-02-01"
+#> 
+#> $value
+#> [1] "LAST_MONTH"
+

Digging into the metadata of the report will allow you to better understand what filters you can set when filtering on the fly. In the example below you should notice that the field names on the report do not match the names of the typical API field names for the object, so please review carefully the fields on the report. For example, the CREATED_DATE report field is based on the CreatedDate object field.

+
# report fields
+report_fields <- sf_list_report_fields(my_report_id)
+head(names(report_fields$equivalentFieldIndices))
+#> [1] "CONTACT_CREATED_ALIAS"     "Contact.My_External_Id__c"
+#> [3] "IS_EMAIL_BOUNCED"          "REPORTS_TO"               
+#> [5] "ADDRESS2_ZIP"              "LAST_ACTIVITY"
+
+report_filters <- sf_list_report_filter_operators()
+unique_supported_fields <- report_filters %>% 
+  distinct(supported_field_type) %>% 
+  unlist()
+unique_supported_fields
+#>        supported_field_type1        supported_field_type2 
+#>                       "date"                    "address" 
+#>        supported_field_type3        supported_field_type4 
+#>                     "string"                     "double" 
+#>        supported_field_type5        supported_field_type6 
+#>                   "picklist"                   "textarea" 
+#>        supported_field_type7        supported_field_type8 
+#>            "encryptedstring"                    "percent" 
+#>        supported_field_type9       supported_field_type10 
+#>                        "int"                        "url" 
+#>       supported_field_type11       supported_field_type12 
+#>                  "reference"                   "datetime" 
+#>       supported_field_type13       supported_field_type14 
+#>                    "boolean"                      "phone" 
+#>       supported_field_type15       supported_field_type16 
+#> "datacategorygroupreference"                   "currency" 
+#>       supported_field_type17       supported_field_type18 
+#>                   "location"                       "html" 
+#>       supported_field_type19       supported_field_type20 
+#>                         "id"                       "time" 
+#>       supported_field_type21       supported_field_type22 
+#>                      "email"              "multipicklist"
+
+# operators to filter a picklist field
+picklist_field_operators <- report_filters %>% 
+  filter(supported_field_type == "picklist")
+picklist_field_operators
+#> # A tibble: 9 × 3
+#>   supported_field_type label         name       
+#>   <chr>                <chr>         <chr>      
+#> 1 picklist             equals        equals     
+#> 2 picklist             not equal to  notEqual   
+#> 3 picklist             less than     lessThan   
+#> 4 picklist             greater than  greaterThan
+#> 5 picklist             less or equal lessOrEqual
+#> # … with 4 more rows
+
+
+

Managing your Reports

+

The API also allows you to perform many admin functions like creating, copying, updating, or deleting reports and report instances. Take advantage of these functions as needed to keep your Org’s report list well-maintained. Below is a simple flow of creating, updating, and deleting a single report, but the amount you’re able to customize is completely up to you. The {salesforcer} package should support any operation that the Reports and Dashboards REST API supports.

+
# first, grab all possible reports in your Org
+all_reports <- sf_query("SELECT Id, Name FROM Report")
+
+# second, get the id of the report to update
+this_report_id <- all_reports$Id[1]
+
+new_report <- sf_copy_report(this_report_id)
+#> Naming the new report: 'ReportName - Copy'
+
+# third, update the report (2 ways shown)
+my_updated_report <- sf_update_report(new_report$reportMetadata$id,
+                                      report_metadata =
+                                        list(reportMetadata =
+                                          list(name = "Updated Name!")))
+my_updated_report$reportMetadata$name
+#> [1] "Updated Name!"
+
+# alternatively, pull down its metadata and update the name
+report_details <- sf_describe_report(new_report$reportMetadata$id)
+report_details$reportMetadata$name <- paste0(report_details$reportMetadata$name,
+                                             " - UPDATED AGAIN!")
+
+# update the report by passing the metadata
+my_updated_report <- sf_update_report(new_report$reportMetadata$id,
+                                      report_metadata = report_details)
+my_updated_report$reportMetadata$name
+#> [1] "Updated Name! - UPDATED AGAIN!"
+
+# fourth, delete that report using its Id
+success <- sf_delete_report(new_report$reportMetadata$id)
+success
+#> [1] TRUE
+
+
+

Troubleshooting

+

If you are having an issue with a report please submit in the {salesforcer} GitHub repository at: https://github.com/StevenMMortimer/salesforcer/issues. As a maintainer, reports can be are tough to debug because every Salesforce Org is unique. When filing your issue please make an attempt to understand the query and debug a little bit on your own. Here are a few suggestions:

+
    +
  1. Slightly modify your function call to sf_run_report() to observe the results. Here are a few prompting questions that may assist you:

    +
      +
    • What do you see when you set verbose=TRUE argument?

    • +
    • What happens if you run sync. vs. async. (e.g. async=TRUE vs. FALSE)?

    • +
    • What happens if you try running a different type of report?

    • +
  2. +
  3. Double check Salesforce’s Reports and Dashboards REST API Developer Guide to see whether if your report type would be supported or limited in some way.

  4. +
  5. Review report unit tests at: https://github.com/StevenMMortimer/salesforcer/blob/main/tests/testthat/test-report.R. These unit tests were written to cover a variety of use cases and to track any changes made between newly released versions of the Salesforce API (typically 4 each year). These tests are an excellent source of examples that may be helpful in troubleshooting your own case.

  6. +
  7. Roll up your sleeves and dive into the source code for the {salesforcer} package. The main scripts to review are:

    +
  8. +
+
+ + + + + + + + + + + diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/extdata/cloud.png b/revdep/library.noindex/salesforcer/old/salesforcer/extdata/cloud.png new file mode 100644 index 00000000..f3d90f71 Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/extdata/cloud.png differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/extdata/logo.png b/revdep/library.noindex/salesforcer/old/salesforcer/extdata/logo.png new file mode 100644 index 00000000..ecf5fa74 Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/extdata/logo.png differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/extdata/old-logo.png b/revdep/library.noindex/salesforcer/old/salesforcer/extdata/old-logo.png new file mode 100644 index 00000000..9e2ae3be Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/extdata/old-logo.png differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/AnIndex b/revdep/library.noindex/salesforcer/old/salesforcer/help/AnIndex new file mode 100644 index 00000000..0dc78b36 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/help/AnIndex @@ -0,0 +1,298 @@ +salesforcer-package salesforcer-package +accepted_controls_by_api accepted_controls_by_api +accepted_controls_by_operation accepted_controls_by_operation +bind_query_resultsets bind_query_resultsets +build_manifest_xml_from_list build_manifest_xml_from_list +build_metadata_xml_from_list build_metadata_xml_from_list +build_proxy build_proxy +build_soap_xml_from_list build_soap_xml_from_list +catch_errors catch_errors +catch_unknown_api catch_unknown_api +check_and_encode_files check_and_encode_files +collapse_list_with_dupe_names collapse_list_with_dupe_names +combine_parent_and_child_resultsets combine_parent_and_child_resultsets +compact2 compact2 +drop_attributes drop_attributes +drop_attributes_recursively drop_attributes_recursively +drop_empty_recursively drop_empty_recursively +drop_nested_child_records drop_nested_child_records +extract_nested_child_records extract_nested_child_records +extract_records_from_xml_node extract_records_from_xml_node +extract_records_from_xml_nodeset extract_records_from_xml_nodeset +extract_records_from_xml_nodeset_of_records extract_records_from_xml_nodeset_of_records +filter_valid_controls filter_valid_controls +flatten_tbl_df flatten_tbl_df +format_headers_for_verbose format_headers_for_verbose +format_report_row format_report_row +get_os get_os +guess_object_name_from_soql guess_object_name_from_soql +is_legit_token is_legit_token +list_extract_parent_and_child_result list_extract_parent_and_child_result +make_analytics_folder_child_operations_url make_analytics_folder_child_operations_url +make_analytics_folder_collections_url make_analytics_folder_collections_url +make_analytics_folder_operations_url make_analytics_folder_operations_url +make_analytics_folder_shares_url make_analytics_folder_shares_url +make_analytics_folder_share_by_id_url make_analytics_folder_share_by_id_url +make_analytics_folder_share_recipients_url make_analytics_folder_share_recipients_url +make_analytics_notifications_limits_url make_analytics_notifications_limits_url +make_analytics_notifications_list_url make_analytics_notifications_list_url +make_analytics_notification_operations_url make_analytics_notification_operations_url +make_base_metadata_url make_base_metadata_url +make_base_rest_url make_base_rest_url +make_base_soap_url make_base_soap_url +make_bulk_batches_url make_bulk_batches_url +make_bulk_batch_details_url make_bulk_batch_details_url +make_bulk_batch_status_url make_bulk_batch_status_url +make_bulk_create_job_url make_bulk_create_job_url +make_bulk_delete_job_url make_bulk_delete_job_url +make_bulk_end_job_generic_url make_bulk_end_job_generic_url +make_bulk_get_all_jobs_url make_bulk_get_all_jobs_url +make_bulk_get_all_query_jobs_url make_bulk_get_all_query_jobs_url +make_bulk_get_job_url make_bulk_get_job_url +make_bulk_job_records_url make_bulk_job_records_url +make_bulk_query_result_url make_bulk_query_result_url +make_bulk_query_url make_bulk_query_url +make_chatter_users_url make_chatter_users_url +make_composite_batch_url make_composite_batch_url +make_composite_url make_composite_url +make_dashboards_list_url make_dashboards_list_url +make_dashboard_copy_url make_dashboard_copy_url +make_dashboard_describe_url make_dashboard_describe_url +make_dashboard_filter_operators_list_url make_dashboard_filter_operators_list_url +make_dashboard_filter_options_analysis_url make_dashboard_filter_options_analysis_url +make_dashboard_status_url make_dashboard_status_url +make_dashboard_url make_dashboard_url +make_login_url make_login_url +make_parameterized_search_url make_parameterized_search_url +make_query_url make_query_url +make_reports_list_url make_reports_list_url +make_report_copy_url make_report_copy_url +make_report_create_url make_report_create_url +make_report_describe_url make_report_describe_url +make_report_execute_url make_report_execute_url +make_report_fields_url make_report_fields_url +make_report_filter_operators_list_url make_report_filter_operators_list_url +make_report_instances_list_url make_report_instances_list_url +make_report_instance_url make_report_instance_url +make_report_query_url make_report_query_url +make_report_types_list_url make_report_types_list_url +make_report_type_describe_url make_report_type_describe_url +make_report_url make_report_url +make_rest_describe_url make_rest_describe_url +make_rest_objects_url make_rest_objects_url +make_rest_record_url make_rest_record_url +make_search_url make_search_url +make_soap_xml_skeleton make_soap_xml_skeleton +make_verbose_httr_message make_verbose_httr_message +map_sf_type_to_r_type map_sf_type_to_r_type +merge_null_to_na merge_null_to_na +message_w_errors_listed message_w_errors_listed +metadata_type_validator metadata_type_validator +parameterized_search_control parameterized_search_control +parse_error_code_and_message parse_error_code_and_message +parse_report_detail_rows parse_report_detail_rows +patched_tempdir patched_tempdir +rDELETE rDELETE +records_list_to_tbl records_list_to_tbl +remove_empty_linked_object_cols remove_empty_linked_object_cols +return_matching_controls return_matching_controls +rforcecom.bulkAction rforcecom.bulkAction +rforcecom.bulkQuery rforcecom.bulkQuery +rforcecom.create rforcecom.create +rforcecom.delete rforcecom.delete +rforcecom.getObjectDescription rforcecom.getObjectDescription +rforcecom.getServerTimestamp rforcecom.getServerTimestamp +rforcecom.login rforcecom.login +rforcecom.query rforcecom.query +rforcecom.retrieve rforcecom.retrieve +rforcecom.search rforcecom.search +rforcecom.update rforcecom.update +rforcecom.upsert rforcecom.upsert +rGET rGET +rPATCH rPATCH +rPOST rPOST +rPUT rPUT +safe_bind_rows safe_bind_rows +salesforcer salesforcer-package +salesforcer_state salesforcer_state +session_id_available session_id_available +set_null_elements_to_na set_null_elements_to_na +set_null_elements_to_na_recursively set_null_elements_to_na_recursively +sf_abort_job_bulk sf_abort_job_bulk +sf_access_token sf_access_token +sf_analytics_notifications_limits sf_analytics_notifications_limits +sf_analytics_notifications_list sf_analytics_notifications_list +sf_analytics_notification_create sf_analytics_notification_create +sf_analytics_notification_delete sf_analytics_notification_delete +sf_analytics_notification_describe sf_analytics_notification_describe +sf_analytics_notification_update sf_analytics_notification_update +sf_auth sf_auth +sf_auth_check sf_auth_check +sf_auth_refresh sf_auth_refresh +sf_batch_details_bulk sf_batch_details_bulk +sf_batch_status_bulk sf_batch_status_bulk +sf_build_cols_spec sf_build_cols_spec +sf_bulk_operation sf_run_bulk_operation +sf_close_job_bulk sf_close_job_bulk +sf_control sf_control +sf_convert_lead sf_convert_lead +sf_copy_dashboard sf_copy_dashboard +sf_copy_report sf_copy_report +sf_create sf_create +sf_create_attachment sf_create_attachment +sf_create_attachment_bulk_v1 sf_create_attachment_bulk_v1 +sf_create_attachment_rest sf_create_attachment_rest +sf_create_attachment_soap sf_create_attachment_soap +sf_create_batches_bulk sf_create_batches_bulk +sf_create_bulk_v1 sf_create_bulk_v1 +sf_create_bulk_v2 sf_create_bulk_v2 +sf_create_job_bulk sf_create_job_bulk +sf_create_job_bulk_v1 sf_create_job_bulk_v1 +sf_create_job_bulk_v2 sf_create_job_bulk_v2 +sf_create_metadata sf_create_metadata +sf_create_report sf_create_report +sf_create_rest sf_create_rest +sf_create_soap sf_create_soap +sf_delete sf_delete +sf_delete_attachment sf_delete_attachment +sf_delete_bulk_v1 sf_delete_bulk_v1 +sf_delete_bulk_v2 sf_delete_bulk_v2 +sf_delete_dashboard sf_delete_dashboard +sf_delete_job_bulk sf_delete_job_bulk +sf_delete_metadata sf_delete_metadata +sf_delete_report sf_delete_report +sf_delete_report_instance sf_delete_report_instance +sf_delete_rest sf_delete_rest +sf_delete_soap sf_delete_soap +sf_describe_dashboard sf_describe_dashboard +sf_describe_dashboard_components sf_describe_dashboard_components +sf_describe_metadata sf_describe_metadata +sf_describe_objects sf_describe_objects +sf_describe_object_fields sf_describe_object_fields +sf_describe_report sf_describe_report +sf_describe_report_type sf_describe_report_type +sf_download_attachment sf_download_attachment +sf_empty_recycle_bin sf_empty_recycle_bin +sf_end_job_bulk sf_end_job_bulk +sf_execute_report sf_execute_report +sf_filter_dashboard_operators_list sf_filter_dashboard_operators_list +sf_filter_dashboard_options_analysis sf_filter_dashboard_options_analysis +sf_find_duplicates sf_find_duplicates +sf_find_duplicates_by_id sf_find_duplicates_by_id +sf_format_date sf_format_date +sf_format_datetime sf_format_datetime +sf_format_time sf_format_time +sf_format_time.AsIs sf_format_time +sf_format_time.character sf_format_time +sf_format_time.data.frame sf_format_time +sf_format_time.Date sf_format_time +sf_format_time.list sf_format_time +sf_format_time.logical sf_format_time +sf_format_time.NULL sf_format_time +sf_format_time.numeric sf_format_time +sf_format_time.POSIXct sf_format_time +sf_format_time.POSIXlt sf_format_time +sf_format_time.POSIXt sf_format_time +sf_get_all_jobs_bulk sf_get_all_jobs_bulk +sf_get_all_query_jobs_bulk sf_get_all_query_jobs_bulk +sf_get_dashboard_data sf_get_dashboard_data +sf_get_dashboard_results sf_get_dashboard_results +sf_get_dashboard_status sf_get_dashboard_status +sf_get_deleted sf_get_deleted +sf_get_job_bulk sf_get_job_bulk +sf_get_job_records_bulk sf_get_job_records_bulk +sf_get_report_instance_results sf_get_report_instance_results +sf_get_updated sf_get_updated +sf_guess_cols sf_guess_cols +sf_input_data_validation sf_input_data_validation +sf_job_batches_bulk sf_job_batches_bulk +sf_list_api_limits sf_list_api_limits +sf_list_dashboards sf_list_dashboards +sf_list_metadata sf_list_metadata +sf_list_objects sf_list_objects +sf_list_reports sf_list_reports +sf_list_report_fields sf_list_report_fields +sf_list_report_filter_operators sf_list_report_filter_operators +sf_list_report_instances sf_list_report_instances +sf_list_report_types sf_list_report_types +sf_list_resources sf_list_resources +sf_list_rest_api_versions sf_list_rest_api_versions +sf_merge sf_merge +sf_query sf_query +sf_query_bulk sf_run_bulk_query +sf_query_bulk_v1 sf_query_bulk_v1 +sf_query_bulk_v2 sf_query_bulk_v2 +sf_query_report sf_query_report +sf_query_result_bulk sf_query_result_bulk +sf_query_result_bulk_v1 sf_query_result_bulk_v1 +sf_query_result_bulk_v2 sf_query_result_bulk_v2 +sf_read_metadata sf_read_metadata +sf_refresh_dashboard sf_refresh_dashboard +sf_rename_metadata sf_rename_metadata +sf_reorder_cols sf_reorder_cols +sf_report_folders_list sf_report_folders_list +sf_report_folder_children sf_report_folder_children +sf_report_folder_create sf_report_folder_create +sf_report_folder_delete sf_report_folder_delete +sf_report_folder_describe sf_report_folder_describe +sf_report_folder_shares_add sf_report_folder_shares_add +sf_report_folder_shares_list sf_report_folder_shares_list +sf_report_folder_shares_update sf_report_folder_shares_update +sf_report_folder_share_delete sf_report_folder_share_delete +sf_report_folder_share_describe sf_report_folder_share_describe +sf_report_folder_share_recipients sf_report_folder_share_recipients +sf_report_folder_share_update sf_report_folder_share_update +sf_report_folder_update sf_report_folder_update +sf_reset_password sf_reset_password +sf_rest_list sf_rest_list +sf_retrieve sf_retrieve +sf_retrieve_metadata sf_retrieve_metadata +sf_retrieve_metadata_check_status sf_retrieve_metadata_check_status +sf_retrieve_rest sf_retrieve_rest +sf_retrieve_soap sf_retrieve_soap +sf_run_bulk_operation sf_run_bulk_operation +sf_run_bulk_query sf_run_bulk_query +sf_run_report sf_run_report +sf_search sf_search +sf_server_timestamp sf_server_timestamp +sf_session_id sf_session_id +sf_set_dashboard_sticky_filter sf_set_dashboard_sticky_filter +sf_set_password sf_set_password +sf_submit_query_bulk sf_submit_query_bulk +sf_undelete sf_undelete +sf_update sf_update +sf_update_attachment sf_update_attachment +sf_update_attachment_bulk_v1 sf_update_attachment_bulk_v1 +sf_update_attachment_rest sf_update_attachment_rest +sf_update_attachment_soap sf_update_attachment_soap +sf_update_bulk_v1 sf_update_bulk_v1 +sf_update_bulk_v2 sf_update_bulk_v2 +sf_update_dashboard sf_update_dashboard +sf_update_metadata sf_update_metadata +sf_update_report sf_update_report +sf_update_rest sf_update_rest +sf_update_soap sf_update_soap +sf_upload_complete_bulk sf_upload_complete_bulk +sf_upsert sf_upsert +sf_upsert_bulk_v1 sf_upsert_bulk_v1 +sf_upsert_bulk_v2 sf_upsert_bulk_v2 +sf_upsert_metadata sf_upsert_metadata +sf_upsert_rest sf_upsert_rest +sf_upsert_soap sf_upsert_soap +sf_user_info sf_user_info +sf_write_csv sf_write_csv +simplify_report_metadata simplify_report_metadata +stop_w_errors_listed stop_w_errors_listed +token_available token_available +unbox_list_elements unbox_list_elements +unbox_list_elements_recursively unbox_list_elements_recursively +unnest_col unnest_col +validate_get_all_jobs_params validate_get_all_jobs_params +valid_metadata_list valid_metadata_list +VERB_n VERB_n +warn_w_errors_listed warn_w_errors_listed +xmlToList2 xmlToList2 +xml_drop_and_unlist xml_drop_and_unlist +xml_drop_and_unlist_recursively xml_drop_and_unlist_recursively +xml_extract_parent_and_child_result xml_extract_parent_and_child_result +xml_nodeset_to_df xml_nodeset_to_df diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/aliases.rds b/revdep/library.noindex/salesforcer/old/salesforcer/help/aliases.rds new file mode 100644 index 00000000..c9c41bd1 Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/help/aliases.rds differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/cloud.png b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/cloud.png new file mode 100644 index 00000000..f3d90f71 Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/cloud.png differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-archived.svg b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-archived.svg new file mode 100644 index 00000000..48f72a6f --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-archived.svg @@ -0,0 +1 @@ + lifecyclelifecyclearchivedarchived \ No newline at end of file diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-defunct.svg b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-defunct.svg new file mode 100644 index 00000000..01452e5f --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-defunct.svg @@ -0,0 +1 @@ +lifecyclelifecycledefunctdefunct \ No newline at end of file diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-deprecated.svg b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-deprecated.svg new file mode 100644 index 00000000..4baaee01 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-deprecated.svg @@ -0,0 +1 @@ +lifecyclelifecycledeprecateddeprecated \ No newline at end of file diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-experimental.svg b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-experimental.svg new file mode 100644 index 00000000..d1d060e9 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-experimental.svg @@ -0,0 +1 @@ +lifecyclelifecycleexperimentalexperimental \ No newline at end of file diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-maturing.svg b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-maturing.svg new file mode 100644 index 00000000..df713101 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-maturing.svg @@ -0,0 +1 @@ +lifecyclelifecyclematuringmaturing \ No newline at end of file diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-questioning.svg b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-questioning.svg new file mode 100644 index 00000000..08ee0c90 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-questioning.svg @@ -0,0 +1 @@ +lifecyclelifecyclequestioningquestioning \ No newline at end of file diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-soft-deprecated.svg b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-soft-deprecated.svg new file mode 100644 index 00000000..9f014fd1 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-soft-deprecated.svg @@ -0,0 +1 @@ +lifecyclelifecyclesoft-deprecatedsoft-deprecated \ No newline at end of file diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-stable.svg b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-stable.svg new file mode 100644 index 00000000..e015dc81 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-stable.svg @@ -0,0 +1 @@ +lifecyclelifecyclestablestable \ No newline at end of file diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-superseded.svg b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-superseded.svg new file mode 100644 index 00000000..75f24f55 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/lifecycle-superseded.svg @@ -0,0 +1 @@ + lifecyclelifecyclesupersededsuperseded \ No newline at end of file diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/logo.png b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/logo.png new file mode 100644 index 00000000..ecf5fa74 Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/logo.png differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/old-logo.png b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/old-logo.png new file mode 100644 index 00000000..9e2ae3be Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/old-logo.png differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/old-salesforcer-hex.png b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/old-salesforcer-hex.png new file mode 100644 index 00000000..2fc28638 Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/old-salesforcer-hex.png differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/old-salesforcer.png b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/old-salesforcer.png new file mode 100644 index 00000000..90772457 Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/old-salesforcer.png differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/salesforcer.png b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/salesforcer.png new file mode 100644 index 00000000..ff56023c Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/help/figures/salesforcer.png differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/paths.rds b/revdep/library.noindex/salesforcer/old/salesforcer/help/paths.rds new file mode 100644 index 00000000..75d296b8 Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/help/paths.rds differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/salesforcer.rdb b/revdep/library.noindex/salesforcer/old/salesforcer/help/salesforcer.rdb new file mode 100644 index 00000000..a3be9d79 Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/help/salesforcer.rdb differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/help/salesforcer.rdx b/revdep/library.noindex/salesforcer/old/salesforcer/help/salesforcer.rdx new file mode 100644 index 00000000..a292c7ef Binary files /dev/null and b/revdep/library.noindex/salesforcer/old/salesforcer/help/salesforcer.rdx differ diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/html/00Index.html b/revdep/library.noindex/salesforcer/old/salesforcer/html/00Index.html new file mode 100644 index 00000000..1f6cb017 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/html/00Index.html @@ -0,0 +1,318 @@ + + +R: An Implementation of 'Salesforce' APIs Using Tidy Principles + + + +
+

An Implementation of 'Salesforce' APIs Using Tidy Principles + +

+
+
+[Up] +[Top] +

Documentation for package ‘salesforcer’ version 1.0.1

+ + + +

Help Pages

+ + +

+C +M +P +R +S +V +

+ + +

-- C --

+ + + + +
collapse_list_with_dupe_namesCollapse Elements in List with Same Name
+ +

-- M --

+ + + + +
metadata_type_validatorMetadata Data Type Validator
+ +

-- P --

+ + + + +
parameterized_search_controlAuxiliary for Controlling Parametrized Searches
+ +

-- R --

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
rforcecom.bulkActionThe 'salesforcer' backwards compatible version of the RForcecom function 'rforcecom.bulkAction'
rforcecom.bulkQueryThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.bulkQuery'
rforcecom.createThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.create'
rforcecom.deleteThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.delete'
rforcecom.getObjectDescriptionThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.getObjectDescription'
rforcecom.getServerTimestampThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.getServerTimestamp'
rforcecom.loginThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.login'
rforcecom.queryThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.query'
rforcecom.retrieveThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.retrieve'
rforcecom.searchThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.search'
rforcecom.updateThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.update'
rforcecom.upsertThe 'salesforcer' backwards compatible version of 'RForcecom::rforcecom.upsert'
+ +

-- S --

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
sf_abort_job_bulkAbort Bulk API Job
sf_analytics_notifications_limitsReturn limits of analytics notifications
sf_analytics_notifications_listList analytics notifications
sf_analytics_notification_createCreate an analytics notification
sf_analytics_notification_deleteDelete an analytics notification
sf_analytics_notification_describeDescribe an analytics notification
sf_analytics_notification_updateUpdate an analytics notification
sf_authLog in to Salesforce
sf_batch_details_bulkReturning the Details of a Batch in a Bulk API Job
sf_batch_status_bulkChecking the Status of a Batch in a Bulk API Job
sf_bulk_operationRun Bulk Operation
sf_close_job_bulkClose Bulk API Job
sf_controlAuxiliary for Controlling Calls to Salesforce APIs
sf_convert_leadConvert Leads
sf_copy_dashboardCopy a dashboard
sf_copy_reportCopy a report
sf_createCreate Records
sf_create_attachmentCreate Attachments
sf_create_batches_bulkAdd Batches to a Bulk API Job
sf_create_job_bulkCreate Bulk API Job
sf_create_metadataCreate Object or Field Metadata in Salesforce
sf_create_reportCreate a report
sf_deleteDelete Records
sf_delete_attachmentDelete Attachments
sf_delete_dashboardDelete a dashboard
sf_delete_job_bulkDelete Bulk API Job
sf_delete_metadataDelete Object or Field Metadata in Salesforce
sf_delete_reportDelete a report
sf_delete_report_instanceDelete a report instance
sf_describe_dashboardDescribe a dashboard
sf_describe_dashboard_componentsDescribe dashboard components
sf_describe_metadataDescribe the Metadata in an Organization
sf_describe_objectsSObject Basic Information
sf_describe_object_fieldsDescribe Object Fields
sf_describe_reportDescribe a report
sf_describe_report_typeDescribe a report type
sf_download_attachmentDownload an Attachment
sf_empty_recycle_binEmpty Recycle Bin
sf_execute_reportExecute a report
sf_filter_dashboard_operators_listList dashboard filter operators
sf_filter_dashboard_options_analysisGet an analysis of the filter options for a dashboard
sf_find_duplicatesFind Duplicate Records
sf_find_duplicates_by_idFind Duplicate Records By Id
sf_get_all_jobs_bulkGet All Bulk API Jobs
sf_get_all_query_jobs_bulkGet All Bulk API Query Jobs
sf_get_dashboard_dataGet dashboard data in a tabular format
sf_get_dashboard_resultsGet the results of an existing dashboard
sf_get_dashboard_statusGet the status of a dashboard
sf_get_deletedGet Deleted Records from a Timeframe
sf_get_job_bulkGet Bulk API Job
sf_get_job_records_bulkReturning the Details of a Bulk API Job
sf_get_report_instance_resultsGet report instance results
sf_get_updatedGet Updated Records from a Timeframe
sf_job_batches_bulkChecking the Status of a Batch in a Bulk API Job
sf_list_api_limitsList the Limits for an API
sf_list_dashboardsList dashboards
sf_list_metadataList All Objects of a Certain Metadata Type in Salesforce
sf_list_objectsList Organization Objects and their Metadata
sf_list_reportsList reports
sf_list_report_fieldsGet a list of report fields
sf_list_report_filter_operatorsList report filter operators
sf_list_report_instancesList report instances
sf_list_report_typesList report types
sf_list_resourcesList the Resources for an API
sf_list_rest_api_versionsList REST API Versions
sf_mergeMerge Records
sf_queryPerform SOQL Query
sf_query_bulkRun bulk query
sf_query_bulk_v1Run Bulk 1.0 query
sf_query_bulk_v2Run Bulk 2.0 query
sf_query_reportGet Report Data without Saving Changes to or Creating a Report
sf_query_result_bulkRetrieve the results of a completed bulk query
sf_query_result_bulk_v1Retrieve the results of a Bulk 1.0 query
sf_query_result_bulk_v2Retrieve the results of a Bulk 2.0 query
sf_read_metadataRead Object or Field Metadata from Salesforce
sf_refresh_dashboardRefresh an existing dashboard
sf_rename_metadataRename Metadata Elements in Salesforce
sf_report_folders_listList report folders
sf_report_folder_childrenGet the subfolders (children) of a report folder
sf_report_folder_createCreate report folder
sf_report_folder_deleteDelete a report folder
sf_report_folder_describeDescribe a report folder
sf_report_folder_shares_addAdd shares to a report folder
sf_report_folder_shares_listList the shares in a report folder
sf_report_folder_shares_updateUpdate the shares for a report folder
sf_report_folder_share_deleteDelete a report folder share
sf_report_folder_share_describeDescribe a report folder share
sf_report_folder_share_recipientsGet report folder share recipients
sf_report_folder_share_updateUpdate a report folder share
sf_report_folder_updateUpdate a report folder
sf_reset_passwordReset User Password
sf_retrieveRetrieve Records By Id
sf_retrieve_metadataMake A Request to Retrieve the Metadata
sf_run_bulk_operationRun Bulk Operation
sf_run_bulk_queryRun bulk query
sf_run_reportGet a report's data in tabular format
sf_searchPerform SOSL Search
sf_server_timestampSalesforce Server Timestamp
sf_set_dashboard_sticky_filterSet a sticky dashboard filter
sf_set_passwordSet User Password
sf_submit_query_bulkSubmit Bulk Query Batch to a Bulk API Job
sf_undeleteUndelete Records
sf_updateUpdate Records
sf_update_attachmentUpdate Attachments
sf_update_dashboardUpdate a dashboard
sf_update_metadataUpdate Object or Field Metadata in Salesforce
sf_update_reportUpdate a report
sf_upload_complete_bulkSignal Upload Complete to Bulk API Job
sf_upsertUpsert Records
sf_upsert_metadataUpsert Object or Field Metadata in Salesforce
sf_user_infoReturn Current User Info
+ +

-- V --

+ + + + +
valid_metadata_listList of Valid Data Types
+
diff --git a/revdep/library.noindex/salesforcer/old/salesforcer/html/R.css b/revdep/library.noindex/salesforcer/old/salesforcer/html/R.css new file mode 100644 index 00000000..c2289098 --- /dev/null +++ b/revdep/library.noindex/salesforcer/old/salesforcer/html/R.css @@ -0,0 +1,130 @@ +@media screen { + .container { + padding-right: 10px; + padding-left: 10px; + margin-right: auto; + margin-left: auto; + max-width: 900px; + } +} + +.rimage img { /* from knitr - for examples and demos */ + width: 96%; + margin-left: 2%; +} + +.katex { font-size: 1.1em; } + +code { + color: inherit; + background: inherit; +} + +body { + line-height: 1.4; + background: white; + color: black; +} + +a:link { + background: white; + color: blue; +} + +a:visited { + background: white; + color: rgb(50%, 0%, 50%); +} + +h1 { + background: white; + color: rgb(55%, 55%, 55%); + font-family: monospace; + font-size: 1.4em; /* x-large; */ + text-align: center; +} + +h2 { + background: white; + color: rgb(40%, 40%, 40%); + font-family: monospace; + font-size: 1.2em; /* large; */ + text-align: center; +} + +h3 { + background: white; + color: rgb(40%, 40%, 40%); + font-family: monospace; + font-size: 1.2em; /* large; */ +} + +h4 { + background: white; + color: rgb(40%, 40%, 40%); + font-family: monospace; + font-style: italic; + font-size: 1.2em; /* large; */ +} + +h5 { + background: white; + color: rgb(40%, 40%, 40%); + font-family: monospace; +} + +h6 { + background: white; + color: rgb(40%, 40%, 40%); + font-family: monospace; + font-style: italic; +} + +img.toplogo { + width: 4em; + vertical-align: middle; +} + +img.arrow { + width: 30px; + height: 30px; + border: 0; +} + +span.acronym { + font-size: small; +} + +span.env { + font-family: monospace; +} + +span.file { + font-family: monospace; +} + +span.option{ + font-family: monospace; +} + +span.pkg { + font-weight: bold; +} + +span.samp{ + font-family: monospace; +} + +div.vignettes a:hover { + background: rgb(85%, 85%, 85%); +} + +tr { + vertical-align: top; +} + +span.rlang { + font-family: Courier New, Courier; + color: #666666; +} +