Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
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
20 changes: 0 additions & 20 deletions .github/workflows/node.js.yml

This file was deleted.

38 changes: 38 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Test and lint
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

on:
push:
branches: [main]
pull_request:
branches: ["**"]

jobs:
check:
name: Test and lint
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5

- name: Node setup
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
with:
cache-dependency-path: package.json
node-version: "20.x"
cache: "npm"

- name: Install and build
run: |
npm i
npm run build
- name: Publish package for testing branch
run: npx pkg-pr-new publish || echo "Have you set up pkg-pr-new for this repo?"
- name: Test
run: |
npm run test
npm run typecheck
npm run lint
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ dist-ssr
*.sw?

# It's a package
package-lock.json

*.tgz
*.tgz
*.tsbuildinfo
4 changes: 4 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"trailingComma": "all",
"proseWrap": "always"
}
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Changelog

## 0.4.0

- Adds /test and /\_generated/component.js entrypoints
- Drops commonjs support
- Improves source mapping for generated files
- Changes to a statically generated component API
40 changes: 40 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Developing guide

## Running locally

```sh
npm i
npm run dev
```

## Testing

```sh
npm run clean
npm run build
npm run typecheck
npm run lint
npm run test
```

## Deploying

### Building a one-off package

```sh
npm run clean
npm ci
npm pack
```

### Deploying a new version

```sh
npm run release
```

or for alpha release:

```sh
npm run alpha
```
114 changes: 79 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@

<!-- START: Include on https://convex.dev/components -->

This is a Convex component for feature flagging and experimentation using [LaunchDarkly](https://launchdarkly.com).
This is a Convex component for feature flagging and experimentation using
[LaunchDarkly](https://launchdarkly.com).

It syncs your LaunchDarkly environment to your Convex deployment, allowing you to use your feature flags in Convex.
It syncs your LaunchDarkly environment to your Convex deployment, allowing you
to use your feature flags in Convex.

## Why use LaunchDarkly with Convex?

- **Feature flags in your backend**: Use feature flags in your Convex functions to dynamically control the behavior of your app.
- **Experimentation**: Run A/B tests and feature experiments in Convex using LaunchDarkly.
- **Real-time updates**: Your LaunchDarkly flags and segments are synced to Convex in real-time, so you can use them in your app without needing to make additional API requests.
- **Feature flags in your backend**: Use feature flags in your Convex functions
to dynamically control the behavior of your app.
- **Experimentation**: Run A/B tests and feature experiments in Convex using
LaunchDarkly.
- **Real-time updates**: Your LaunchDarkly flags and segments are synced to
Convex in real-time, so you can use them in your app without needing to make
additional API requests.

## Prerequisites

Expand All @@ -22,11 +28,12 @@ To use this component you must have a LaunchDarkly account.

### Convex App

You'll need an existing Convex project to use the component.
Convex is a hosted backend platform, including a database, serverless functions,
and a ton more you can learn about [here](https://docs.convex.dev/get-started).
You'll need an existing Convex project to use the component. Convex is a hosted
backend platform, including a database, serverless functions, and a ton more you
can learn about [here](https://docs.convex.dev/get-started).

Run `npm create convex` or follow any of the [quickstarts](https://docs.convex.dev/home) to set one up.
Run `npm create convex` or follow any of the
[quickstarts](https://docs.convex.dev/home) to set one up.

## Installation

Expand All @@ -36,12 +43,13 @@ Run `npm create convex` or follow any of the [quickstarts](https://docs.convex.d
npm install @convex-dev/launchdarkly
```

Create a `convex.config.ts` file in your app's `convex/` folder and install the component by calling `use`:
Create a `convex.config.ts` file in your app's `convex/` folder and install the
component by calling `use`:

```typescript
// convex/convex.config.ts
import { defineApp } from "convex/server";
import launchdarkly from "@convex-dev/launchdarkly/convex.config";
import launchdarkly from "@convex-dev/launchdarkly/convex.config.js";

const app = defineApp();

Expand All @@ -50,7 +58,8 @@ app.use(launchdarkly);
export default app;
```

Once you've installed the component, make sure you push your changes to your Convex app:
Once you've installed the component, make sure you push your changes to your
Convex app:

```bash
npx convex dev
Expand All @@ -72,42 +81,63 @@ registerRoutes(components.launchdarkly, http);
export default http;
```

This will register two webhook HTTP handlers in your your Convex app's deployment:
This will register two webhook HTTP handlers in your your Convex app's
deployment:

- `GET YOUR_CONVEX_SITE_URL/ld/webhook` - LaunchDarkly will use this endpoint to verify the installation of your component.
- `PUT YOUR_CONVEX_SITE_URL/ld/webhook` - LaunchDarkly will send your flag and segment data to this endpoint.
- `GET YOUR_CONVEX_SITE_URL/ld/webhook` - LaunchDarkly will use this endpoint to
verify the installation of your component.
- `PUT YOUR_CONVEX_SITE_URL/ld/webhook` - LaunchDarkly will send your flag and
segment data to this endpoint.

### Configure the LaunchDarkly integration

Now, you'll need to copy your LaunchDarkly environment's SDK Key and store it in the component. You can copy your LaunchDarkly SDK by loading the [LaunchDarkly dashboard](https://app.launchdarkly.com), selecting your environment, and pressing Cmd + K (or Ctrl + K) to open the command palette. Select the "Copy SDK Key for the current environment" option.
Now, you'll need to copy your LaunchDarkly environment's SDK Key and store it in
the component. You can copy your LaunchDarkly SDK by loading the
[LaunchDarkly dashboard](https://app.launchdarkly.com). From there visit your project's settings and copy the SDK key for your environment.

![Copy SDK Key](./images/copy-sdk-key.png)

The value you copied should start with `sdk-`.

Store the SDK key you copied as an environment variable named `LAUNCHDARKLY_SDK_KEY` in your Convex deployment. You can do so on the [environment variables](https://dashboard.convex.dev/deployment/settings/environment-variables) page or via `npx convex env set LAUNCHDARKLY_SDK_KEY sdk-***` from the CLI.
Store the SDK key you copied as an environment variable named
`LAUNCHDARKLY_SDK_KEY` in your Convex deployment. You can do so on the
[environment variables](https://dashboard.convex.dev/deployment/settings/environment-variables)
page or via `npx convex env set LAUNCHDARKLY_SDK_KEY sdk-***` from the CLI.

You can now configure the LaunchDarkly integration. On the [Integrations page](https://app.launchdarkly.com/settings/integrations/convex/new) of the LaunchDarkly dashboard, search for Convex and click "Add Integration".
You can now configure the LaunchDarkly integration. On the
[Integrations page](https://app.launchdarkly.com/settings/integrations/convex/new)
of the LaunchDarkly dashboard, search for Convex and click "Add Integration".

Each of your Convex deployments (e.g. Production and other developer's environments) will need their own integration configured in LaunchDarkly.
Each of your Convex deployments (e.g. Production and other developer's
environments) will need their own integration configured in LaunchDarkly.

![Add Integration](./images/launchdarkly-integration-configuration.png)

Select a name and environment for the integration.

For "Webhook URL", use your deployment's HTTP Actions URL suffixed with the path provided to the `registerRoutes` call in your `http.ts` file. By default, the path is `/ld/webhook`. You can retrieve your HTTP Actions URL on the [Deployment Settings page](https://dashboard.convex.dev/deployment/settings) of the Convex dashboard. Example: `https://techno-kitten-138.convex.site/ld/webhook`
For "Webhook URL", use your deployment's HTTP Actions URL suffixed with the path
provided to the `registerRoutes` call in your `http.ts` file. By default, the
path is `/ld/webhook`. You can retrieve your HTTP Actions URL on the
[Deployment Settings page](https://dashboard.convex.dev/deployment/settings) of
the Convex dashboard. Example:
`https://techno-kitten-138.convex.site/ld/webhook`

For "Component API Token", generate a shared secret to be used by the LaunchDarkly integration. This will ensure the payloads sent to your webhook are coming from LaunchDarkly.
For "Component API Token", generate a shared secret to be used by the
LaunchDarkly integration. This will ensure the payloads sent to your webhook are
coming from LaunchDarkly.

```bash
npx convex run --component=launchdarkly tokens:generate --push
```

Once you save, you can open the integration form again and click the Validate button to test the connection. If you encounter errors, check the logs page in the Convex dashboard for more information.
Once you save, you can open the integration form again and click the Validate
button to test the connection. If you encounter errors, check the logs page in
the Convex dashboard for more information.

### Using the LaunchDarkly component

You may initialize the LaunchDarkly class with the component configuration and use the LaunchDarkly SDK as you would in a normal JavaScript application.
You may initialize the LaunchDarkly class with the component configuration and
use the LaunchDarkly SDK as you would in a normal JavaScript application.

```typescript
import { LaunchDarkly } from "@convex-dev/launchdarkly";
Expand All @@ -123,7 +153,7 @@ export const myQuery = query({
const isFlagOn = await ld.boolVariation(
"my-flag",
{ key: "myUser" },
false
false,
);
if (isFlagOn) {
// Do something when flag is on
Expand All @@ -136,11 +166,16 @@ export const myQuery = query({

## Example App

You can run the example in the [`examples`](./example/README.md) folder to see how the LaunchDarkly component works.
You can run the example in the [`examples`](./example/README.md) folder to see
how the LaunchDarkly component works.

## Production

When you're ready to deploy your app to production with LaunchDarkly, be sure to follow all the setup steps for production, including adding the `LAUNCHDARKLY_SDK_KEY` evnironment variable and configuring an additional shared secret and integration for Production. You'll want this to be configured before any of your code relies on the LaunchDarkly flags.
When you're ready to deploy your app to production with LaunchDarkly, be sure to
follow all the setup steps for production, including adding the
`LAUNCHDARKLY_SDK_KEY` evnironment variable and configuring an additional shared
secret and integration for Production. You'll want this to be configured before
any of your code relies on the LaunchDarkly flags.

You may use this command to generate your production secret:

Expand All @@ -150,12 +185,13 @@ npx convex run --component=launchdarkly --prod tokens:generate

## Syncing multiple LaunchDarkly environments in one Convex app

If you have multiple LaunchDarkly environments, you can create a separate component configuration for each environment.
If you have multiple LaunchDarkly environments, you can create a separate
component configuration for each environment.

```typescript
// convex/convex.config.js
import { defineApp } from "convex/server";
import launchdarkly from "@convex-dev/launchdarkly/convex.config";
import launchdarkly from "@convex-dev/launchdarkly/convex.config.js";

const app = defineApp();

Expand All @@ -170,7 +206,8 @@ app.use(launchdarkly, {
export default app;
```

Be sure to also update your `http.ts` file to register the routes for each component:
Be sure to also update your `http.ts` file to register the routes for each
component:

```typescript
// convex/http.ts
Expand All @@ -193,11 +230,14 @@ npx convex run --component=first tokens:generate
npx convex run --component=second tokens:generate
```

Also, store the appropriate SDK keys in your Convex deployment for each LaunchDarkly environment:
Also, store the appropriate SDK keys in your Convex deployment for each
LaunchDarkly environment:

These secrets can be plugged into seperate integration configurations in LaunchDarkly.
These secrets can be plugged into seperate integration configurations in
LaunchDarkly.

Once configured, you may initialize `LaunchDarkly` with the appropriate component configuration:
Once configured, you may initialize `LaunchDarkly` with the appropriate
component configuration:

```typescript
import { LaunchDarkly } from "@convex-dev/launchdarkly";
Expand All @@ -224,10 +264,14 @@ export const myQuery = query({

## Unsupported LaunchDarkly features

The LaunchDarkly component for Convex is in beta, and may not support all functionality available in the LaunchDarkly SDK.
If you encounter any issues or need help with a specific feature, please file an issue in the [GitHub repository](https://github.com/get-convex/launchdarkly/issues).
The LaunchDarkly component for Convex is in beta, and may not support all
functionality available in the LaunchDarkly SDK. If you encounter any issues or
need help with a specific feature, please file an issue in the
[GitHub repository](https://github.com/get-convex/launchdarkly/issues).

- Sending events in Convex queries is not supported. If you would like to have the SDK send events to LaunchDarkly (e.g. flag evaluation insights and for experimentation), you should use LaunchDarkly in a mutation or action instead.
- Sending events in Convex queries is not supported. If you would like to have
the SDK send events to LaunchDarkly (e.g. flag evaluation insights and for
experimentation), you should use LaunchDarkly in a mutation or action instead.
- Big segments
- Diagnostic events

Expand Down
8 changes: 0 additions & 8 deletions commonjs.json

This file was deleted.

7 changes: 7 additions & 0 deletions convex.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"$schema": "./node_modules/convex/schemas/convex.schema.json",
"functions": "example/convex",
"codegen": {
"legacyComponentApi": false
}
}
Loading
Loading