Skip to content

Commit

Permalink
feat: add remaining SDK instructions (#164)
Browse files Browse the repository at this point in the history
  • Loading branch information
k3llymariee authored Apr 11, 2024
1 parent c428bbf commit 284669d
Show file tree
Hide file tree
Showing 26 changed files with 1,753 additions and 31 deletions.
51 changes: 25 additions & 26 deletions internal/quickstart/choose_sdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,35 +108,34 @@ func (s sdkDetail) FilterValue() string { return "" }

var SDKs = []sdkDetail{
{canonicalName: "react", displayName: "React", kind: clientSideSDK, hasInstructions: true},
{canonicalName: "node-server", displayName: "Node.js (server-side)", kind: serverSideSDK},
{canonicalName: "node-server", displayName: "Node.js (server-side)", kind: serverSideSDK, hasInstructions: true},
{canonicalName: "python", displayName: "Python", kind: serverSideSDK, hasInstructions: true},
{canonicalName: "java", displayName: "Java", kind: serverSideSDK},
{canonicalName: "dotnet-server", displayName: ".NET (server-side)", kind: serverSideSDK},
{canonicalName: "js", displayName: "JavaScript", kind: clientSideSDK},
{canonicalName: "java", displayName: "Java", kind: serverSideSDK, hasInstructions: true},
{canonicalName: "dotnet-server", displayName: ".NET (server-side)", kind: serverSideSDK, hasInstructions: true},
{canonicalName: "js", displayName: "JavaScript", kind: clientSideSDK, hasInstructions: true},
{
canonicalName: "vue",
displayName: "Vue",
kind: clientSideSDK,
url: "https://raw.githubusercontent.com/launchdarkly/vue-client-sdk/main/example/README.md",
canonicalName: "vue",
displayName: "Vue",
kind: clientSideSDK,
url: "https://raw.githubusercontent.com/launchdarkly/vue-client-sdk/main/example/README.md",
hasInstructions: true,
},
{canonicalName: "ios-swift", displayName: "iOS", kind: mobileSDK},
{canonicalName: "go", displayName: "Go", kind: serverSideSDK},
{canonicalName: "android", displayName: "Android", kind: mobileSDK},
{canonicalName: "react-native", displayName: "React Native", kind: mobileSDK},
{canonicalName: "ruby", displayName: "Ruby", kind: serverSideSDK},
{canonicalName: "flutter", displayName: "Flutter", kind: mobileSDK},
{canonicalName: "dotnet-client", displayName: ".NET (client-side)", kind: clientSideSDK},
{canonicalName: "erlang", displayName: "Erlang", kind: serverSideSDK},
{canonicalName: "rust", displayName: "Rust", kind: serverSideSDK},
{canonicalName: "electron", displayName: "Electron", kind: clientSideSDK},
{canonicalName: "c-client", displayName: "C/C++ (client-side)", kind: clientSideSDK},
{canonicalName: "roku", displayName: "Roku", kind: clientSideSDK},
{canonicalName: "node-client", displayName: "Node.js (client-side)", kind: clientSideSDK},
{canonicalName: "c-server", displayName: "C/C++ (server-side)", kind: serverSideSDK},
{canonicalName: "lua-server", displayName: "Lua", kind: serverSideSDK},
{canonicalName: "haskell-server", displayName: "Haskell", kind: serverSideSDK},
{canonicalName: "apex-server", displayName: "Apex", kind: serverSideSDK},
{canonicalName: "php", displayName: "PHP", kind: serverSideSDK},
{canonicalName: "ios-swift", displayName: "iOS", kind: mobileSDK, hasInstructions: true},
{canonicalName: "go", displayName: "Go", kind: serverSideSDK, hasInstructions: true},
{canonicalName: "android", displayName: "Android", kind: mobileSDK, hasInstructions: true},
{canonicalName: "react-native", displayName: "React Native", kind: mobileSDK, hasInstructions: true},
{canonicalName: "ruby", displayName: "Ruby", kind: serverSideSDK, hasInstructions: true},
{canonicalName: "flutter", displayName: "Flutter", kind: mobileSDK, hasInstructions: true},
{canonicalName: "dotnet-client", displayName: ".NET (client-side)", kind: clientSideSDK, hasInstructions: true},
{canonicalName: "erlang", displayName: "Erlang", kind: serverSideSDK, hasInstructions: true},
{canonicalName: "rust", displayName: "Rust", kind: serverSideSDK, hasInstructions: true},
{canonicalName: "c-client", displayName: "C/C++ (client-side)", kind: clientSideSDK, hasInstructions: true},
{canonicalName: "roku", displayName: "Roku", kind: clientSideSDK, hasInstructions: true},
{canonicalName: "node-client", displayName: "Node.js (client-side)", kind: clientSideSDK, hasInstructions: true},
{canonicalName: "c-server", displayName: "C/C++ (server-side)", kind: serverSideSDK, hasInstructions: true},
{canonicalName: "lua-server", displayName: "Lua", kind: serverSideSDK, hasInstructions: true},
{canonicalName: "haskell-server", displayName: "Haskell", kind: serverSideSDK, hasInstructions: true},
{canonicalName: "php", displayName: "PHP", kind: serverSideSDK, hasInstructions: true},
}

func sdksToItems() []list.Item {
Expand Down
10 changes: 8 additions & 2 deletions internal/quickstart/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ func showToggleFlag() tea.Cmd {
}

type fetchedEnvMsg struct {
clientSideID string
clientSideId string
mobileKey string
sdkKey string
}

Expand All @@ -175,13 +176,18 @@ func fetchEnv(
var resp struct {
SDKKey string `json:"apiKey"`
ClientSideId string `json:"_id"`
MobileKey string `json:"mobileKey"`
}
err = json.Unmarshal(response, &resp)
if err != nil {
return errMsg{err: err}
}

return fetchedEnvMsg{clientSideID: resp.ClientSideId, sdkKey: resp.SDKKey}
return fetchedEnvMsg{
clientSideId: resp.ClientSideId,
sdkKey: resp.SDKKey,
mobileKey: resp.MobileKey,
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion internal/quickstart/show_sdk_instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func (m showSDKInstructionsModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.instructions = sdks.ReplaceFlagKey(string(msg.instructions), m.flagKey)
case fetchedEnvMsg:
m.sdkKey = msg.sdkKey
m.instructions = sdks.ReplaceSDKKeys(string(m.instructions), msg.sdkKey, msg.clientSideID)
m.instructions = sdks.ReplaceSDKKeys(string(m.instructions), msg.sdkKey, msg.clientSideId, msg.mobileKey)
md, err := m.renderMarkdown()
if err != nil {
return m, sendErrMsg(err)
Expand Down
124 changes: 124 additions & 0 deletions internal/sdks/sdk_instructions/android.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# Installation steps
If you want to skip ahead, the final code is available in our [GitHub repository](https://github.com/launchdarkly/hello-android).

1. Open Android Studio and create a new project named `hello-android` with an empty activity.

2. Next, add the LaunchDarkly SDK as a dependency in the `app/build.gradle` file:
```java
dependencies {
...
implementation("com.launchdarkly:launchdarkly-android-client-sdk:5.1.1")
}
```

3. Open the file `MainActivity.kt` and add the following code:
```java
import com.launchdarkly.sdk.android.LDClient

class MainActivity : AppCompatActivity() {

// Set BOOLEAN_FLAG_KEY to the boolean feature flag you want to evaluate.
val BOOLEAN_FLAG_KEY = "my-flag-key"

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val textView : TextView = findViewById(R.id.textview)

val client = LDClient.get()

// to get the variation the SDK has cached
textView.text = getString(
R.string.flag_evaluated,
BOOLEAN_FLAG_KEY,
client.boolVariation(BOOLEAN_FLAG_KEY, false).toString()
)

// to register a listener to get updates in real time
client.registerFeatureFlagListener(BOOLEAN_FLAG_KEY) {
textView.text = getString(
R.string.flag_evaluated,
BOOLEAN_FLAG_KEY,
client.boolVariation(BOOLEAN_FLAG_KEY, false).toString()
)
}

// This call ensures all evaluation events show up immediately for this demo. Otherwise, the
// SDK sends them at some point in the future. You don't need to call this in production,
// because the SDK handles them automatically at an interval. The interval is customizable.
client.flush()
}
}
```

4. Add a `TextView` to your `layout/activity_main.xml` with id `textview`:
```xml
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
... />
```

5. Create `MainApplication.kt` and add the following code:
```java
import com.launchdarkly.sdk.ContextKind
import com.launchdarkly.sdk.LDContext
import com.launchdarkly.sdk.android.LDClient
import com.launchdarkly.sdk.android.LDConfig

class MainApplication : Application() {

companion object {

// Set LAUNCHDARKLY_MOBILE_KEY to your LaunchDarkly SDK mobile key.
const val LAUNCHDARKLY_MOBILE_KEY = "myMobileKey"
}

override fun onCreate() {
super.onCreate()

val ldConfig = LDConfig.Builder(AutoEnvAttributes.Enabled)
.mobileKey(LAUNCHDARKLY_MOBILE_KEY)
.build()

// Set up the context properties. This context should appear on your LaunchDarkly contexts
// list soon after you run the demo.
val context = if (isUserLoggedIn()) {
LDContext.builder(ContextKind.DEFAULT, getUserKey())
.name(getUserName())
.build()
} else {
LDContext.builder(ContextKind.DEFAULT, "example-user-key")
.anonymous(true)
.build()
}

LDClient.init(this@MainApplication, ldConfig, context)
}

private fun isUserLoggedIn(): Boolean = false

private fun getUserKey(): String = "user-key-123abc"

private fun getUserName(): String = "Sandy"

}
```

6. Register the `MainApplication` class in the `AndroidManifest.xml`:
```xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<application
android:name=".MainApplication"
...
...
</application>
</manifest>
```

Now that your application is ready, run the through the Android Emulator or on a real device to see what value we get. You should see:

`Feature flag my-flag-key is FALSE for this context`
130 changes: 130 additions & 0 deletions internal/sdks/sdk_instructions/c-client.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Installation steps
If you want to skip ahead, the final code is available in our [GitHub repository](https://github.com/launchdarkly/cpp-sdks/tree/main/examples/hello-cpp-client).

1. First, ensure the required build dependencies are installed:
- C++ 17
- CMake 3.19 or higher
- A build system such as make, Ninja, or MSVC
- Boost 1.81 or higher
- OpenSSL

2. Create a new project directory:
```shell
mkdir hello-cpp-client && cd hello-cpp-client
```

3. Clone the C++ SDK inside the directory you created above using git:
```shell
git clone https://github.com/launchdarkly/cpp-sdks.git
```

4. Create a file named `main.cpp` and add the following code:
```cpp
#include <launchdarkly/client_side/client.hpp>
#include <launchdarkly/context_builder.hpp>

#include <cstring>
#include <iostream>

// Set INIT_TIMEOUT_MILLISECONDS to the amount of time you will wait for
// the client to become initialized.
#define INIT_TIMEOUT_MILLISECONDS 3000

using namespace launchdarkly;
using namespace launchdarkly::client_side;

int main() {

auto config = ConfigBuilder("myMobileKey").Build();
if (!config) {
std::cout << "error: config is invalid: " << config.error() << std::endl;
return 1;
}

auto context =
ContextBuilder().Kind("user", "example-user-key").Name("Sandy").Build();

auto client = Client(std::move(*config), std::move(context));

auto start_result = client.StartAsync();

if (auto const status = start_result.wait_for(
std::chrono::milliseconds(INIT_TIMEOUT_MILLISECONDS));
status == std::future_status::ready) {
if (start_result.get()) {
std::cout << "*** SDK successfully initialized!" << std::endl;
} else {
std::cout << "*** SDK failed to initialize" << std::endl;
return 1;
}
} else {
std::cout << "*** SDK initialization didn't complete in "
<< INIT_TIMEOUT_MILLISECONDS << "ms" << std::endl;
return 1;
}

bool const flag_value = client.BoolVariation("my-flag-key", false);

std::cout << "*** Feature flag 'my-flag-key' is "
<< (flag_value ? "true" : "false") << " for this user" << std::endl;

return 0;
}
```
5. Create a `CMakeLists.txt` file and the following content:
```txt
cmake_minimum_required(VERSION 3.19)
project(
CPPClientQuickstart
VERSION 0.1
DESCRIPTION "LaunchDarkly CPP Client-side SDK Quickstart"
LANGUAGES CXX
)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
add_subdirectory(cpp-sdks)
add_executable(cpp-client-quickstart main.cpp)
target_link_libraries(cpp-client-quickstart
PRIVATE
launchdarkly::client
Threads::Threads
)
```

6. Create a build directory:
```shell
mkdir build && cd build
```

7. Configure the SDK with your chosen build system. Examples:
**Make**
```shell
cmake -G"Unix Makefiles" -DBUILD_TESTING=OFF ..
```
**Ninja**
```shell
cmake -G"Ninja" -DBUILD_TESTING=OFF ..
```
**Microsoft Visual Studio**
```shell
cmake -G"Visual Studio 17 2022" -DBUILD_TESTING=OFF ..
```

8. Build the SDK:
```shell
cmake --build .
```

Now that your application is ready, run the application to see what value we get.
```shell
./cpp-client-quickstart
```

You should see:
`Feature flag my-flag-key is false`
Loading

0 comments on commit 284669d

Please sign in to comment.