diff --git a/examples/cpp/sync/CMakeLists.txt b/examples/cpp/sync/CMakeLists.txt index 4f2bc0b812..df14bd45ff 100644 --- a/examples/cpp/sync/CMakeLists.txt +++ b/examples/cpp/sync/CMakeLists.txt @@ -16,8 +16,12 @@ FetchContent_Declare( GIT_REPOSITORY https://github.com/realm/realm-cpp.git GIT_TAG 8eba9728ea535a6cd78beaef37ed6d22b73fe889 ) +FetchContent_Declare( + json + URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz +) -FetchContent_MakeAvailable(Catch2 cpprealm) +FetchContent_MakeAvailable(Catch2 cpprealm json) add_executable(examples-sync app.cpp @@ -32,3 +36,4 @@ add_executable(examples-sync target_link_libraries(examples-sync PRIVATE Catch2::Catch2WithMain) target_link_libraries(examples-sync PRIVATE cpprealm) +target_link_libraries(examples-sync PRIVATE nlohmann_json::nlohmann_json) diff --git a/examples/cpp/sync/authentication.cpp b/examples/cpp/sync/authentication.cpp index 0b14ee3d93..630103f48c 100644 --- a/examples/cpp/sync/authentication.cpp +++ b/examples/cpp/sync/authentication.cpp @@ -53,24 +53,22 @@ TEST_CASE("create and log in an anonymous user", "[realm][sync]") { REQUIRE(user.access_token().empty()); } -// TODO: Figure out how to do this properly in the updated SDK -// TEST_CASE("test custom function authentication", "[realm][sync]") { -// // :snippet-start: custom-function -// // Custom function authentication takes a BSON Document with parameters. -// // The parameter details vary depending on how you define your custom -// authentication function. realm::bson::BsonDocument params = {{ -// "username", "bob" }}; - -// auto appConfig = realm::App::configuration(); -// appConfig.app_id = APP_ID; -// auto app = realm::App(appConfig); - -// auto user = app.login(realm::App::credentials::function(params)).get(); -// // :snippet-end: -// REQUIRE(!user.access_token().empty()); -// user.log_out().get(); -// REQUIRE(user.access_token().empty()); -// } +TEST_CASE("test custom function authentication", "[realm][sync]") { + // :snippet-start: custom-function + auto appConfig = realm::App::configuration(); + appConfig.app_id = APP_ID; + auto app = realm::App(appConfig); + + /* Custom function authentication takes a string parameters argument. + The parameter details vary depending on how you define your custom + authentication function. */ + std::string params = "{\"username\": \"bob\"}"; + auto user = app.login(realm::App::credentials::function(params)).get(); + // :snippet-end: + REQUIRE(!user.access_token().empty()); + user.log_out().get(); + REQUIRE(user.access_token().empty()); +} TEST_CASE("test get user access token", "[realm][sync]") { auto appConfig = realm::App::configuration(); diff --git a/examples/cpp/sync/call-function.cpp b/examples/cpp/sync/call-function.cpp index f8207c8515..9cf119199c 100644 --- a/examples/cpp/sync/call-function.cpp +++ b/examples/cpp/sync/call-function.cpp @@ -5,15 +5,6 @@ static const std::string APP_ID = "cpp-tester-uliix"; -// This test is currently commented out because the SDK has removed the -// exposed Core headers that gave it access to a BSON library. -// See PR https://github.com/realm/realm-cpp/pull/123/ -// Per Lee, a separate project will create a C++ SDK BSON library, but in -// the meantime, I'll need to use some other library to make this test work. -// I need to figure out how to create BSON strings in C++ and pass them -// instead of using realm::bson::Bson for the params. -// TODO: Figure out what library to use and how to make this test/example work. -#if 0 TEST_CASE("call a function", "[realm][sync]") { // :snippet-start: call-a-function // Connect to an App Services App and authenticate a user @@ -25,24 +16,21 @@ TEST_CASE("call a function", "[realm][sync]") { auto user = app.login(realm::App::credentials::anonymous()).get(); auto sync_config = user.flexible_sync_configuration(); - // If a function takes arguments, pass them as BSON - auto arg1 = realm::bson::Bson("john.smith"); - auto arg2 = realm::bson::Bson("@companyemail.com"); + // If the function takes arguments, pass them as a string array. + // Any quotes within the array must be escaped. + auto argArray = "[\"john.smith\", \"@companyemail.com\"]"; // Call an App Services function as the logged-in user - auto result = user.call_function("concatenate", {arg1, arg2}).get(); + auto result = user.call_function("concatenate", argArray).get(); // Verify that the result has a value CHECK(result); - auto bsonResult = result.value(); + auto functionResult = result.value(); - // Translate the BSON result back to a string - auto resultString = std::string(bsonResult); // Prints "Calling the concatenate function returned - // john.smith@companyemail.com." - std::cout << "Calling the concatenate function returned " << resultString + // "john.smith@companyemail.com"." + std::cout << "Calling the concatenate function returned " << functionResult << ".\n"; // :snippet-end: - REQUIRE(resultString == "john.smith@companyemail.com"); + REQUIRE(functionResult == "\"john.smith@companyemail.com\""); } -#endif \ No newline at end of file diff --git a/examples/cpp/sync/custom-user-data.cpp b/examples/cpp/sync/custom-user-data.cpp index 3d760a9e51..77010e5bae 100644 --- a/examples/cpp/sync/custom-user-data.cpp +++ b/examples/cpp/sync/custom-user-data.cpp @@ -1,55 +1,62 @@ #include #include #include +#include static const std::string APP_ID = "cpp-tester-uliix"; -// This test is currently commented out because the SDK has removed the -// exposed Core headers that gave it access to a BSON library. -// See PR https://github.com/realm/realm-cpp/pull/123/ -// Per Lee, a separate project will create a C++ SDK BSON library, but in -// the meantime, I'll need to use some other library to make this test work. -// I need to figure out how to create BSON strings in C++ and pass them -// instead of using realm::bson::Bson for the params. -// TODO: Figure out what library to use and how to make this test/example work. -#if 0 -TEST_CASE("custom user data", "[realm][sync]") -{ - auto appConfig = realm::App::configuration(); - appConfig.app_id = APP_ID; - auto app = realm::App(appConfig); - - // :snippet-start: create - auto user = app.login(realm::App::credentials::anonymous()).get(); - - // Functions take an argument of BsonArray, so initialize the custom data as a BsonDocument - auto customDataBson = realm::bson::BsonDocument({{"userId", user.identifier()}, {"favoriteColor", "gold"}}); - - // Call an Atlas Function to insert custom data for the user - auto result = user.call_function("updateCustomUserData", { customDataBson }).get(); - // :snippet-end: - CHECK(result); - - // :snippet-start: read - // Custom user data could be stale, so refresh it before reading it - user.refresh_custom_user_data().get(); - CHECK((*user.custom_data())["favoriteColor"] == "gold"); - // :snippet-end: - - // :snippet-start: update - // Functions take an argument of BsonArray, so initialize the custom data as a BsonDocument - auto updatedDataBson = realm::bson::BsonDocument({{"userId", user.identifier()}, { "favoriteColor", "black" }}); - - // Call an Atlas Function to update custom data for the user - auto updateResult = user.call_function("updateCustomUserData", { updatedDataBson }).get(); - - // Refresh the custom user data before reading it to verify it succeeded - user.refresh_custom_user_data().get(); - CHECK((*user.custom_data())["favoriteColor"] == "black"); - // :snippet-end: - // :snippet-start: delete - auto deleteResult = user.call_function("deleteCustomUserData", {}).get(); - // :snippet-end: - CHECK(deleteResult); +TEST_CASE("custom user data", "[realm][sync]") { + auto appConfig = realm::App::configuration(); + appConfig.app_id = APP_ID; + auto app = realm::App(appConfig); + + // :snippet-start: create + auto user = app.login(realm::App::credentials::anonymous()).get(); + + // Functions take a string argument. Any quotes within the array must be + // escaped. + auto customData = + "[{\"userId\":\"" + user.identifier() + "\",\"favoriteColor\":\"gold\"}]"; + + // Call an Atlas Function to insert custom data for the user + auto result = user.call_function("updateCustomUserData", customData).get(); + // :snippet-end: + CHECK(result); + + // :snippet-start: read + // Custom user data could be stale, so refresh it before reading it + user.refresh_custom_user_data().get(); + auto userData = user.custom_data().value(); + + /* Parse the string custom data to use it more easily in your code. + In this example, we're using the nlohmann/json library, but use whatever + works with your application's constraints. */ + auto userDataObject = nlohmann::json::parse(userData); + CHECK(userDataObject["favoriteColor"] == "gold"); + // :snippet-end: + + // :snippet-start: update + // Functions take a string argument. Any quotes within the array must be + // escaped. + auto updatedData = "[{\"userId\":\"" + user.identifier() + + "\",\"favoriteColor\":\"black\"}]"; + + // Call an Atlas Function to update custom data for the user + auto updateResult = + user.call_function("updateCustomUserData", updatedData).get(); + + // Refresh the custom user data before reading it to verify it succeeded + user.refresh_custom_user_data().get(); + auto updatedUserData = user.custom_data().value(); + + /* Parse the string custom data to use it more easily in your code. + In this example, we're using the nlohmann/json library, but use whatever + works with your application's constraints. */ + auto updatedUserDataObject = nlohmann::json::parse(updatedUserData); + CHECK(updatedUserDataObject["favoriteColor"] == "black"); + // :snippet-end: + // :snippet-start: delete + auto deleteResult = user.call_function("deleteCustomUserData", "[]").get(); + // :snippet-end: + CHECK(deleteResult); } -#endif \ No newline at end of file diff --git a/source/examples/generated/cpp/authentication.snippet.custom-function.cpp b/source/examples/generated/cpp/authentication.snippet.custom-function.cpp index 061c67d2ae..970fe3d19b 100644 --- a/source/examples/generated/cpp/authentication.snippet.custom-function.cpp +++ b/source/examples/generated/cpp/authentication.snippet.custom-function.cpp @@ -1,10 +1,9 @@ -// // Custom function authentication takes a BSON Document with parameters. -// // The parameter details vary depending on how you define your custom -// authentication function. realm::bson::BsonDocument params = {{ -// "username", "bob" }}; +auto appConfig = realm::App::configuration(); +appConfig.app_id = APP_ID; +auto app = realm::App(appConfig); -// auto appConfig = realm::App::configuration(); -// appConfig.app_id = APP_ID; -// auto app = realm::App(appConfig); - -// auto user = app.login(realm::App::credentials::function(params)).get(); +/* Custom function authentication takes a string parameters argument. +The parameter details vary depending on how you define your custom +authentication function. */ +std::string params = "{\"username\": \"bob\"}"; +auto user = app.login(realm::App::credentials::function(params)).get(); diff --git a/source/examples/generated/cpp/call-function.snippet.call-a-function.cpp b/source/examples/generated/cpp/call-function.snippet.call-a-function.cpp index 4a8b2b4a4b..f222b8ac91 100644 --- a/source/examples/generated/cpp/call-function.snippet.call-a-function.cpp +++ b/source/examples/generated/cpp/call-function.snippet.call-a-function.cpp @@ -5,20 +5,18 @@ auto app = realm::App(appConfig); auto user = app.login(realm::App::credentials::anonymous()).get(); auto sync_config = user.flexible_sync_configuration(); -// If a function takes arguments, pass them as BSON -auto arg1 = realm::bson::Bson("john.smith"); -auto arg2 = realm::bson::Bson("@companyemail.com"); +// If the function takes arguments, pass them as a string array. +// Any quotes within the array must be escaped. +auto argArray = "[\"john.smith\", \"@companyemail.com\"]"; // Call an App Services function as the logged-in user -auto result = user.call_function("concatenate", {arg1, arg2}).get(); +auto result = user.call_function("concatenate", argArray).get(); // Verify that the result has a value CHECK(result); -auto bsonResult = result.value(); +auto functionResult = result.value(); -// Translate the BSON result back to a string -auto resultString = std::string(bsonResult); // Prints "Calling the concatenate function returned -// john.smith@companyemail.com." -std::cout << "Calling the concatenate function returned " << resultString +// "john.smith@companyemail.com"." +std::cout << "Calling the concatenate function returned " << functionResult << ".\n"; diff --git a/source/examples/generated/cpp/custom-user-data.snippet.create.cpp b/source/examples/generated/cpp/custom-user-data.snippet.create.cpp index 2e97409281..3e7d4f609f 100644 --- a/source/examples/generated/cpp/custom-user-data.snippet.create.cpp +++ b/source/examples/generated/cpp/custom-user-data.snippet.create.cpp @@ -1,7 +1,9 @@ auto user = app.login(realm::App::credentials::anonymous()).get(); -// Functions take an argument of BsonArray, so initialize the custom data as a BsonDocument -auto customDataBson = realm::bson::BsonDocument({{"userId", user.identifier()}, {"favoriteColor", "gold"}}); +// Functions take a string argument. Any quotes within the array must be +// escaped. +auto customData = + "[{\"userId\":\"" + user.identifier() + "\",\"favoriteColor\":\"gold\"}]"; // Call an Atlas Function to insert custom data for the user -auto result = user.call_function("updateCustomUserData", { customDataBson }).get(); +auto result = user.call_function("updateCustomUserData", customData).get(); diff --git a/source/examples/generated/cpp/custom-user-data.snippet.delete.cpp b/source/examples/generated/cpp/custom-user-data.snippet.delete.cpp index f17cf6d28a..d05981a24e 100644 --- a/source/examples/generated/cpp/custom-user-data.snippet.delete.cpp +++ b/source/examples/generated/cpp/custom-user-data.snippet.delete.cpp @@ -1 +1 @@ -auto deleteResult = user.call_function("deleteCustomUserData", {}).get(); +auto deleteResult = user.call_function("deleteCustomUserData", "[]").get(); diff --git a/source/examples/generated/cpp/custom-user-data.snippet.read.cpp b/source/examples/generated/cpp/custom-user-data.snippet.read.cpp index b146636f4e..21d6eeb614 100644 --- a/source/examples/generated/cpp/custom-user-data.snippet.read.cpp +++ b/source/examples/generated/cpp/custom-user-data.snippet.read.cpp @@ -1,3 +1,9 @@ // Custom user data could be stale, so refresh it before reading it user.refresh_custom_user_data().get(); -CHECK((*user.custom_data())["favoriteColor"] == "gold"); +auto userData = user.custom_data().value(); + +/* Parse the string custom data to use it more easily in your code. + In this example, we're using the nlohmann/json library, but use whatever + works with your application's constraints. */ +auto userDataObject = nlohmann::json::parse(userData); +CHECK(userDataObject["favoriteColor"] == "gold"); diff --git a/source/examples/generated/cpp/custom-user-data.snippet.update.cpp b/source/examples/generated/cpp/custom-user-data.snippet.update.cpp index ba15c9aa94..1f1bf34d8e 100644 --- a/source/examples/generated/cpp/custom-user-data.snippet.update.cpp +++ b/source/examples/generated/cpp/custom-user-data.snippet.update.cpp @@ -1,9 +1,18 @@ -// Functions take an argument of BsonArray, so initialize the custom data as a BsonDocument -auto updatedDataBson = realm::bson::BsonDocument({{"userId", user.identifier()}, { "favoriteColor", "black" }}); +// Functions take a string argument. Any quotes within the array must be +// escaped. +auto updatedData = "[{\"userId\":\"" + user.identifier() + + "\",\"favoriteColor\":\"black\"}]"; // Call an Atlas Function to update custom data for the user -auto updateResult = user.call_function("updateCustomUserData", { updatedDataBson }).get(); +auto updateResult = + user.call_function("updateCustomUserData", updatedData).get(); // Refresh the custom user data before reading it to verify it succeeded user.refresh_custom_user_data().get(); -CHECK((*user.custom_data())["favoriteColor"] == "black"); +auto updatedUserData = user.custom_data().value(); + +/* Parse the string custom data to use it more easily in your code. + In this example, we're using the nlohmann/json library, but use whatever + works with your application's constraints. */ +auto updatedUserDataObject = nlohmann::json::parse(updatedUserData); +CHECK(updatedUserDataObject["favoriteColor"] == "black"); diff --git a/source/sdk/cpp/app-services/call-a-function.txt b/source/sdk/cpp/app-services/call-a-function.txt index 6d8f7b2342..ce7089a02d 100644 --- a/source/sdk/cpp/app-services/call-a-function.txt +++ b/source/sdk/cpp/app-services/call-a-function.txt @@ -39,11 +39,10 @@ To execute a function from the C++ SDK, use the :cpp-sdk:`call_function() ` member function on the ``user`` object. Pass in the name of the function as a string for the first parameter. This function takes two arguments, -which we provide as a ``BsonArray`` of arguments: +which we provide as a string array of arguments: .. literalinclude:: /examples/generated/cpp/call-function.snippet.call-a-function.cpp :language: cpp -The callback can provide an optional BSON result, or an optional error. -In the example above, we check that the result has a value, and then cast -it back to a string. +The callback can provide an optional string result, or an optional error. +In the example above, we check that the result has a value.