From 448e640c43321aa719a4037e1aa4abfd503058f1 Mon Sep 17 00:00:00 2001 From: Marc Brakken Date: Wed, 1 Jul 2026 13:11:24 -0500 Subject: [PATCH 1/5] [adapter-launchdarkly] support native Marketplace integration - Read the Edge Config connection string from EXPERIMENTATION_CONFIG, falling back to EDGE_CONFIG for the legacy Vercel integration - Make LAUNCHDARKLY_PROJECT_SLUG / projectSlug optional; it is only used to deep-link flags to the LaunchDarkly dashboard --- .../launchdarkly-experimentation-config.md | 10 ++++++ .../content/docs/providers/launchdarkly.mdx | 23 +++++++----- packages/adapter-launchdarkly/README.md | 12 +++++-- .../adapter-launchdarkly/src/index.test.ts | 17 +++++++-- packages/adapter-launchdarkly/src/index.ts | 35 ++++++++++++++++--- 5 files changed, 78 insertions(+), 19 deletions(-) create mode 100644 .changeset/launchdarkly-experimentation-config.md diff --git a/.changeset/launchdarkly-experimentation-config.md b/.changeset/launchdarkly-experimentation-config.md new file mode 100644 index 00000000..75358d0f --- /dev/null +++ b/.changeset/launchdarkly-experimentation-config.md @@ -0,0 +1,10 @@ +--- +'@flags-sdk/launchdarkly': minor +--- + +Support the native LaunchDarkly Marketplace integration. + +**Breaking changes:** + +- The adapter now reads the Edge Config connection string from `EXPERIMENTATION_CONFIG` first, falling back to `EDGE_CONFIG` for the legacy Vercel integration. If both are set to different values, `EXPERIMENTATION_CONFIG` now takes precedence. The error thrown when neither is set changed to `LaunchDarkly Adapter: Missing EXPERIMENTATION_CONFIG or EDGE_CONFIG environment variable`. +- `LAUNCHDARKLY_PROJECT_SLUG` / `projectSlug` is now optional. It is only used to deep-link flags to the LaunchDarkly dashboard. When it is not set, flag evaluation is unaffected, but `variation().origin` is now `undefined` instead of always being a function. diff --git a/apps/docs/content/docs/providers/launchdarkly.mdx b/apps/docs/content/docs/providers/launchdarkly.mdx index 0f846946..82b1c80e 100644 --- a/apps/docs/content/docs/providers/launchdarkly.mdx +++ b/apps/docs/content/docs/providers/launchdarkly.mdx @@ -49,21 +49,26 @@ import { createLaunchDarklyAdapter } from '@flags-sdk/launchdarkly'; const customLdAdapter = createLaunchDarklyAdapter({ projectSlug: process.env.LAUNCHDARKLY_PROJECT_SLUG, clientSideId: process.env.LAUNCHDARKLY_CLIENT_SIDE_ID, - edgeConfigConnectionString: process.env.EDGE_CONFIG, + edgeConfigConnectionString: + process.env.EXPERIMENTATION_CONFIG ?? process.env.EDGE_CONFIG, }); ``` -| Option key | Type | Description | -| ---------------------------- | ---------| ----------------------------- | -| `projectSlug` | `string` | LaunchDarkly project slug | -| `clientSideId` | `string` | LaunchDarkly client-side ID | -| `edgeConfigConnectionString` | `string` | Edge Config connection string | +| Option key | Type | Description | +| ---------------------------- | ---------| ------------------------------------------------------------------ | +| `projectSlug` | `string` | LaunchDarkly project slug. Optional, only used for dashboard links | +| `clientSideId` | `string` | LaunchDarkly client-side ID | +| `edgeConfigConnectionString` | `string` | Edge Config connection string | The default LaunchDarkly adapter configures itself based on the following environment variables: - `LAUNCHDARKLY_CLIENT_SIDE_ID` _(required)_ → `clientSideId` -- `LAUNCHDARKLY_PROJECT_SLUG` _(required)_ → `projectSlug` -- `EDGE_CONFIG` _(required)_ → `edgeConfigConnectionString` +- `LAUNCHDARKLY_PROJECT_SLUG` _(optional)_ → `projectSlug` +- `EXPERIMENTATION_CONFIG` _(required)_ → `edgeConfigConnectionString` + +`LAUNCHDARKLY_PROJECT_SLUG` is only used to deep-link flags to the LaunchDarkly dashboard. When it is not set, flag evaluation is unaffected but the adapter does not expose an `origin`. + +The native LaunchDarkly [Marketplace integration](https://vercel.com/marketplace/launchdarkly) exposes the Edge Config connection string as `EXPERIMENTATION_CONFIG` when Edge Config is enabled for the collection. The adapter falls back to `EDGE_CONFIG` (used by the legacy Vercel integration) when `EXPERIMENTATION_CONFIG` is not set. --- @@ -143,7 +148,7 @@ The LaunchDarkly adapter loads the configuration from [Edge Config](https://verc Edge Config is a global, ultra-low latency store which uses active replication and is specifically designed for serving feature flag configuration. -The default LaunchDarkly adapter, exported as `ldAdapter`, will automatically connect to Edge Config when the required environment variables are set. +The default LaunchDarkly adapter, exported as `ldAdapter`, will automatically connect to Edge Config when the required environment variables are set. It reads the connection string from `EXPERIMENTATION_CONFIG` (native Marketplace integration) and falls back to `EDGE_CONFIG` (legacy Vercel integration). --- diff --git a/packages/adapter-launchdarkly/README.md b/packages/adapter-launchdarkly/README.md index 6b6ae73a..10ae85cf 100644 --- a/packages/adapter-launchdarkly/README.md +++ b/packages/adapter-launchdarkly/README.md @@ -24,8 +24,13 @@ The default adapter uses the following environment variables to configure itself ```sh export LAUNCHDARKLY_CLIENT_SIDE_ID="612376f91b8f5713a58777a1" +# Optional. Only used to deep-link flags to the LaunchDarkly dashboard. export LAUNCHDARKLY_PROJECT_SLUG="my-project" -# Provided by Vercel when connecting an Edge Config to the project +# Provided by the LaunchDarkly Marketplace integration when Edge Config is +# enabled for the collection. +export EXPERIMENTATION_CONFIG="https://edge-config.vercel.com/ecfg_abdc1234?token=xxx-xxx-xxx" +# Provided by Vercel when connecting an Edge Config. Used as a fallback when +# EXPERIMENTATION_CONFIG is not set. export EDGE_CONFIG="https://edge-config.vercel.com/ecfg_abdc1234?token=xxx-xxx-xxx" ``` @@ -57,8 +62,9 @@ import { createLaunchDarklyAdapter } from "@flags-sdk/launchdarkly"; const adapter = createLaunchDarklyAdapter({ projectSlug: "my-project", - ldClientSideKey: "612376f91b8f5713a58777a1", - edgeConfigConnectionString: process.env.EDGE_CONFIG, + clientSideId: "612376f91b8f5713a58777a1", + edgeConfigConnectionString: + process.env.EXPERIMENTATION_CONFIG ?? process.env.EDGE_CONFIG, }); ``` diff --git a/packages/adapter-launchdarkly/src/index.test.ts b/packages/adapter-launchdarkly/src/index.test.ts index 6e6feb83..fca4c4f3 100644 --- a/packages/adapter-launchdarkly/src/index.test.ts +++ b/packages/adapter-launchdarkly/src/index.test.ts @@ -1,6 +1,6 @@ import type { ReadonlyHeaders, ReadonlyRequestCookies } from 'flags'; import { beforeAll, describe, expect, it, vi } from 'vitest'; -import { type LDContext, ldAdapter } from '.'; +import { createLaunchDarklyAdapter, type LDContext, ldAdapter } from '.'; const ldClientMock = { waitForInitialization: vi.fn(), @@ -24,7 +24,7 @@ describe('ldAdapter', () => { describe('with a missing environment', () => { it('should throw an error', () => { expect(() => ldAdapter.variation()).toThrowError( - 'LaunchDarkly Adapter: Missing EDGE_CONFIG environment variable', + 'LaunchDarkly Adapter: Missing EXPERIMENTATION_CONFIG or EDGE_CONFIG environment variable', ); }); }); @@ -33,7 +33,8 @@ describe('ldAdapter', () => { beforeAll(() => { process.env.LAUNCHDARKLY_PROJECT_SLUG = 'test-project'; process.env.LAUNCHDARKLY_CLIENT_SIDE_ID = 'test-client-side-id'; - process.env.EDGE_CONFIG = 'https://edge-config.com/test-edge-config'; + process.env.EXPERIMENTATION_CONFIG = + 'https://edge-config.com/test-experimentation-config'; }); it('should expose the ldClient', () => { @@ -66,6 +67,16 @@ describe('ldAdapter', () => { await expect(valuePromise).resolves.toEqual(true); expect(ldClientMock.variation).toHaveBeenCalled(); }); + + it('should not expose an origin when projectSlug is omitted', () => { + const adapter = createLaunchDarklyAdapter({ + clientSideId: 'test-client-side-id', + edgeConfigConnectionString: + 'https://edge-config.com/test-experimentation-config', + }); + + expect(adapter.variation().origin).toBeUndefined(); + }); }); }); }); diff --git a/packages/adapter-launchdarkly/src/index.ts b/packages/adapter-launchdarkly/src/index.ts index d3f0972c..1748de3e 100644 --- a/packages/adapter-launchdarkly/src/index.ts +++ b/packages/adapter-launchdarkly/src/index.ts @@ -36,12 +36,35 @@ function assertEnv(name: string): string { return value; } +/** + * Resolves the Edge Config connection string used to load LaunchDarkly flag data. + * + * The native LaunchDarkly Marketplace integration exposes the connection string + * as `EXPERIMENTATION_CONFIG`, while the legacy Vercel integration exposes it as + * `EDGE_CONFIG`. We prefer `EXPERIMENTATION_CONFIG` and fall back to `EDGE_CONFIG` + * for backwards compatibility. + */ +function assertEdgeConfigConnectionString(): string { + const value = process.env.EXPERIMENTATION_CONFIG || process.env.EDGE_CONFIG; + if (!value) { + throw new Error( + 'LaunchDarkly Adapter: Missing EXPERIMENTATION_CONFIG or EDGE_CONFIG environment variable', + ); + } + return value; +} + export function createLaunchDarklyAdapter({ projectSlug, clientSideId, edgeConfigConnectionString, }: { - projectSlug: string; + /** + * LaunchDarkly project slug. Only used to construct the `origin` URL that + * deep-links a flag to its LaunchDarkly dashboard page. When omitted, the + * adapter does not expose an `origin`, but flag evaluation is unaffected. + */ + projectSlug?: string; clientSideId: string; edgeConfigConnectionString: string; }): AdapterResponse { @@ -80,7 +103,9 @@ export function createLaunchDarklyAdapter({ options: AdapterOptions = {}, ): Adapter { return { - origin, + // Only expose `origin` when a project slug is available, otherwise the + // deep-link would be incorrect. + origin: projectSlug ? origin : undefined, async decide({ key, entities, headers }): Promise { if (!ldClient.initialized()) { if (!initPromise) initPromise = ldClient.waitForInitialization(); @@ -108,9 +133,11 @@ export function createLaunchDarklyAdapter({ function getOrCreateDeaultAdapter() { if (!defaultLaunchDarklyAdapter) { - const edgeConfigConnectionString = assertEnv('EDGE_CONFIG'); + const edgeConfigConnectionString = assertEdgeConfigConnectionString(); const clientSideId = assertEnv('LAUNCHDARKLY_CLIENT_SIDE_ID'); - const projectSlug = assertEnv('LAUNCHDARKLY_PROJECT_SLUG'); + // Optional: only used to build the dashboard deep-link (`origin`). The + // native Marketplace integration may not provide this. + const projectSlug = process.env.LAUNCHDARKLY_PROJECT_SLUG; defaultLaunchDarklyAdapter = createLaunchDarklyAdapter({ projectSlug, From 24a950df75a18247acf6866c2b5b579d8ef8ddd5 Mon Sep 17 00:00:00 2001 From: Marc Brakken Date: Wed, 8 Jul 2026 16:50:51 -0500 Subject: [PATCH 2/5] [adapter-launchdarkly] read EXPERIMENTATION_CONFIG only Align with the Statsig adapter: the default adapter reads the Edge Config connection string from EXPERIMENTATION_CONFIG only and no longer falls back to EDGE_CONFIG. Legacy Vercel integration users can set EXPERIMENTATION_CONFIG to their EDGE_CONFIG value or pass edgeConfigConnectionString explicitly. --- .../launchdarkly-experimentation-config.md | 23 ++++++++++++++++++- .../content/docs/providers/launchdarkly.mdx | 8 +++++-- packages/adapter-launchdarkly/README.md | 11 ++++++--- .../adapter-launchdarkly/src/index.test.ts | 2 +- packages/adapter-launchdarkly/src/index.ts | 20 +--------------- 5 files changed, 38 insertions(+), 26 deletions(-) diff --git a/.changeset/launchdarkly-experimentation-config.md b/.changeset/launchdarkly-experimentation-config.md index 75358d0f..cff67ea0 100644 --- a/.changeset/launchdarkly-experimentation-config.md +++ b/.changeset/launchdarkly-experimentation-config.md @@ -6,5 +6,26 @@ Support the native LaunchDarkly Marketplace integration. **Breaking changes:** -- The adapter now reads the Edge Config connection string from `EXPERIMENTATION_CONFIG` first, falling back to `EDGE_CONFIG` for the legacy Vercel integration. If both are set to different values, `EXPERIMENTATION_CONFIG` now takes precedence. The error thrown when neither is set changed to `LaunchDarkly Adapter: Missing EXPERIMENTATION_CONFIG or EDGE_CONFIG environment variable`. +- The default adapter (`ldAdapter`) now reads the Edge Config connection string from the `EXPERIMENTATION_CONFIG` environment variable instead of `EDGE_CONFIG`. This aligns with the native LaunchDarkly Marketplace integration and matches the behavior of other adapters (e.g. Statsig). `EDGE_CONFIG` is no longer read by the default adapter. The error thrown when `EXPERIMENTATION_CONFIG` is not set changed to `LaunchDarkly Adapter: Missing EXPERIMENTATION_CONFIG environment variable`. + + **If you use the legacy LaunchDarkly Vercel integration** (which provides the connection string as `EDGE_CONFIG`), do one of the following: + + 1. Set `EXPERIMENTATION_CONFIG` to the same value as `EDGE_CONFIG`, for example in your project's environment variables: + + ```sh + EXPERIMENTATION_CONFIG=$EDGE_CONFIG + ``` + + 2. Or pass the connection string explicitly with `createLaunchDarklyAdapter`: + + ```ts + import { createLaunchDarklyAdapter } from '@flags-sdk/launchdarkly'; + + const ldAdapter = createLaunchDarklyAdapter({ + projectSlug: process.env.LAUNCHDARKLY_PROJECT_SLUG, + clientSideId: process.env.LAUNCHDARKLY_CLIENT_SIDE_ID, + edgeConfigConnectionString: process.env.EDGE_CONFIG, + }); + ``` + - `LAUNCHDARKLY_PROJECT_SLUG` / `projectSlug` is now optional. It is only used to deep-link flags to the LaunchDarkly dashboard. When it is not set, flag evaluation is unaffected, but `variation().origin` is now `undefined` instead of always being a function. diff --git a/apps/docs/content/docs/providers/launchdarkly.mdx b/apps/docs/content/docs/providers/launchdarkly.mdx index 82b1c80e..47c0b18e 100644 --- a/apps/docs/content/docs/providers/launchdarkly.mdx +++ b/apps/docs/content/docs/providers/launchdarkly.mdx @@ -49,6 +49,8 @@ import { createLaunchDarklyAdapter } from '@flags-sdk/launchdarkly'; const customLdAdapter = createLaunchDarklyAdapter({ projectSlug: process.env.LAUNCHDARKLY_PROJECT_SLUG, clientSideId: process.env.LAUNCHDARKLY_CLIENT_SIDE_ID, + // Legacy integrations that provide the connection string as `EDGE_CONFIG` + // can pass it explicitly here. edgeConfigConnectionString: process.env.EXPERIMENTATION_CONFIG ?? process.env.EDGE_CONFIG, }); @@ -68,7 +70,9 @@ The default LaunchDarkly adapter configures itself based on the following enviro `LAUNCHDARKLY_PROJECT_SLUG` is only used to deep-link flags to the LaunchDarkly dashboard. When it is not set, flag evaluation is unaffected but the adapter does not expose an `origin`. -The native LaunchDarkly [Marketplace integration](https://vercel.com/marketplace/launchdarkly) exposes the Edge Config connection string as `EXPERIMENTATION_CONFIG` when Edge Config is enabled for the collection. The adapter falls back to `EDGE_CONFIG` (used by the legacy Vercel integration) when `EXPERIMENTATION_CONFIG` is not set. +The native LaunchDarkly [Marketplace integration](https://vercel.com/marketplace/launchdarkly) exposes the Edge Config connection string as `EXPERIMENTATION_CONFIG` when Edge Config is enabled for the collection. + +If you use the legacy LaunchDarkly Vercel integration, which provides the connection string as `EDGE_CONFIG`, set `EXPERIMENTATION_CONFIG` to the same value, or use `createLaunchDarklyAdapter` to pass `edgeConfigConnectionString` explicitly. --- @@ -148,7 +152,7 @@ The LaunchDarkly adapter loads the configuration from [Edge Config](https://verc Edge Config is a global, ultra-low latency store which uses active replication and is specifically designed for serving feature flag configuration. -The default LaunchDarkly adapter, exported as `ldAdapter`, will automatically connect to Edge Config when the required environment variables are set. It reads the connection string from `EXPERIMENTATION_CONFIG` (native Marketplace integration) and falls back to `EDGE_CONFIG` (legacy Vercel integration). +The default LaunchDarkly adapter, exported as `ldAdapter`, will automatically connect to Edge Config when the required environment variables are set. It reads the connection string from `EXPERIMENTATION_CONFIG` (provided by the native Marketplace integration). --- diff --git a/packages/adapter-launchdarkly/README.md b/packages/adapter-launchdarkly/README.md index 10ae85cf..4c418363 100644 --- a/packages/adapter-launchdarkly/README.md +++ b/packages/adapter-launchdarkly/README.md @@ -29,11 +29,14 @@ export LAUNCHDARKLY_PROJECT_SLUG="my-project" # Provided by the LaunchDarkly Marketplace integration when Edge Config is # enabled for the collection. export EXPERIMENTATION_CONFIG="https://edge-config.vercel.com/ecfg_abdc1234?token=xxx-xxx-xxx" -# Provided by Vercel when connecting an Edge Config. Used as a fallback when -# EXPERIMENTATION_CONFIG is not set. -export EDGE_CONFIG="https://edge-config.vercel.com/ecfg_abdc1234?token=xxx-xxx-xxx" ``` +> **Using the legacy LaunchDarkly Vercel integration?** The default adapter reads +> the Edge Config connection string from `EXPERIMENTATION_CONFIG` only. If your +> project provides the connection string as `EDGE_CONFIG`, set +> `EXPERIMENTATION_CONFIG` to the same value, or pass it explicitly with +> [`createLaunchDarklyAdapter`](#custom-adapter). + ## Example ```ts @@ -63,6 +66,8 @@ import { createLaunchDarklyAdapter } from "@flags-sdk/launchdarkly"; const adapter = createLaunchDarklyAdapter({ projectSlug: "my-project", clientSideId: "612376f91b8f5713a58777a1", + // Legacy integrations that provide the connection string as `EDGE_CONFIG` + // can pass it explicitly here. edgeConfigConnectionString: process.env.EXPERIMENTATION_CONFIG ?? process.env.EDGE_CONFIG, }); diff --git a/packages/adapter-launchdarkly/src/index.test.ts b/packages/adapter-launchdarkly/src/index.test.ts index fca4c4f3..88f791c5 100644 --- a/packages/adapter-launchdarkly/src/index.test.ts +++ b/packages/adapter-launchdarkly/src/index.test.ts @@ -24,7 +24,7 @@ describe('ldAdapter', () => { describe('with a missing environment', () => { it('should throw an error', () => { expect(() => ldAdapter.variation()).toThrowError( - 'LaunchDarkly Adapter: Missing EXPERIMENTATION_CONFIG or EDGE_CONFIG environment variable', + 'LaunchDarkly Adapter: Missing EXPERIMENTATION_CONFIG environment variable', ); }); }); diff --git a/packages/adapter-launchdarkly/src/index.ts b/packages/adapter-launchdarkly/src/index.ts index 1748de3e..e6876423 100644 --- a/packages/adapter-launchdarkly/src/index.ts +++ b/packages/adapter-launchdarkly/src/index.ts @@ -36,24 +36,6 @@ function assertEnv(name: string): string { return value; } -/** - * Resolves the Edge Config connection string used to load LaunchDarkly flag data. - * - * The native LaunchDarkly Marketplace integration exposes the connection string - * as `EXPERIMENTATION_CONFIG`, while the legacy Vercel integration exposes it as - * `EDGE_CONFIG`. We prefer `EXPERIMENTATION_CONFIG` and fall back to `EDGE_CONFIG` - * for backwards compatibility. - */ -function assertEdgeConfigConnectionString(): string { - const value = process.env.EXPERIMENTATION_CONFIG || process.env.EDGE_CONFIG; - if (!value) { - throw new Error( - 'LaunchDarkly Adapter: Missing EXPERIMENTATION_CONFIG or EDGE_CONFIG environment variable', - ); - } - return value; -} - export function createLaunchDarklyAdapter({ projectSlug, clientSideId, @@ -133,7 +115,7 @@ export function createLaunchDarklyAdapter({ function getOrCreateDeaultAdapter() { if (!defaultLaunchDarklyAdapter) { - const edgeConfigConnectionString = assertEdgeConfigConnectionString(); + const edgeConfigConnectionString = assertEnv('EXPERIMENTATION_CONFIG'); const clientSideId = assertEnv('LAUNCHDARKLY_CLIENT_SIDE_ID'); // Optional: only used to build the dashboard deep-link (`origin`). The // native Marketplace integration may not provide this. From a618f6581a845a4a237dcee01b06f8770f89a2d8 Mon Sep 17 00:00:00 2001 From: Marc Brakken Date: Wed, 8 Jul 2026 17:18:35 -0500 Subject: [PATCH 3/5] [adapter-launchdarkly] mark changeset as major (breaking change) --- .changeset/launchdarkly-experimentation-config.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/launchdarkly-experimentation-config.md b/.changeset/launchdarkly-experimentation-config.md index cff67ea0..3ceea2b4 100644 --- a/.changeset/launchdarkly-experimentation-config.md +++ b/.changeset/launchdarkly-experimentation-config.md @@ -1,5 +1,5 @@ --- -'@flags-sdk/launchdarkly': minor +'@flags-sdk/launchdarkly': major --- Support the native LaunchDarkly Marketplace integration. From 726899889d39c5139ad0d6ef22450199f6a1c2d1 Mon Sep 17 00:00:00 2001 From: Marc Brakken Date: Thu, 9 Jul 2026 11:00:56 -0500 Subject: [PATCH 4/5] Update changelog to have a single recommendation for legacy EDGE_CONFIG env var --- .../launchdarkly-experimentation-config.md | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/.changeset/launchdarkly-experimentation-config.md b/.changeset/launchdarkly-experimentation-config.md index 3ceea2b4..f385a990 100644 --- a/.changeset/launchdarkly-experimentation-config.md +++ b/.changeset/launchdarkly-experimentation-config.md @@ -8,24 +8,16 @@ Support the native LaunchDarkly Marketplace integration. - The default adapter (`ldAdapter`) now reads the Edge Config connection string from the `EXPERIMENTATION_CONFIG` environment variable instead of `EDGE_CONFIG`. This aligns with the native LaunchDarkly Marketplace integration and matches the behavior of other adapters (e.g. Statsig). `EDGE_CONFIG` is no longer read by the default adapter. The error thrown when `EXPERIMENTATION_CONFIG` is not set changed to `LaunchDarkly Adapter: Missing EXPERIMENTATION_CONFIG environment variable`. - **If you use the legacy LaunchDarkly Vercel integration** (which provides the connection string as `EDGE_CONFIG`), do one of the following: + **If you use the legacy LaunchDarkly Vercel integration** (which provides the connection string as `EDGE_CONFIG`), pass the connection string explicitly with `createLaunchDarklyAdapter`: - 1. Set `EXPERIMENTATION_CONFIG` to the same value as `EDGE_CONFIG`, for example in your project's environment variables: + ```ts + import { createLaunchDarklyAdapter } from '@flags-sdk/launchdarkly'; - ```sh - EXPERIMENTATION_CONFIG=$EDGE_CONFIG - ``` - - 2. Or pass the connection string explicitly with `createLaunchDarklyAdapter`: - - ```ts - import { createLaunchDarklyAdapter } from '@flags-sdk/launchdarkly'; - - const ldAdapter = createLaunchDarklyAdapter({ - projectSlug: process.env.LAUNCHDARKLY_PROJECT_SLUG, - clientSideId: process.env.LAUNCHDARKLY_CLIENT_SIDE_ID, - edgeConfigConnectionString: process.env.EDGE_CONFIG, - }); - ``` + const ldAdapter = createLaunchDarklyAdapter({ + projectSlug: process.env.LAUNCHDARKLY_PROJECT_SLUG, + clientSideId: process.env.LAUNCHDARKLY_CLIENT_SIDE_ID, + edgeConfigConnectionString: process.env.EDGE_CONFIG, + }); + ``` - `LAUNCHDARKLY_PROJECT_SLUG` / `projectSlug` is now optional. It is only used to deep-link flags to the LaunchDarkly dashboard. When it is not set, flag evaluation is unaffected, but `variation().origin` is now `undefined` instead of always being a function. From 92e53b8634a209b7f28caa38b0d6db6cab5b5e07 Mon Sep 17 00:00:00 2001 From: Marc Brakken Date: Fri, 10 Jul 2026 09:46:40 -0500 Subject: [PATCH 5/5] Bring back LAUNCHDARKLY_PROJECT_SLUG as required --- .changeset/launchdarkly-experimentation-config.md | 2 -- apps/docs/content/docs/providers/launchdarkly.mdx | 6 ++---- packages/adapter-launchdarkly/README.md | 1 - packages/adapter-launchdarkly/src/index.test.ts | 12 +----------- packages/adapter-launchdarkly/src/index.ts | 15 +++------------ 5 files changed, 6 insertions(+), 30 deletions(-) diff --git a/.changeset/launchdarkly-experimentation-config.md b/.changeset/launchdarkly-experimentation-config.md index f385a990..b48f994b 100644 --- a/.changeset/launchdarkly-experimentation-config.md +++ b/.changeset/launchdarkly-experimentation-config.md @@ -19,5 +19,3 @@ Support the native LaunchDarkly Marketplace integration. edgeConfigConnectionString: process.env.EDGE_CONFIG, }); ``` - -- `LAUNCHDARKLY_PROJECT_SLUG` / `projectSlug` is now optional. It is only used to deep-link flags to the LaunchDarkly dashboard. When it is not set, flag evaluation is unaffected, but `variation().origin` is now `undefined` instead of always being a function. diff --git a/apps/docs/content/docs/providers/launchdarkly.mdx b/apps/docs/content/docs/providers/launchdarkly.mdx index 47c0b18e..b367d232 100644 --- a/apps/docs/content/docs/providers/launchdarkly.mdx +++ b/apps/docs/content/docs/providers/launchdarkly.mdx @@ -58,18 +58,16 @@ const customLdAdapter = createLaunchDarklyAdapter({ | Option key | Type | Description | | ---------------------------- | ---------| ------------------------------------------------------------------ | -| `projectSlug` | `string` | LaunchDarkly project slug. Optional, only used for dashboard links | +| `projectSlug` | `string` | LaunchDarkly project slug | | `clientSideId` | `string` | LaunchDarkly client-side ID | | `edgeConfigConnectionString` | `string` | Edge Config connection string | The default LaunchDarkly adapter configures itself based on the following environment variables: - `LAUNCHDARKLY_CLIENT_SIDE_ID` _(required)_ → `clientSideId` -- `LAUNCHDARKLY_PROJECT_SLUG` _(optional)_ → `projectSlug` +- `LAUNCHDARKLY_PROJECT_SLUG` _(required)_ → `projectSlug` - `EXPERIMENTATION_CONFIG` _(required)_ → `edgeConfigConnectionString` -`LAUNCHDARKLY_PROJECT_SLUG` is only used to deep-link flags to the LaunchDarkly dashboard. When it is not set, flag evaluation is unaffected but the adapter does not expose an `origin`. - The native LaunchDarkly [Marketplace integration](https://vercel.com/marketplace/launchdarkly) exposes the Edge Config connection string as `EXPERIMENTATION_CONFIG` when Edge Config is enabled for the collection. If you use the legacy LaunchDarkly Vercel integration, which provides the connection string as `EDGE_CONFIG`, set `EXPERIMENTATION_CONFIG` to the same value, or use `createLaunchDarklyAdapter` to pass `edgeConfigConnectionString` explicitly. diff --git a/packages/adapter-launchdarkly/README.md b/packages/adapter-launchdarkly/README.md index 4c418363..9cae5cd3 100644 --- a/packages/adapter-launchdarkly/README.md +++ b/packages/adapter-launchdarkly/README.md @@ -24,7 +24,6 @@ The default adapter uses the following environment variables to configure itself ```sh export LAUNCHDARKLY_CLIENT_SIDE_ID="612376f91b8f5713a58777a1" -# Optional. Only used to deep-link flags to the LaunchDarkly dashboard. export LAUNCHDARKLY_PROJECT_SLUG="my-project" # Provided by the LaunchDarkly Marketplace integration when Edge Config is # enabled for the collection. diff --git a/packages/adapter-launchdarkly/src/index.test.ts b/packages/adapter-launchdarkly/src/index.test.ts index 88f791c5..2bcb255b 100644 --- a/packages/adapter-launchdarkly/src/index.test.ts +++ b/packages/adapter-launchdarkly/src/index.test.ts @@ -1,6 +1,6 @@ import type { ReadonlyHeaders, ReadonlyRequestCookies } from 'flags'; import { beforeAll, describe, expect, it, vi } from 'vitest'; -import { createLaunchDarklyAdapter, type LDContext, ldAdapter } from '.'; +import { type LDContext, ldAdapter } from '.'; const ldClientMock = { waitForInitialization: vi.fn(), @@ -67,16 +67,6 @@ describe('ldAdapter', () => { await expect(valuePromise).resolves.toEqual(true); expect(ldClientMock.variation).toHaveBeenCalled(); }); - - it('should not expose an origin when projectSlug is omitted', () => { - const adapter = createLaunchDarklyAdapter({ - clientSideId: 'test-client-side-id', - edgeConfigConnectionString: - 'https://edge-config.com/test-experimentation-config', - }); - - expect(adapter.variation().origin).toBeUndefined(); - }); }); }); }); diff --git a/packages/adapter-launchdarkly/src/index.ts b/packages/adapter-launchdarkly/src/index.ts index e6876423..54779a7e 100644 --- a/packages/adapter-launchdarkly/src/index.ts +++ b/packages/adapter-launchdarkly/src/index.ts @@ -41,12 +41,7 @@ export function createLaunchDarklyAdapter({ clientSideId, edgeConfigConnectionString, }: { - /** - * LaunchDarkly project slug. Only used to construct the `origin` URL that - * deep-links a flag to its LaunchDarkly dashboard page. When omitted, the - * adapter does not expose an `origin`, but flag evaluation is unaffected. - */ - projectSlug?: string; + projectSlug: string; clientSideId: string; edgeConfigConnectionString: string; }): AdapterResponse { @@ -85,9 +80,7 @@ export function createLaunchDarklyAdapter({ options: AdapterOptions = {}, ): Adapter { return { - // Only expose `origin` when a project slug is available, otherwise the - // deep-link would be incorrect. - origin: projectSlug ? origin : undefined, + origin, async decide({ key, entities, headers }): Promise { if (!ldClient.initialized()) { if (!initPromise) initPromise = ldClient.waitForInitialization(); @@ -117,9 +110,7 @@ function getOrCreateDeaultAdapter() { if (!defaultLaunchDarklyAdapter) { const edgeConfigConnectionString = assertEnv('EXPERIMENTATION_CONFIG'); const clientSideId = assertEnv('LAUNCHDARKLY_CLIENT_SIDE_ID'); - // Optional: only used to build the dashboard deep-link (`origin`). The - // native Marketplace integration may not provide this. - const projectSlug = process.env.LAUNCHDARKLY_PROJECT_SLUG; + const projectSlug = assertEnv('LAUNCHDARKLY_PROJECT_SLUG'); defaultLaunchDarklyAdapter = createLaunchDarklyAdapter({ projectSlug,