Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/svelte sdk example #722

Draft
wants to merge 20 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
26f564e
add initial SDK library boilerplate and basic svelte LD SDK
robinson-md Oct 23, 2024
22a3378
Refactor test file paths and update Vite config
robinson-md Oct 23, 2024
147f67b
intial refactor to use new "@launchdarkly/js-client-sdk"
robinson-md Nov 6, 2024
938314c
refactor: update SvelteLDClient tests to use clientSideID
nosnibor89 Nov 6, 2024
3bf80cb
Merge pull request #1 from nosnibor89/feat/svelte-sdk-core-js-refactor
nosnibor89 Nov 11, 2024
3690339
refactor: update SvelteLDClient to use proxy for flag variations and …
nosnibor89 Nov 29, 2024
00380bb
Merge pull request #3 from nosnibor89/feat/svelte-sdk-refactor-is-on
nosnibor89 Nov 29, 2024
5bb9d7a
Merge branch 'ld-main' into feat/svelte-sdk
nosnibor89 Nov 29, 2024
13ba1b8
Merge branch 'feat/svelte-sdk' of github.com:nosnibor89/ld-sdk-criss-…
nosnibor89 Nov 29, 2024
cf49571
refactor: update SvelteLDClient to use compat SDK and improve initial…
nosnibor89 Dec 3, 2024
2365346
Merge pull request #4 from nosnibor89/feat/svelte-sdk-client-improvem…
nosnibor89 Dec 3, 2024
1572639
feat: add Svelte example project with configuration and initial tests
nosnibor89 Dec 4, 2024
f0ae0f4
docs: add README files for LaunchDarkly Svelte SDK and example project
nosnibor89 Dec 5, 2024
a4b1f3f
Merge branch 'main' into feat/svelte-sdk
nosnibor89 Dec 9, 2024
ff0b51b
refactor: replace isOn with useFlag in SvelteLDClient and update tests
nosnibor89 Dec 10, 2024
f328051
Merge branch 'feat/svelte-sdk' into feat/svelte-sdk-example
nosnibor89 Dec 11, 2024
a3711fc
docs: update README files to reflect SDK client ID changes and improv…
nosnibor89 Dec 11, 2024
fb4f9c4
Merge branch 'main' into feat/svelte-sdk
nosnibor89 Dec 17, 2024
18e8141
Merge branch 'feat/svelte-sdk' into feat/svelte-sdk-example
nosnibor89 Dec 17, 2024
098e319
Merge branch 'ld-main' into feat/svelte-sdk-example
nosnibor89 Dec 19, 2024
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"packages/sdk/react-universal/example",
"packages/sdk/vercel",
"packages/sdk/svelte",
"packages/sdk/svelte/example",
"packages/sdk/akamai-base",
"packages/sdk/akamai-base/example",
"packages/sdk/akamai-edgekv",
Expand Down
131 changes: 131 additions & 0 deletions packages/sdk/svelte/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Launch Darkly Svelte SDK

This is a Svelte library for Launch Darkly. It is a wrapper around the official Launch Darkly JavaScript SDK but with a Svelte-friendly API.

## Table of Contents

- [Getting Started](#getting-started)
- [Advanced Usage](#advanced-usage)
- [Changing user context](#changing-user-context)
- [Getting feature flag values](#getting-feature-flag-values)
- [Getting immediate flag value](#getting-immediate-flag-value)
- [Watching flag value changes](#watching-flag-value-changes)
- [Getting all flag values](#getting-all-flag-values)

## Getting started

First, install the package:

```bash
npm install @launchdarkly/svelte-client-sdk # or use yarn or pnpm
```

Then, initialize the SDK with your client-side ID using the `LDProvider` component:

```svelte
<script>
import { LDProvider } from '@launchdarkly/svelte-client-sdk';
import App from './App.svelte';
</script>

// Use context relevant to your application
const context = {
user: {
key: 'user-key',
},
};

<LDProvider clientID="your-client-side-id" {context}>
<App />
</LDProvider>
```

Now you can use the `LDFlag` component to conditionally render content based on feature flags:

```svelte
<script>
import { LDFlag } from '@launchdarkly/svelte-client-sdk';
</script>

<LDFlag flag={'my-feature-flag'}>
<div slot="on">
<p>this will render if the feature flag is on</p>
</div>
<div slot="off">
<p>this will render if the feature flag is off</p>
</div>
</LDFlag>
```

## Advanced usage

### Changing user context

You can change the user context by using the `identify` function from the `LD` object:

```svelte
<script>
import { LD } from '@launchdarkly/svelte-client-sdk';

function handleLogin() {
LD.identify({ key: 'new-user-key' });
}
</script>

<button on:click={handleLogin}>Login</button>
```

### Getting feature flag values

#### Getting immediate flag value

If you need to get the value of a flag at time of evaluation you can use the `useFlag` function:

```svelte
<script>
import { LD } from '@launchdarkly/svelte-client-sdk';

function handleClick() {
const isFeatureFlagOn = LD.useFlag('my-feature-flag', false);
console.log(isFeatureFlagOn);
}
</script>

<button on:click={handleClick}>Check flag value</button>
```

**Note:** Please note that `useFlag` function will return the current value of the flag at the time of evaluation, which means you won't get notified if the flag value changes. This is useful for cases where you need to get the value of a flag at a specific time like a function call. If you need to get notified when the flag value changes, you should use the `LDFlag` component, the `watch` function or the `flags` object depending on your use case.

#### Watching flag value changes

If you need to get notified when a flag value changes you can use the `watch` function. The `watch` function is an instance of [Svelte Store](https://svelte.dev/docs/svelte-store), which means you can use it with the `$` store subscriber syntax or the `subscribe` method. Here is an example of how to use the `watch` function:

```svelte
<script>
import { LD } from '@launchdarkly/svelte-client-sdk';

$: flagValue = LD.watch('my-feature-flag');
</script>

<p>{$flagValue}</p>
```

#### Getting all flag values

If you need to get all flag values you can use the `flags` object. The `flags` object is an instance of [Svelte Store](https://svelte.dev/docs/svelte-store), which means you can use it with the `$` store subscriber syntax or the `subscribe` method. Here is an example of how to use the `flags` object:

```svelte
<script>
import { LD } from '@launchdarkly/svelte-client-sdk';

$: allFlags = LD.flags;
</script>

{#each Object.keys($allFlags) as flagName}
<p>{flagName}: {$allFlags[flagName]}</p>
{/each}
```

## Credits

- Original code by [Robinson Marquez](https://github.com/nosnibor89)
13 changes: 13 additions & 0 deletions packages/sdk/svelte/example/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example

# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock
31 changes: 31 additions & 0 deletions packages/sdk/svelte/example/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/** @type { import("eslint").Linter.Config } */
module.exports = {
root: true,
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:svelte/recommended',
'prettier'
],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
parserOptions: {
sourceType: 'module',
ecmaVersion: 2020,
extraFileExtensions: ['.svelte']
},
env: {
browser: true,
es2017: true,
node: true
},
overrides: [
{
files: ['*.svelte'],
parser: 'svelte-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser'
}
}
]
};
11 changes: 11 additions & 0 deletions packages/sdk/svelte/example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.DS_Store
node_modules
/build
/dist
/.svelte-kit
/package
.env
.env.*
!.env.example
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
1 change: 1 addition & 0 deletions packages/sdk/svelte/example/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
engine-strict=true
4 changes: 4 additions & 0 deletions packages/sdk/svelte/example/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock
8 changes: 8 additions & 0 deletions packages/sdk/svelte/example/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"useTabs": true,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100,
"plugins": ["prettier-plugin-svelte"],
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
}
36 changes: 36 additions & 0 deletions packages/sdk/svelte/example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# LaunchDarkly Svelte SDK Example

This project demonstrates the usage of the `@launchdarkly/svelte-client-sdk`. It showcases how to conditionally render content based on feature flags using the `LDFlag` component.

## Installing Dependencies and Setting Environment Variables

First, install the project dependencies:

```bash
yarn install
```

Next, create a `.env` file in the root of the project and add your LaunchDarkly client-side ID and flag key. You can obtain these from any LaunchDarkly project/environment you choose.

```bash
PUBLIC_LD_CLIENT_ID=your-client-side-id
PUBLIC_LD_FLAG_KEY=your-flag-key
```

Note: The flag specified by `PUBLIC_LD_FLAG_KEY` must be a boolean flag.

## Running the Project

To run the project, use the following command:

```bash
yarn dev
```

This will start the development server. Open your browser and navigate to the provided URL to see the example in action. The box will change its background color based on the value of the feature flag specified by `PUBLIC_LD_FLAG_KEY`.

### Role of `LDProvider`

The `LDProvider` component is used to initialize the LaunchDarkly client and provide the feature flag context to the rest of the application. It requires a `clientID` and a `context` object. The `context` object typically contains information about the user or environment, which LaunchDarkly uses to determine the state of feature flags.

In this example, the `LDProvider` wraps the entire application, ensuring that all child components have access to the feature flag data. The `slot="initializing"` is used to display a loading message while the flags are being fetched.
49 changes: 49 additions & 0 deletions packages/sdk/svelte/example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"name": "ld-svelte-example",
"version": "0.0.1",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview"
},
"exports": {
".": {
"types": "./dist/index.d.ts",
"svelte": "./dist/index.js",
"default": "./dist/index.js"
}
},
"files": [
"dist",
"!dist/**/*.test.*",
"!dist/**/*.spec.*"
],
"svelte": "./dist/index.js",
"types": "./dist/index.d.ts",
"type": "module",
"dependencies": {
"@launchdarkly/svelte-client-sdk": "workspace:^",
"esm-env": "^1.0.0",
"svelte": "^5.4.0"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/package": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^5.0.1",
"@types/eslint": "8.56.0",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.35.1",
"jsdom": "^24.0.0",
"prettier": "^3.1.1",
"prettier-plugin-svelte": "^3.1.2",
"svelte-check": "^3.6.0",
"tslib": "^2.4.1",
"typescript": "^5.0.0",
"vite": "^6.0.2",
"vitest": "^2.1.8"
}
}
13 changes: 13 additions & 0 deletions packages/sdk/svelte/example/src/app.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface PageState {}
// interface Platform {}
}
}

export {};
12 changes: 12 additions & 0 deletions packages/sdk/svelte/example/src/app.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div>%sveltekit.body%</div>
</body>
</html>
7 changes: 7 additions & 0 deletions packages/sdk/svelte/example/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { describe, it, expect } from 'vitest';

describe('sum test', () => {
it('adds 1 + 2 to equal 3', () => {
expect(1 + 2).toBe(3);
});
});
27 changes: 27 additions & 0 deletions packages/sdk/svelte/example/src/routes/+layout.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script lang="ts">
import { LDProvider } from '@launchdarkly/svelte-client-sdk';
import { PUBLIC_LD_CLIENT_ID } from '$env/static/public';

const context = {
kind: 'user',
key: 'example-context-key',
name: 'Sandy'
};
</script>


{#snippet failed(error: unknown, reset: () => void)}
<main>
<h1>Something failed!</h1>
<p>There was an error loading the app. Please make sure you have the environment variables properly setup</p>
<button on:click={reset}>Retry</button>
</main>
{/snippet}

<svelte:boundary {failed} onerror={console.error}>
<LDProvider clientID={PUBLIC_LD_CLIENT_ID} {context}>
<slot />

<p slot="initializing">loading flags...</p>
</LDProvider>
</svelte:boundary>
26 changes: 26 additions & 0 deletions packages/sdk/svelte/example/src/routes/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script lang="ts">
import { LDFlag } from '@launchdarkly/svelte-client-sdk';
import { PUBLIC_LD_FLAG_KEY } from '$env/static/public';
</script>

<style>
div {
margin: 1rem;
padding: 1rem;
width: 250px;
height: 250px;
border: 1px solid #ccc;
background-color: var(--bg-color);
}
</style>

<LDFlag flag={PUBLIC_LD_FLAG_KEY}>
<div slot="true" style="--bg-color: lightblue;">
<p>this box is lightblue when flag is on ({PUBLIC_LD_FLAG_KEY})</p>
</div>
<div slot="false" style="--bg-color: lightyellow;">
<p>this box is lightyellow when flag is off ({PUBLIC_LD_FLAG_KEY})</p>
</div>
</LDFlag>


Binary file added packages/sdk/svelte/example/static/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading