Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
"packages/sdk/combined-browser",
"packages/sdk/shopify-oxygen",
"packages/sdk/shopify-oxygen/contract-tests",
"packages/sdk/shopify-oxygen/example"
"packages/sdk/shopify-oxygen/example",
"packages/sdk/browser/example"
],
"private": true,
"scripts": {
Expand Down
44 changes: 44 additions & 0 deletions packages/sdk/browser/example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# LaunchDarkly sample javascript application

# ⛔️⛔️⛔️⛔️

> [!CAUTION]
> This example is created against a non-production SDK which means things may change and this example might
> not work while this message is visible.

# ☝️☝️☝️☝️☝️☝️

We've built a simple browser application that demonstrates how this LaunchDarkly SDK works.

Below, you'll find the build procedure. For more comprehensive instructions, you can visit your [Quickstart page](https://app.launchdarkly.com/quickstart#/) or
the [{name of SDK} reference guide](https://docs.launchdarkly.com/sdk/client-side/javascript).

## Build instructions

Modify [app.ts](./src/app.ts) with the following changes:

1. Set the value of the {`clientSideID`} variable in {file name} to your client-side ID:
```typescript
const clientSideID = "my-client-side-id";
```

2. If there is an existing boolean feature flag in your LaunchDarkly project that
you want to evaluate, set `flagKey` to the flag key:
```typescript
const flagKey = "my-flag-key";
```

3. If you haven't already, install and build the project:
```bash
yarn && yarn build
```

4. On the command line, run `yarn start`
```bash
yarn start
```
> [!NOTE]
> The `yarn start` script simply runs `open index.html`. If that is not working for you,
> you can open the `index.html` file in a browser for the same results.

The application will run continuously and react to the flag changes in LaunchDarkly.
11 changes: 11 additions & 0 deletions packages/sdk/browser/example/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
body {
margin: 0;
background: #373841;
color: white;
font-family:
-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
}
11 changes: 11 additions & 0 deletions packages/sdk/browser/example/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge;chrome=1">
<title>LaunchDarkly tutorial</title>
<script src="./dist/app.js" defer></script>
<link rel="stylesheet" href="./index.css">
</head>
<body></body>
</html>
27 changes: 27 additions & 0 deletions packages/sdk/browser/example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "@launchdarkly/browser-example",
"version": "0.0.0",
"prviate": true,
"description": "LaunchDarkly example for JavaScript Browser SDK",
"homepage": "https://github.com/launchdarkly/js-core/tree/main/packages/sdk/browser/example",
"repository": {
"type": "git",
"url": "https://github.com/launchdarkly/js-core.git"
},
"license": "Apache-2.0",
"packageManager": "[email protected]",
"type": "module",
"scripts": {
"start": "open index.html",
"clean": "rm -rf dist dist-static",
"build": "npm run clean && tsdown"
},
"dependencies": {
"@launchdarkly/js-client-sdk": "workspace:^",
"express": "^5.1.0"
},
"devDependencies": {
"tsdown": "^0.17.0-beta.4",
"typescript": "^5.9.3"
}
}
42 changes: 42 additions & 0 deletions packages/sdk/browser/example/src/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { initialize } from '@launchdarkly/js-client-sdk';

// Set clientSideID to your LaunchDarkly client-side ID
const clientSideID = '';

// Set flagKey to the feature flag key you want to evaluate
const flagKey = 'sample-feature';

// Set up the evaluation context. This context should appear on your
// LaunchDarkly contexts dashboard soon after you run the demo.
const context = {
kind: 'user',
key: 'example-user-key',
name: 'Sandy',
};

const div = document.createElement('div');
document.body.appendChild(div);
div.appendChild(document.createTextNode('Initializing...'));

const ldclient = initialize(clientSideID);

function render() {
const flagValue = ldclient.variation(flagKey, false);
const label = `The ${flagKey} feature flag evaluates to ${flagValue}.`;
document.body.style.background = flagValue ? '#00844B' : '#373841';
div.replaceChild(document.createTextNode(label), div.firstChild as Node);
}

ldclient.identify(context).then(() => {
ldclient.on('initialized', () => {
div.replaceChild(
document.createTextNode('SDK successfully initialized!'),
div.firstChild as Node,
);
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Identify error handling uses catch but promise never rejects

The .catch() handler on ldclient.identify(context) will never execute because the SDK's identify() method returns a promise that doesn't reject on errors. Per the SDK's documented behavior, the promise "will not be rejected" - instead, errors are returned as an LDIdentifyResult object with status: 'error'. To properly handle identify failures, the code would need to use .then() and check result.status for error conditions.

Fix in Cursor Fix in Web

ldclient.on('failed', () => {
div.replaceChild(document.createTextNode('SDK failed to initialize'), div.firstChild as Node);
});
ldclient.on('ready', render);
ldclient.on('change', render);
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: UI remains stuck when identify succeeds without flags

The identify call only has a .catch() handler without a .then() for the success case. The UI update relies entirely on the change event firing. However, the SDK only emits a change event when flag values differ from previous values. If no flags are configured in the LaunchDarkly project (or the server returns empty flags), identify succeeds but no change event fires, leaving the UI permanently stuck on "Initializing...". Adding a .then() handler that calls render() would ensure the UI updates after successful identification regardless of whether flags exist.

Fix in Cursor Fix in Web

22 changes: 22 additions & 0 deletions packages/sdk/browser/example/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"declaration": true,
"declarationMap": true,
"lib": ["ES2017", "dom"],
"module": "ESNext",
"moduleResolution": "node",
"noImplicitOverride": true,
"resolveJsonModule": true,
"rootDir": ".",
"outDir": "dist",
"skipLibCheck": true,
"sourceMap": true,
"inlineSources": true,
"strict": true,
"stripInternal": true,
"target": "ES2017",
"allowJs": true
},
"include": ["src"]
}
9 changes: 9 additions & 0 deletions packages/sdk/browser/example/tsdown.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* eslint-disable import/no-extraneous-dependencies */
import { defineConfig } from 'tsdown';

export default defineConfig({
entry: 'src/app.ts',
platform: 'browser',
outDir: 'dist',
noExternal: ['@launchdarkly/js-client-sdk'],
});
Loading