From 38fb8f2e24eb41ba5b1cfef7eb5a9a8c3d9e7cdc Mon Sep 17 00:00:00 2001 From: Luis Meyer Date: Wed, 29 Jul 2026 11:47:03 +0200 Subject: [PATCH 1/5] Rename edge config packages --- .changeset/rename-global-config.md | 12 ++ .../docs/providers/custom-adapters.mdx | 2 +- .../content/docs/providers/edge-config.mdx | 14 +-- .../docs/content/docs/providers/hypertune.mdx | 4 +- examples/shirt-shop/package.json | 2 +- .../concepts/adapters/edge-config-adapter.ts | 8 +- examples/snippets/package.json | 2 +- .../CHANGELOG.md | 2 +- .../README.md | 8 +- .../package.json | 6 +- .../src/index.test.ts | 4 +- .../src/index.ts | 12 +- .../tsconfig.json | 0 .../tsup.config.js | 0 .../vitest.config.ts | 0 packages/adapter-growthbook/package.json | 2 +- packages/adapter-growthbook/src/index.ts | 2 +- packages/adapter-hypertune/package.json | 2 +- packages/adapter-hypertune/src/adapter.ts | 2 +- packages/adapter-launchdarkly/package.json | 2 +- .../adapter-launchdarkly/src/index.test.ts | 2 +- packages/adapter-launchdarkly/src/index.ts | 6 +- packages/adapter-statsig/package.json | 2 +- .../adapter-statsig/src/edge-runtime-hooks.ts | 4 +- pnpm-lock.yaml | 105 +++++++++++------- skills/flags-sdk/references/providers.md | 10 +- 26 files changed, 123 insertions(+), 92 deletions(-) create mode 100644 .changeset/rename-global-config.md rename packages/{adapter-edge-config => adapter-global-config}/CHANGELOG.md (97%) rename packages/{adapter-edge-config => adapter-global-config}/README.md (85%) rename packages/{adapter-edge-config => adapter-global-config}/package.json (89%) rename packages/{adapter-edge-config => adapter-global-config}/src/index.test.ts (98%) rename packages/{adapter-edge-config => adapter-global-config}/src/index.ts (86%) rename packages/{adapter-edge-config => adapter-global-config}/tsconfig.json (100%) rename packages/{adapter-edge-config => adapter-global-config}/tsup.config.js (100%) rename packages/{adapter-edge-config => adapter-global-config}/vitest.config.ts (100%) diff --git a/.changeset/rename-global-config.md b/.changeset/rename-global-config.md new file mode 100644 index 00000000..b290b7af --- /dev/null +++ b/.changeset/rename-global-config.md @@ -0,0 +1,12 @@ +--- +'@flags-sdk/global-config': minor +'@flags-sdk/growthbook': patch +'@flags-sdk/hypertune': patch +'@flags-sdk/launchdarkly': patch +'@flags-sdk/posthog': patch +'@flags-sdk/statsig': patch +--- + +Replace `@vercel/edge-config` with `@vercel/global-config`. + +Rename the Edge Config adapter package to `@flags-sdk/global-config`. diff --git a/apps/docs/content/docs/providers/custom-adapters.mdx b/apps/docs/content/docs/providers/custom-adapters.mdx index 92967e60..fc84e19a 100644 --- a/apps/docs/content/docs/providers/custom-adapters.mdx +++ b/apps/docs/content/docs/providers/custom-adapters.mdx @@ -27,7 +27,7 @@ Creating custom adapters is possible by creating an adapter factory: ```ts title="example-adapter.ts" import type { Adapter } from "flags"; -import { createClient, EdgeConfigClient } from "@vercel/edge-config"; +import { createClient, GlobalConfigClient } from "@vercel/global-config"; /** * A factory function for your adapter diff --git a/apps/docs/content/docs/providers/edge-config.mdx b/apps/docs/content/docs/providers/edge-config.mdx index ffd28cc4..b216f66b 100644 --- a/apps/docs/content/docs/providers/edge-config.mdx +++ b/apps/docs/content/docs/providers/edge-config.mdx @@ -2,7 +2,7 @@ title: 'Edge Config' --- -The `@flags-sdk/edge-config` package provides a basic adapter for defining feature flags powered by [Vercel Edge Config](https://vercel.com/docs/storage/edge-config) +The `@flags-sdk/global-config` package provides a basic adapter for defining feature flags powered by [Vercel Edge Config](https://vercel.com/docs/storage/edge-config) { it('default adapter should throw on usage when EDGE_CONFIG is not set', () => { expect(() => edgeConfigAdapter()).toThrowError( - '@flags-sdk/edge-config: Missing EDGE_CONFIG env var', + '@flags-sdk/global-config: Missing EDGE_CONFIG env var', ); }); diff --git a/packages/adapter-edge-config/src/index.ts b/packages/adapter-global-config/src/index.ts similarity index 86% rename from packages/adapter-edge-config/src/index.ts rename to packages/adapter-global-config/src/index.ts index 00ad87be..04c07a29 100644 --- a/packages/adapter-edge-config/src/index.ts +++ b/packages/adapter-global-config/src/index.ts @@ -1,4 +1,4 @@ -import { createClient, type EdgeConfigClient } from '@vercel/edge-config'; +import { createClient, type EdgeConfigClient } from '@vercel/global-config'; import type { Adapter, ReadonlyHeaders } from 'flags'; export type EdgeConfigFlags = { @@ -21,7 +21,7 @@ export function edgeConfigAdapter(): Adapter< // Initialized lazily to avoid warning when it is not actually used and env vars are missing. if (!defaultEdgeConfigAdapter) { if (!process.env.EDGE_CONFIG) { - throw new Error('@flags-sdk/edge-config: Missing EDGE_CONFIG env var'); + throw new Error('@flags-sdk/global-config: Missing EDGE_CONFIG env var'); } defaultEdgeConfigAdapter = createEdgeConfigAdapter(process.env.EDGE_CONFIG); @@ -47,7 +47,7 @@ export function createEdgeConfigAdapter( }, ) { if (!connectionString) { - throw new Error('@flags-sdk/edge-config: Missing connection string'); + throw new Error('@flags-sdk/global-config: Missing connection string'); } const edgeConfigClient = typeof connectionString === 'string' @@ -91,14 +91,14 @@ export function createEdgeConfigAdapter( // if a defaultValue was provided this error will be caught and the defaultValue will be used if (!definitions) { throw new Error( - `@flags-sdk/edge-config: Edge Config item "${edgeConfigItemKey}" not found`, + `@flags-sdk/global-config: Edge Config item "${edgeConfigItemKey}" not found`, ); } // if a defaultValue was provided this error will be caught and the defaultValue will be used if (!(key in definitions)) { throw new Error( - `@flags-sdk/edge-config: Flag "${key}" not found in Edge Config item "${edgeConfigItemKey}"`, + `@flags-sdk/global-config: Flag "${key}" not found in Edge Config item "${edgeConfigItemKey}"`, ); } return definitions[key]; @@ -108,7 +108,7 @@ export function createEdgeConfigAdapter( if (!definitions) { throw new Error( - `@flags-sdk/edge-config: Edge Config item "${edgeConfigItemKey}" not found`, + `@flags-sdk/global-config: Edge Config item "${edgeConfigItemKey}" not found`, ); } diff --git a/packages/adapter-edge-config/tsconfig.json b/packages/adapter-global-config/tsconfig.json similarity index 100% rename from packages/adapter-edge-config/tsconfig.json rename to packages/adapter-global-config/tsconfig.json diff --git a/packages/adapter-edge-config/tsup.config.js b/packages/adapter-global-config/tsup.config.js similarity index 100% rename from packages/adapter-edge-config/tsup.config.js rename to packages/adapter-global-config/tsup.config.js diff --git a/packages/adapter-edge-config/vitest.config.ts b/packages/adapter-global-config/vitest.config.ts similarity index 100% rename from packages/adapter-edge-config/vitest.config.ts rename to packages/adapter-global-config/vitest.config.ts diff --git a/packages/adapter-growthbook/package.json b/packages/adapter-growthbook/package.json index 0d0c5ae1..07dcc9d0 100644 --- a/packages/adapter-growthbook/package.json +++ b/packages/adapter-growthbook/package.json @@ -61,7 +61,7 @@ }, "dependencies": { "@growthbook/growthbook": "^1.5.1", - "@vercel/edge-config": "^1.4.3", + "@vercel/global-config": "^1.5.0", "@vercel/functions": "^1.5.2" }, "devDependencies": { diff --git a/packages/adapter-growthbook/src/index.ts b/packages/adapter-growthbook/src/index.ts index ba78f1a9..81533aa9 100644 --- a/packages/adapter-growthbook/src/index.ts +++ b/packages/adapter-growthbook/src/index.ts @@ -10,7 +10,7 @@ import { type TrackingCallbackWithUser, type UserContext, } from '@growthbook/growthbook'; -import { createClient } from '@vercel/edge-config'; +import { createClient } from '@vercel/global-config'; import { AsyncLocalStorage } from 'async_hooks'; import type { Adapter } from 'flags'; diff --git a/packages/adapter-hypertune/package.json b/packages/adapter-hypertune/package.json index 00df7008..0c5ef1cb 100644 --- a/packages/adapter-hypertune/package.json +++ b/packages/adapter-hypertune/package.json @@ -45,7 +45,7 @@ "type-check": "tsc --noEmit" }, "dependencies": { - "@vercel/edge-config": "^1.4.3", + "@vercel/global-config": "^1.5.0", "hypertune": "2.8.3" }, "devDependencies": { diff --git a/packages/adapter-hypertune/src/adapter.ts b/packages/adapter-hypertune/src/adapter.ts index 038aad39..f9c660f3 100644 --- a/packages/adapter-hypertune/src/adapter.ts +++ b/packages/adapter-hypertune/src/adapter.ts @@ -1,4 +1,4 @@ -import { createClient } from '@vercel/edge-config'; +import { createClient } from '@vercel/global-config'; import type { Adapter, FlagDeclaration, diff --git a/packages/adapter-launchdarkly/package.json b/packages/adapter-launchdarkly/package.json index 39c9a216..29c289f1 100644 --- a/packages/adapter-launchdarkly/package.json +++ b/packages/adapter-launchdarkly/package.json @@ -51,7 +51,7 @@ }, "dependencies": { "@launchdarkly/vercel-server-sdk": "^1.3.34", - "@vercel/edge-config": "^1.4.3" + "@vercel/global-config": "^1.5.0" }, "devDependencies": { "@types/node": "22.14.0", diff --git a/packages/adapter-launchdarkly/src/index.test.ts b/packages/adapter-launchdarkly/src/index.test.ts index 2bcb255b..09cde89f 100644 --- a/packages/adapter-launchdarkly/src/index.test.ts +++ b/packages/adapter-launchdarkly/src/index.test.ts @@ -12,7 +12,7 @@ vi.mock('@launchdarkly/vercel-server-sdk', () => ({ init: vi.fn(() => ldClientMock), })); -vi.mock('@vercel/edge-config', () => ({ +vi.mock('@vercel/global-config', () => ({ createClient: vi.fn(), })); diff --git a/packages/adapter-launchdarkly/src/index.ts b/packages/adapter-launchdarkly/src/index.ts index 54779a7e..38d0dce3 100644 --- a/packages/adapter-launchdarkly/src/index.ts +++ b/packages/adapter-launchdarkly/src/index.ts @@ -3,7 +3,7 @@ import { type LDClient, type LDContext, } from '@launchdarkly/vercel-server-sdk'; -import { createClient, type EdgeConfigClient } from '@vercel/edge-config'; +import { createClient, type GlobalConfigClient } from '@vercel/global-config'; import { AsyncLocalStorage } from 'async_hooks'; import type { Adapter } from 'flags'; @@ -50,7 +50,7 @@ export function createLaunchDarklyAdapter({ const store = new AsyncLocalStorage(); const cache = new WeakMap>(); - const patchedEdgeConfigClient: EdgeConfigClient = { + const patchedGlobalConfigClient: GlobalConfigClient = { ...edgeConfigClient, get: async (key: string) => { const h = store.getStore(); @@ -70,7 +70,7 @@ export function createLaunchDarklyAdapter({ let initPromise: Promise | null = null; - const ldClient = init(clientSideId, patchedEdgeConfigClient); + const ldClient = init(clientSideId, patchedGlobalConfigClient); function origin(key: string) { return `https://app.launchdarkly.com/projects/${projectSlug}/flags/${key}/`; diff --git a/packages/adapter-statsig/package.json b/packages/adapter-statsig/package.json index 3b4c6692..a345718c 100644 --- a/packages/adapter-statsig/package.json +++ b/packages/adapter-statsig/package.json @@ -63,7 +63,7 @@ "type-check": "tsc --noEmit" }, "dependencies": { - "@vercel/edge-config": "^1.4.3", + "@vercel/global-config": "^1.5.0", "@vercel/functions": "^1.5.2", "statsig-node-lite": "^0.5.2", "statsig-node-vercel": "^0.7.0" diff --git a/packages/adapter-statsig/src/edge-runtime-hooks.ts b/packages/adapter-statsig/src/edge-runtime-hooks.ts index e65cb03a..ce3a4d00 100644 --- a/packages/adapter-statsig/src/edge-runtime-hooks.ts +++ b/packages/adapter-statsig/src/edge-runtime-hooks.ts @@ -16,10 +16,10 @@ export async function createEdgeConfigDataAdapter(options: { edgeConfigItemKey: string; edgeConfigConnectionString: string; }) { - // Edge Config adapter requires `@vercel/edge-config` and `statsig-node-vercel` + // Edge Config adapter requires `@vercel/global-config` and `statsig-node-vercel` // Since it is a peer dependency, we will import it dynamically const { EdgeConfigDataAdapter } = await import('statsig-node-vercel'); - const { createClient } = await import('@vercel/edge-config'); + const { createClient } = await import('@vercel/global-config'); return new EdgeConfigDataAdapter({ edgeConfigItemKey: options.edgeConfigItemKey, edgeConfigClient: createClient(options.edgeConfigConnectionString, { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 09e19044..3e0aed95 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -259,9 +259,9 @@ importers: '@vercel/edge': specifier: 1.2.1 version: 1.2.1 - '@vercel/edge-config': - specifier: ^1.4.3 - version: 1.4.3(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + '@vercel/global-config': + specifier: ^1.5.0 + version: 1.5.0(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) '@vercel/toolbar': specifier: 0.2.7 version: 0.2.7(3524d3730989e44dd8751dbb901f98bf) @@ -326,9 +326,9 @@ importers: '@radix-ui/react-tooltip': specifier: 1.1.4 version: 1.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1) - '@vercel/edge-config': - specifier: ^1.4.3 - version: 1.4.3(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)) + '@vercel/global-config': + specifier: ^1.5.0 + version: 1.5.0(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1)) '@vercel/toolbar': specifier: 0.2.7 version: 0.2.7(e7aae08e340f7dd52d9ab2f16f5decad) @@ -434,11 +434,11 @@ importers: specifier: ^8.1.5 version: 8.1.5(@types/node@24.10.13)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0) - packages/adapter-edge-config: + packages/adapter-flagsmith: dependencies: - '@vercel/edge-config': - specifier: ^1.4.3 - version: 1.4.3(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.3.0-canary-fef12a01-20260413))(react@19.3.0-canary-fef12a01-20260413)) + flagsmith: + specifier: ^9.0.5 + version: 9.3.2 devDependencies: '@types/node': specifier: 22.14.0 @@ -446,6 +446,9 @@ importers: flags: specifier: workspace:* version: link:../flags + msw: + specifier: 2.6.4 + version: 2.6.4(@types/node@22.14.0)(typescript@5.6.3) rimraf: specifier: 6.1.2 version: 6.1.2 @@ -462,11 +465,11 @@ importers: specifier: 4.1.10 version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.14.0)(msw@2.6.4(@types/node@22.14.0)(typescript@5.6.3))(vite@8.1.5(@types/node@22.14.0)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)) - packages/adapter-flagsmith: + packages/adapter-global-config: dependencies: - flagsmith: - specifier: ^9.0.5 - version: 9.3.2 + '@vercel/global-config': + specifier: ^1.5.0 + version: 1.5.0(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.3.0-canary-fef12a01-20260413))(react@19.3.0-canary-fef12a01-20260413)) devDependencies: '@types/node': specifier: 22.14.0 @@ -474,9 +477,6 @@ importers: flags: specifier: workspace:* version: link:../flags - msw: - specifier: 2.6.4 - version: 2.6.4(@types/node@22.14.0)(typescript@5.6.3) rimraf: specifier: 6.1.2 version: 6.1.2 @@ -498,12 +498,12 @@ importers: '@growthbook/growthbook': specifier: ^1.5.1 version: 1.6.1 - '@vercel/edge-config': - specifier: ^1.4.3 - version: 1.4.3(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.3.0-canary-fef12a01-20260413))(react@19.3.0-canary-fef12a01-20260413)) '@vercel/functions': specifier: ^1.5.2 version: 1.6.0 + '@vercel/global-config': + specifier: ^1.5.0 + version: 1.5.0(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.3.0-canary-fef12a01-20260413))(react@19.3.0-canary-fef12a01-20260413)) devDependencies: '@types/node': specifier: 22.14.0 @@ -532,9 +532,9 @@ importers: packages/adapter-hypertune: dependencies: - '@vercel/edge-config': - specifier: ^1.4.3 - version: 1.4.3(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.3.0-canary-fef12a01-20260413))(react@19.3.0-canary-fef12a01-20260413)) + '@vercel/global-config': + specifier: ^1.5.0 + version: 1.5.0(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.3.0-canary-fef12a01-20260413))(react@19.3.0-canary-fef12a01-20260413)) hypertune: specifier: 2.8.3 version: 2.8.3 @@ -569,9 +569,9 @@ importers: '@launchdarkly/vercel-server-sdk': specifier: ^1.3.34 version: 1.3.34(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.3.0-canary-fef12a01-20260413))(react@19.3.0-canary-fef12a01-20260413)) - '@vercel/edge-config': - specifier: ^1.4.3 - version: 1.4.3(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.3.0-canary-fef12a01-20260413))(react@19.3.0-canary-fef12a01-20260413)) + '@vercel/global-config': + specifier: ^1.5.0 + version: 1.5.0(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.3.0-canary-fef12a01-20260413))(react@19.3.0-canary-fef12a01-20260413)) devDependencies: '@types/node': specifier: 22.14.0 @@ -746,12 +746,12 @@ importers: packages/adapter-statsig: dependencies: - '@vercel/edge-config': - specifier: ^1.4.3 - version: 1.4.3(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.3.0-canary-fef12a01-20260413))(react@19.3.0-canary-fef12a01-20260413)) '@vercel/functions': specifier: ^1.5.2 version: 1.6.0 + '@vercel/global-config': + specifier: ^1.5.0 + version: 1.5.0(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.3.0-canary-fef12a01-20260413))(react@19.3.0-canary-fef12a01-20260413)) statsig-node-lite: specifier: ^0.5.2 version: 0.5.2 @@ -4697,6 +4697,18 @@ packages: react-dom: ^19.2.3 tailwindcss: ^4.1.17 + '@vercel/global-config@1.5.0': + resolution: {integrity: sha512-YxyyzkIjlD7kHSlPpYOQun81Y1o3JUU19snytzFSex/l6h6t5kEg9UsWoG7F5BIT1aBcCmTGUtP5LpkeSN+b8w==} + engines: {node: '>=14.6'} + peerDependencies: + '@opentelemetry/api': ^1.7.0 + next: '>=1' + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + next: + optional: true + '@vercel/microfrontends@2.4.0': resolution: {integrity: sha512-dpUzyjpLtE40gB+vxU3AWy5Dlkx/O91joVc/Q7PTYTtHVmw7ZkKgbR0QFEQJC0kw6SXOb35q46QN1BVwVRL5DQ==} hasBin: true @@ -12695,20 +12707,6 @@ snapshots: '@vercel/edge-config-fs@0.1.0': {} - '@vercel/edge-config@1.4.3(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1))': - dependencies: - '@vercel/edge-config-fs': 0.1.0 - optionalDependencies: - '@opentelemetry/api': 1.9.0 - next: 16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1) - - '@vercel/edge-config@1.4.3(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))': - dependencies: - '@vercel/edge-config-fs': 0.1.0 - optionalDependencies: - '@opentelemetry/api': 1.9.0 - next: 16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@vercel/edge-config@1.4.3(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.3.0-canary-fef12a01-20260413))(react@19.3.0-canary-fef12a01-20260413))': dependencies: '@vercel/edge-config-fs': 0.1.0 @@ -12782,6 +12780,27 @@ snapshots: - vite - waku + '@vercel/global-config@1.5.0(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1))': + dependencies: + '@vercel/edge-config-fs': 0.1.0 + optionalDependencies: + '@opentelemetry/api': 1.9.0 + next: 16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1) + + '@vercel/global-config@1.5.0(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))': + dependencies: + '@vercel/edge-config-fs': 0.1.0 + optionalDependencies: + '@opentelemetry/api': 1.9.0 + next: 16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + + '@vercel/global-config@1.5.0(@opentelemetry/api@1.9.0)(next@16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.3.0-canary-fef12a01-20260413))(react@19.3.0-canary-fef12a01-20260413))': + dependencies: + '@vercel/edge-config-fs': 0.1.0 + optionalDependencies: + '@opentelemetry/api': 1.9.0 + next: 16.2.12(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.3.0-canary-fef12a01-20260413))(react@19.3.0-canary-fef12a01-20260413) + '@vercel/microfrontends@2.4.0(2703fe56f3fdc60e9aff457d6c92bf11)': dependencies: '@next/env': 16.0.10 diff --git a/skills/flags-sdk/references/providers.md b/skills/flags-sdk/references/providers.md index f1737f77..81b8c289 100644 --- a/skills/flags-sdk/references/providers.md +++ b/skills/flags-sdk/references/providers.md @@ -194,10 +194,10 @@ Full CLI reference: https://vercel.com/docs/cli/flags ## Edge Config -Package: `@flags-sdk/edge-config` +Package: `@flags-sdk/global-config` ```bash -pnpm i @flags-sdk/edge-config +pnpm i @flags-sdk/global-config ``` Env: `EDGE_CONFIG="edge-config-connection-string"` @@ -206,7 +206,7 @@ Env: `EDGE_CONFIG="edge-config-connection-string"` ```ts import { flag } from 'flags/next'; -import { edgeConfigAdapter } from '@flags-sdk/edge-config'; +import { edgeConfigAdapter } from '@flags-sdk/global-config'; export const exampleFlag = flag({ adapter: edgeConfigAdapter, @@ -228,7 +228,7 @@ Edge Config should contain: ### Custom configuration ```ts -import { createEdgeConfigAdapter } from '@flags-sdk/edge-config'; +import { createEdgeConfigAdapter } from '@flags-sdk/global-config'; const myAdapter = createEdgeConfigAdapter({ connectionString: process.env.OTHER_EDGE_CONFIG, @@ -505,7 +505,7 @@ growthbookAdapter.setTrackingCallback((experiment, result) => { Package: `@flags-sdk/hypertune` ```bash -pnpm i hypertune flags server-only @flags-sdk/hypertune @vercel/edge-config +pnpm i hypertune flags server-only @flags-sdk/hypertune @vercel/global-config ``` Requires code generation: `npx hypertune` From 1deb0e6813714c15fd08a87c68fef7c8185af2de Mon Sep 17 00:00:00 2001 From: Luis Meyer Date: Wed, 29 Jul 2026 12:57:57 +0200 Subject: [PATCH 2/5] Rename Global Config APIs --- .changeset/rename-global-config.md | 10 +- apps/docs/components/custom/provider-list.tsx | 12 +- .../next/guides/dashboard-pages.mdx | 2 +- .../content/docs/principles/data-locality.mdx | 10 +- .../docs/providers/custom-adapters.mdx | 20 ++-- .../content/docs/providers/edge-config.mdx | 108 ----------------- .../content/docs/providers/global-config.mdx | 108 +++++++++++++++++ .../content/docs/providers/growthbook.mdx | 34 +++--- .../docs/content/docs/providers/hypertune.mdx | 10 +- apps/docs/content/docs/providers/index.mdx | 6 +- .../content/docs/providers/launchdarkly.mdx | 24 ++-- apps/docs/content/docs/providers/meta.json | 2 +- .../docs/providers/openfeature/abtasty.mdx | 2 +- .../docs/providers/openfeature/cloudbees.mdx | 2 +- .../openfeature/confidence-by-spotify.mdx | 2 +- .../docs/providers/openfeature/configcat.mdx | 2 +- .../docs/providers/openfeature/devcycle.mdx | 2 +- .../docs/providers/openfeature/featbit.mdx | 2 +- .../docs/providers/openfeature/flagd.mdx | 2 +- .../docs/providers/openfeature/flipt.mdx | 2 +- .../content/docs/providers/openfeature/go.mdx | 2 +- .../docs/providers/openfeature/growthbook.mdx | 2 +- .../docs/providers/openfeature/hypertune.mdx | 2 +- .../docs/providers/openfeature/index.mdx | 10 +- .../docs/providers/openfeature/kameloon.mdx | 2 +- .../docs/providers/openfeature/posthog.mdx | 2 +- .../docs/providers/openfeature/split.mdx | 2 +- .../docs/providers/openfeature/tggl.mdx | 2 +- apps/docs/content/docs/providers/statsig.mdx | 18 +-- apps/docs/next.config.ts | 4 +- .../snippets/app/concepts/adapters/flags.tsx | 8 +- ...ig-adapter.ts => global-config-adapter.ts} | 24 ++-- .../app/examples/dashboard-pages/flags.ts | 2 +- packages/adapter-global-config/README.md | 22 ++-- .../adapter-global-config/src/index.test.ts | 100 ++++++++-------- packages/adapter-global-config/src/index.ts | 72 +++++------ packages/adapter-growthbook/src/index.ts | 113 +++++++++--------- packages/adapter-hypertune/README.md | 2 +- packages/adapter-hypertune/src/adapter.ts | 4 +- packages/adapter-launchdarkly/README.md | 14 +-- packages/adapter-launchdarkly/package.json | 2 +- packages/adapter-launchdarkly/src/index.ts | 14 +-- packages/adapter-reflag/package.json | 2 +- packages/adapter-statsig/package.json | 2 +- .../adapter-statsig/src/edge-runtime-hooks.ts | 24 ++-- packages/adapter-statsig/src/index.ts | 32 ++--- packages/flags/src/types.ts | 6 +- .../vercel-flags-core/src/index.default.ts | 2 +- skills/flags-sdk/SKILL.md | 4 +- skills/flags-sdk/references/providers.md | 26 ++-- 50 files changed, 447 insertions(+), 436 deletions(-) delete mode 100644 apps/docs/content/docs/providers/edge-config.mdx create mode 100644 apps/docs/content/docs/providers/global-config.mdx rename examples/snippets/app/concepts/adapters/{edge-config-adapter.ts => global-config-adapter.ts} (61%) diff --git a/.changeset/rename-global-config.md b/.changeset/rename-global-config.md index b290b7af..93eac5dd 100644 --- a/.changeset/rename-global-config.md +++ b/.changeset/rename-global-config.md @@ -1,12 +1,14 @@ --- '@flags-sdk/global-config': minor -'@flags-sdk/growthbook': patch +'@flags-sdk/growthbook': major '@flags-sdk/hypertune': patch -'@flags-sdk/launchdarkly': patch +'@flags-sdk/launchdarkly': major '@flags-sdk/posthog': patch -'@flags-sdk/statsig': patch +'@flags-sdk/reflag': patch +'@flags-sdk/statsig': major +'flags': major --- Replace `@vercel/edge-config` with `@vercel/global-config`. -Rename the Edge Config adapter package to `@flags-sdk/global-config`. +Rename the Edge Config adapter package to `@flags-sdk/global-config` and rename repository-owned Edge Config files, exports, types, options, variables, and environment variables to Global Config. diff --git a/apps/docs/components/custom/provider-list.tsx b/apps/docs/components/custom/provider-list.tsx index 8d387ab8..921885ea 100644 --- a/apps/docs/components/custom/provider-list.tsx +++ b/apps/docs/components/custom/provider-list.tsx @@ -44,7 +44,7 @@ const providers: Provider[] = [ name: 'Vercel', href: '/providers/vercel', logo: VercelLogo, - badges: ['Adapter', 'Edge Config', 'Flags Explorer'], + badges: ['Adapter', 'Global Config', 'Flags Explorer'], glowColor: '#000000', skipInvert: true, }, @@ -53,7 +53,7 @@ const providers: Provider[] = [ name: 'Statsig', href: '/providers/statsig', logo: StatsigLogo, - badges: ['Adapter', 'Edge Config', 'Flags Explorer', 'Marketplace'], + badges: ['Adapter', 'Global Config', 'Flags Explorer', 'Marketplace'], glowColor: '#1b63d2', }, { @@ -61,7 +61,7 @@ const providers: Provider[] = [ name: 'Hypertune', href: '/providers/hypertune', logo: HypertuneLogo, - badges: ['Adapter', 'Edge Config', 'Flags Explorer', 'Marketplace'], + badges: ['Adapter', 'Global Config', 'Flags Explorer', 'Marketplace'], glowColor: '#000000', }, { @@ -69,7 +69,7 @@ const providers: Provider[] = [ name: 'LaunchDarkly', href: '/providers/launchdarkly', logo: LaunchDarklyLogo, - badges: ['Adapter', 'Edge Config', 'Flags Explorer'], + badges: ['Adapter', 'Global Config', 'Flags Explorer'], glowColor: '#7084ff', }, { @@ -77,7 +77,7 @@ const providers: Provider[] = [ name: 'GrowthBook', href: '/providers/growthbook', logo: GrowthbookLogo, - badges: ['Adapter', 'Edge Config', 'Flags Explorer', 'Marketplace'], + badges: ['Adapter', 'Global Config', 'Flags Explorer', 'Marketplace'], glowColor: '#7B51FB', }, { @@ -127,7 +127,7 @@ const providers: Provider[] = [ // name: 'Split', // href: '/providers/split', // logo: SplitLogo, - // badges: ['Edge Config', 'Flags Explorer'], + // badges: ['Global Config', 'Flags Explorer'], // glowColor: '#ff00d2', // }, ]; diff --git a/apps/docs/content/docs/frameworks/next/guides/dashboard-pages.mdx b/apps/docs/content/docs/frameworks/next/guides/dashboard-pages.mdx index c11f6db5..b3d40412 100644 --- a/apps/docs/content/docs/frameworks/next/guides/dashboard-pages.mdx +++ b/apps/docs/content/docs/frameworks/next/guides/dashboard-pages.mdx @@ -41,7 +41,7 @@ export const dashboardFlag = flag({ identify, decide({ entities }) { if (!entities?.user) return false; - // Allowed users could be loaded from Edge Config or elsewhere + // Allowed users could be loaded from Global Config or elsewhere const allowedUsers = ['user1']; return allowedUsers.includes(entities.user.id); diff --git a/apps/docs/content/docs/principles/data-locality.mdx b/apps/docs/content/docs/principles/data-locality.mdx index 87f98bcd..e41872c2 100644 --- a/apps/docs/content/docs/principles/data-locality.mdx +++ b/apps/docs/content/docs/principles/data-locality.mdx @@ -51,17 +51,17 @@ applications need to pay the latency cost of bootstrapping feature flags more frequently. Having multiple websocket connections to the same flag provider also increases load on the provider. -## Vercel Edge Config +## Vercel Global Config -Vercel offers a solution called Edge Config to this problem. It is -specifically designed for storing feature flag definitions. Edge Config +Vercel offers a solution called Global Config to this problem. It is +specifically designed for storing feature flag definitions. Global Config can be read in under 1ms at p90 and under 15ms at p95, including the network latency from your Serverless Function or Routing Middleware. To put this into perspective, [according to this benchmark](https://github.com/dvassallo/s3-benchmark), an AWS S3 bucket does not even send the first byte by the time an Edge Config is fully read. -Using Edge Config is optional, but highly recommended, when using the +Using Global Config is optional, but highly recommended, when using the Flags SDK. ## Evaluating on the server @@ -79,7 +79,7 @@ request to establish the evaluation context. To evaluate feature flags at the edge, you need the definition and the evaluation context available at the edge. -Using Edge Config allows storing definitions at the Edge as shown in the +Using Global Config allows storing definitions at the Edge as shown in the previous section. This means you can use feature flags in Routing Functions at ultra low latency. diff --git a/apps/docs/content/docs/providers/custom-adapters.mdx b/apps/docs/content/docs/providers/custom-adapters.mdx index fc84e19a..472fe548 100644 --- a/apps/docs/content/docs/providers/custom-adapters.mdx +++ b/apps/docs/content/docs/providers/custom-adapters.mdx @@ -108,7 +108,7 @@ return { ## Example -Below is an example of an Flags SDK adapter reading Edge Config. +Below is an example of an Flags SDK adapter reading Global Config. +let defaultGlobalConfigAdapter: + | ReturnType | undefined; /** - * A default Vercel adapter for Edge Config + * A default Vercel adapter for Global Config * */ -export function edgeConfigAdapter(): Adapter< +export function globalConfigAdapter(): Adapter< ValueType, EntitiesType > { // Initialized lazily to avoid warning when it is not actually used and env vars are missing. - if (!defaultEdgeConfigAdapter) { - if (!process.env.EDGE_CONFIG) { - throw new Error("Edge Config Adapter: Missing EDGE_CONFIG env var"); + if (!defaultGlobalConfigAdapter) { + if (!process.env.GLOBAL_CONFIG) { + throw new Error("Global Config Adapter: Missing GLOBAL_CONFIG env var"); } - defaultEdgeConfigAdapter = createEdgeConfigAdapter(process.env.EDGE_CONFIG); + defaultGlobalConfigAdapter = createGlobalConfigAdapter(process.env.GLOBAL_CONFIG); } - return defaultEdgeConfigAdapter(); + return defaultGlobalConfigAdapter(); } ``` diff --git a/apps/docs/content/docs/providers/edge-config.mdx b/apps/docs/content/docs/providers/edge-config.mdx deleted file mode 100644 index b216f66b..00000000 --- a/apps/docs/content/docs/providers/edge-config.mdx +++ /dev/null @@ -1,108 +0,0 @@ ---- -title: 'Edge Config' ---- - -The `@flags-sdk/global-config` package provides a basic adapter for defining feature flags powered by [Vercel Edge Config](https://vercel.com/docs/storage/edge-config) - - - Learn more about Adapters - - -## Installation - -Follow the [Quickstart](/docs/getting-started/next), then add the [Edge Config adapter](https://github.com/vercel/flags/tree/main/packages/adapter-global-config). - -Install desired dependencies - -```sh -pnpm i @flags-sdk/global-config -``` - -Set relevant variables - -```sh title=".env.local" -EDGE_CONFIG="edge-config-connection-string" -``` - -## Usage - -```ts title="flags.ts#next" -import { flag } from 'flags/next'; -import { edgeConfigAdapter } from '@flags-sdk/global-config'; - -export const exampleFlag = flag({ - // Will load the `flags` key from Edge Config - adapter: edgeConfigAdapter, - // Will get the `example-flag` key from the `flags` object - key: 'example-flag', -}); -``` - -Your Edge Config should be [managed on the dashboard](https://vercel.com/docs/storage/edge-config/edge-config-dashboard) as follows: - -```json -{ - // `flags` is the default used by the Edge Config adapter - "flags": { - // Flags using the adapter should have their `key` defined here - "example-flag": true, - "another-example-flag": false, - } -} -``` - -## API reference - -### edgeConfigAdapter - -The adapter assumes that there is an `EDGE_CONFIG` environment variable set with a connection string, -and that it contains a `flags` object with each key corresponding to a flag you define in code. - -```ts title="flags.ts#next" -import { edgeConfigAdapter } from '@flags-sdk/global-config'; - -export const exampleFlag = flag({ - adapter: edgeConfigAdapter, - key: 'example-flag', -}); -``` - -### createEdgeConfigAdapter - -To customize these options you can import and call `createEdgeConfigAdapter` manually. - -| Option key | Type | Description | -| ----------- | -------- | ----------------------- | -| `connectionString` | `string | GlobalConfigClient` | A [connection string](https://vercel.com/docs/storage/edge-config/using-edge-config#using-a-connection-string) or a [client instance](https://vercel.com/docs/storage/edge-config/edge-config-sdk#use-connection-strings) | -| `options.edgeConfigItemKey` | `string` | Defaults to `flags` | -| `options.teamSlug` | `string` | The team slug used for your team in the Vercel dashboard, used to create links to your Edge Config | - -```ts title="flags.ts#next" -import { createEdgeConfigAdapter } from '@flags-sdk/global-config'; - -const myEdgeConfigAdapter = createEdgeConfigAdapter({ - connectionString: process.env.OTHER_EDGE_CONFIG_CONNECTION_STRING, - options: { - edgeConfigItemKey: 'other-flags-key', - teamSlug: 'my-vercel-team-slug', - }, -}); - -export const exampleFlag = flag({ - adapter: myEdgeConfigAdapter, - key: 'example-flag', -}); -``` - -## Read more - -Read more about Edge Config, Flags SDK, and the Edge Config adapter. - -- [Concepts: Precompute](/principles/precompute) -- [Edge Config Docs](https://vercel.com/docs/storage/edge-config) -- [Edge Config SDK Reference](https://vercel.com/docs/storage/edge-config/edge-config-sdk) -- [Edge Config Examples](https://vercel.com/templates/edge-config) -- [Edge Config Limits and Pricing](https://vercel.com/docs/storage/edge-config/edge-config-limits) diff --git a/apps/docs/content/docs/providers/global-config.mdx b/apps/docs/content/docs/providers/global-config.mdx new file mode 100644 index 00000000..68caf120 --- /dev/null +++ b/apps/docs/content/docs/providers/global-config.mdx @@ -0,0 +1,108 @@ +--- +title: 'Global Config' +--- + +The `@flags-sdk/global-config` package provides a basic adapter for defining feature flags powered by [Vercel Global Config](https://vercel.com/docs/storage/edge-config) + + + Learn more about Adapters + + +## Installation + +Follow the [Quickstart](/docs/getting-started/next), then add the [Global Config adapter](https://github.com/vercel/flags/tree/main/packages/adapter-global-config). + +Install desired dependencies + +```sh +pnpm i @flags-sdk/global-config +``` + +Set relevant variables + +```sh title=".env.local" +GLOBAL_CONFIG="global-config-connection-string" +``` + +## Usage + +```ts title="flags.ts#next" +import { flag } from 'flags/next'; +import { globalConfigAdapter } from '@flags-sdk/global-config'; + +export const exampleFlag = flag({ + // Will load the `flags` key from Global Config + adapter: globalConfigAdapter, + // Will get the `example-flag` key from the `flags` object + key: 'example-flag', +}); +``` + +Your Global Config should be [managed on the dashboard](https://vercel.com/docs/storage/edge-config/edge-config-dashboard) as follows: + +```json +{ + // `flags` is the default used by the Global Config adapter + "flags": { + // Flags using the adapter should have their `key` defined here + "example-flag": true, + "another-example-flag": false, + } +} +``` + +## API reference + +### globalConfigAdapter + +The adapter assumes that there is an `GLOBAL_CONFIG` environment variable set with a connection string, +and that it contains a `flags` object with each key corresponding to a flag you define in code. + +```ts title="flags.ts#next" +import { globalConfigAdapter } from '@flags-sdk/global-config'; + +export const exampleFlag = flag({ + adapter: globalConfigAdapter, + key: 'example-flag', +}); +``` + +### createGlobalConfigAdapter + +To customize these options you can import and call `createGlobalConfigAdapter` manually. + +| Option key | Type | Description | +| ----------- | -------- | ----------------------- | +| `connectionString` | `string | GlobalConfigClient` | A [connection string](https://vercel.com/docs/storage/edge-config/using-edge-config#using-a-connection-string) or a [client instance](https://vercel.com/docs/storage/edge-config/edge-config-sdk#use-connection-strings) | +| `options.globalConfigItemKey` | `string` | Defaults to `flags` | +| `options.teamSlug` | `string` | The team slug used for your team in the Vercel dashboard, used to create links to your Global Config | + +```ts title="flags.ts#next" +import { createGlobalConfigAdapter } from '@flags-sdk/global-config'; + +const myGlobalConfigAdapter = createGlobalConfigAdapter({ + connectionString: process.env.OTHER_GLOBAL_CONFIG_CONNECTION_STRING, + options: { + globalConfigItemKey: 'other-flags-key', + teamSlug: 'my-vercel-team-slug', + }, +}); + +export const exampleFlag = flag({ + adapter: myGlobalConfigAdapter, + key: 'example-flag', +}); +``` + +## Read more + +Read more about Global Config, Flags SDK, and the Global Config adapter. + +- [Concepts: Precompute](/principles/precompute) +- [Global Config Docs](https://vercel.com/docs/storage/edge-config) +- [Global Config SDK Reference](https://vercel.com/docs/storage/edge-config/edge-config-sdk) +- [Global Config Examples](https://vercel.com/templates/edge-config) +- [Global Config Limits and Pricing](https://vercel.com/docs/storage/edge-config/edge-config-limits) diff --git a/apps/docs/content/docs/providers/growthbook.mdx b/apps/docs/content/docs/providers/growthbook.mdx index 2a495cd8..b5d6c2f5 100644 --- a/apps/docs/content/docs/providers/growthbook.mdx +++ b/apps/docs/content/docs/providers/growthbook.mdx @@ -2,7 +2,7 @@ title: 'GrowthBook' --- -The GrowthBook adapter integrates [GrowthBook](https://www.growthbook.io/) with the Flags SDK, enabling feature flagging, experimentation, and configuration management in your application. This adapter lets you evaluate feature flags and experiments, with support for server-side, client-side, and Edge Config bootstrapping. +The GrowthBook adapter integrates [GrowthBook](https://www.growthbook.io/) with the Flags SDK, enabling feature flagging, experimentation, and configuration management in your application. This adapter lets you evaluate feature flags and experiments, with support for server-side, client-side, and Global Config bootstrapping. GrowthBook is an open-source feature flagging and experimentation platform that helps you safely roll out features, run A/B tests, and manage configuration at scale. @@ -41,9 +41,9 @@ The default adapter considers the following environment variables: | `GROWTHBOOK_CLIENT_KEY` | **Required.** GrowthBook SDK key | | `GROWTHBOOK_API_HOST` | Optional. Override the GrowthBook API endpoint | | `GROWTHBOOK_APP_ORIGIN` | Optional. Override the GrowthBook app URL | -| `GROWTHBOOK_EDGE_CONNECTION_STRING` | Optional. Edge Config connection string | -| `GROWTHBOOK_EDGE_CONFIG_ITEM_KEY` | Optional. Edge Config item key (Defaults to your client key) | -| `EXPERIMENTATION_CONFIG` | Optional. Used when installed through Vercel Marketplace (replaces GROWTHBOOK_EDGE_CONNECTION_STRING) | +| `GROWTHBOOK_GLOBAL_CONFIG_CONNECTION_STRING` | Optional. Global Config connection string | +| `GROWTHBOOK_GLOBAL_CONFIG_ITEM_KEY` | Optional. Global Config item key (Defaults to your client key) | +| `EXPERIMENTATION_CONFIG` | Optional. Used when installed through Vercel Marketplace (replaces GROWTHBOOK_GLOBAL_CONFIG_CONNECTION_STRING) | ### Create a custom adapter @@ -56,9 +56,9 @@ const myGrowthBookAdapter = createGrowthbookAdapter({ clientKey: process.env.GROWTHBOOK_CLIENT_KEY!, apiHost: process.env.GROWTHBOOK_API_HOST, // optional appOrigin: process.env.GROWTHBOOK_APP_ORIGIN, // optional - edgeConfig: { - connectionString: process.env.GROWTHBOOK_EDGE_CONNECTION_STRING!, - itemKey: process.env.GROWTHBOOK_EDGE_CONFIG_ITEM_KEY, // optional + globalConfig: { + connectionString: process.env.GROWTHBOOK_GLOBAL_CONFIG_CONNECTION_STRING!, + itemKey: process.env.GROWTHBOOK_GLOBAL_CONFIG_ITEM_KEY, // optional }, trackingCallback: (experiment, result) => { // Custom exposure logging @@ -174,21 +174,21 @@ You may access the underlying GrowthBook instance. Specifically, the GrowthBook If you have set a sticky bucket service, you may retrieve its instance here. -## Edge Config +## Global Config -The adapter can load feature configuration from [Vercel Edge Config](https://vercel.com/docs/storage/edge-config) to lower the latency of feature flag evaluation. +The adapter can load feature configuration from [Vercel Global Config](https://vercel.com/docs/storage/edge-config) to lower the latency of feature flag evaluation. -- Set `GROWTHBOOK_EDGE_CONNECTION_STRING` (or `EXPERIMENTATION_CONFIG` if installed through the Vercel Marketplace) in your environment. Optionally set `GROWTHBOOK_EDGE_CONFIG_ITEM_KEY` to override the default key name (defaults to your client key). -- Or pass `edgeConfig` directly to the adapter. +- Set `GROWTHBOOK_GLOBAL_CONFIG_CONNECTION_STRING` (or `EXPERIMENTATION_CONFIG` if installed through the Vercel Marketplace) in your environment. Optionally set `GROWTHBOOK_GLOBAL_CONFIG_ITEM_KEY` to override the default key name (defaults to your client key). +- Or pass `globalConfig` directly to the adapter. -If Edge Config is not set, the adapter will fetch configuration from GrowthBook's API. +If Global Config is not set, the adapter will fetch configuration from GrowthBook's API. ### Configuring a SDK Webhook -1. To automatically populate the Edge Config whenever your feature definitions change, create a GrowthBook [SDK Webhook](https://docs.growthbook.io/app/webhooks/sdk-webhooks) on the same SDK Connection that you are using for the Next.js integration.ts +1. To automatically populate the Global Config whenever your feature definitions change, create a GrowthBook [SDK Webhook](https://docs.growthbook.io/app/webhooks/sdk-webhooks) on the same SDK Connection that you are using for the Next.js integration.ts -2. Select "Vercel Edge Config" as the webhook type and fill out the following fields: -- Vercel Edge Config ID (begins with `ecfg_`) +2. Select "Vercel Global Config" as the webhook type and fill out the following fields: +- Vercel Global Config ID (begins with `ecfg_`) - Team ID (optional) - Vercel API Token (see Vercel → Account Settings → Tokens) @@ -200,7 +200,7 @@ Under the hood, the webhook is being configured with the following properties. I ``` - **Method** is being set to `PATCH` - An **Authorization: Bearer token** header is being added with your Vercel API Token -- The **Payload format** is being set to `Vercel Edge Config` +- The **Payload format** is being set to `Vercel Global Config` ## Caveats and best practices @@ -233,6 +233,6 @@ export const GET = createFlagsDiscoveryEndpoint(async (request) => { - [GrowthBook Documentation](https://docs.growthbook.io/) - [GrowthBook JS SDK Reference](https://docs.growthbook.io/lib/js) -- [Vercel Edge Config](https://vercel.com/docs/storage/edge-config) +- [Vercel Global Config](https://vercel.com/docs/storage/edge-config) - [Flags Explorer](https://vercel.com/docs/flags/flags-explorer) - [Deploy the GrowthBook template](https://vercel.com/templates/next.js/growthbook-flags-sdk-example) diff --git a/apps/docs/content/docs/providers/hypertune.mdx b/apps/docs/content/docs/providers/hypertune.mdx index b5cafdc7..33097117 100644 --- a/apps/docs/content/docs/providers/hypertune.mdx +++ b/apps/docs/content/docs/providers/hypertune.mdx @@ -98,9 +98,9 @@ export const GET = createFlagsDiscoveryEndpoint(() => { Learn more about the Flags Explorer -## How to configure Edge Config +## How to configure Global Config -If Hypertune is syncing to Vercel Edge Config, you can configure that through environment variables or through the adapter. +If Hypertune is syncing to Vercel Global Config, you can configure that through environment variables or through the adapter. ```bash title=".env.local" EXPERIMENTATION_CONFIG="https://edge-config.vercel.com/ecfg_xyz?token=abc" @@ -108,7 +108,7 @@ EXPERIMENTATION_CONFIG_ITEM_KEY="hypertune_99999" ``` ```ts title="flags.ts" -import { VercelEdgeConfigInitDataProvider } from 'hypertune' +import { VercelEdgeConfigInitDataProvider as VercelGlobalConfigInitDataProvider } from 'hypertune' import { createClient } from "@vercel/global-config" const hypertuneAdapter = createHypertuneAdapter< @@ -117,7 +117,7 @@ const hypertuneAdapter = createHypertuneAdapter< >({ // ... previous initialization code createSourceOptions: { - initDataProvider: new VercelEdgeConfigInitDataProvider({ + initDataProvider: new VercelGlobalConfigInitDataProvider({ edgeConfigClient: createClient( 'https://edge-config.vercel.com/ecfg_xyz?token=abc' ), @@ -130,6 +130,6 @@ const hypertuneAdapter = createHypertuneAdapter< ## More resources - [Hypertune Documentation](https://docs.hypertune.com/) -- [Vercel Edge Config](https://vercel.com/docs/edge-config) +- [Vercel Global Config](https://vercel.com/docs/edge-config) - [Flags Explorer](https://vercel.com/docs/flags/flags-explorer) - [Hypertune OpenFeature Provider](/providers/openfeature/hypertune) diff --git a/apps/docs/content/docs/providers/index.mdx b/apps/docs/content/docs/providers/index.mdx index 6f988fb1..f3bca0ca 100644 --- a/apps/docs/content/docs/providers/index.mdx +++ b/apps/docs/content/docs/providers/index.mdx @@ -11,14 +11,14 @@ your provider or in case you have an in-house solution for feature flags. ## Featured providers Featured providers offer fast setup using [Vercel Marketplace](https://vercel.com/marketplace/category/experimentation), -and low latency with Edge Config. They also work well outside of Vercel in Next.js and SvelteKit projects. +and low latency with Global Config. They also work well outside of Vercel in Next.js and SvelteKit projects. ## Additional providers Additional providers are published under the `@flags-sdk` npm scope in the [Flags SDK repository](https://github.com/vercel/flags) and offer different levels of -integration with Next.js, SvelteKit, and Edge Config. +integration with Next.js, SvelteKit, and Global Config. @@ -26,4 +26,4 @@ integration with Next.js, SvelteKit, and Edge Config. - **Adapter** - Lets you evaluate feature flags and experiments using the Flags SDK. - **Flags Explorer** - Displays flag metadata like descriptions in the [Flags Explorer](https://vercel.com/docs/flags/flags-explorer). - **Marketplace** - Available in the Vercel Marketplace. -- **Edge Config** - Lets you read feature flags from an Edge Config. +- **Global Config** - Lets you read feature flags from an Global Config. diff --git a/apps/docs/content/docs/providers/launchdarkly.mdx b/apps/docs/content/docs/providers/launchdarkly.mdx index b367d232..7bbc9c98 100644 --- a/apps/docs/content/docs/providers/launchdarkly.mdx +++ b/apps/docs/content/docs/providers/launchdarkly.mdx @@ -49,10 +49,10 @@ 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` + // Legacy integrations that provide the connection string as `GLOBAL_CONFIG` // can pass it explicitly here. - edgeConfigConnectionString: - process.env.EXPERIMENTATION_CONFIG ?? process.env.EDGE_CONFIG, + globalConfigConnectionString: + process.env.EXPERIMENTATION_CONFIG ?? process.env.GLOBAL_CONFIG, }); ``` @@ -60,17 +60,17 @@ const customLdAdapter = createLaunchDarklyAdapter({ | ---------------------------- | ---------| ------------------------------------------------------------------ | | `projectSlug` | `string` | LaunchDarkly project slug | | `clientSideId` | `string` | LaunchDarkly client-side ID | -| `edgeConfigConnectionString` | `string` | Edge Config connection string | +| `globalConfigConnectionString` | `string` | Global 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` -- `EXPERIMENTATION_CONFIG` _(required)_ → `edgeConfigConnectionString` +- `EXPERIMENTATION_CONFIG` _(required)_ → `globalConfigConnectionString` -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 native LaunchDarkly [Marketplace integration](https://vercel.com/marketplace/launchdarkly) exposes the Global Config connection string as `EXPERIMENTATION_CONFIG` when Global 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. +If you use the legacy LaunchDarkly Vercel integration, which provides the connection string as `GLOBAL_CONFIG`, set `EXPERIMENTATION_CONFIG` to the same value, or use `createLaunchDarklyAdapter` to pass `globalConfigConnectionString` explicitly. --- @@ -144,13 +144,13 @@ ldAdapter.ldClient; --- -## Edge Config +## Global Config -The LaunchDarkly adapter loads the configuration from [Edge Config](https://vercel.com/storage/edge-config). +The LaunchDarkly adapter loads the configuration from [Global Config](https://vercel.com/storage/edge-config). -Edge Config is a global, ultra-low latency store which uses active replication and is specifically designed for serving feature flag configuration. +Global 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` (provided by the native Marketplace integration). +The default LaunchDarkly adapter, exported as `ldAdapter`, will automatically connect to Global Config when the required environment variables are set. It reads the connection string from `EXPERIMENTATION_CONFIG` (provided by the native Marketplace integration). --- @@ -172,7 +172,7 @@ await ldAdapter.ldClient.waitForInitialization(); ### LaunchDarkly Vercel SDK -The adapter uses the [LaunchDarkly Vercel SDK](https://launchdarkly.com/docs/sdk/edge/vercel) (`@launchdarkly/vercel-server-sdk`) internally, which is designed for usage with Edge Config. +The adapter uses the [LaunchDarkly Vercel SDK](https://launchdarkly.com/docs/sdk/edge/vercel) (`@launchdarkly/vercel-server-sdk`) internally, which is designed for usage with Global Config. --- diff --git a/apps/docs/content/docs/providers/meta.json b/apps/docs/content/docs/providers/meta.json index 14236ac7..15d506d7 100644 --- a/apps/docs/content/docs/providers/meta.json +++ b/apps/docs/content/docs/providers/meta.json @@ -11,7 +11,7 @@ "statsig", "hypertune", "growthbook", - "edge-config", + "global-config", "---Adapters---", "launchdarkly", "reflag", diff --git a/apps/docs/content/docs/providers/openfeature/abtasty.mdx b/apps/docs/content/docs/providers/openfeature/abtasty.mdx index 34ddcc10..bd1daa71 100644 --- a/apps/docs/content/docs/providers/openfeature/abtasty.mdx +++ b/apps/docs/content/docs/providers/openfeature/abtasty.mdx @@ -81,7 +81,7 @@ export const exampleFlag = flag({ _Note that OpenFeature providers may require additional configuration for optimal performance and compatibility. Setup instructions are provided on a best effort basis. Refer to each provider's own documentation._ _If there is a native Flags SDK adapter for your provider, we recommend using that instead. -Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Edge Config. +Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Global Config. See [available adapters](/docs/adapters/supported-providers#adapters)._ _If you are a feature flag provider interested in developing a native adapter please [open a GitHub issue](https://github.com/vercel/flags) to get in touch._ diff --git a/apps/docs/content/docs/providers/openfeature/cloudbees.mdx b/apps/docs/content/docs/providers/openfeature/cloudbees.mdx index c91c8fe5..bc3f17a7 100644 --- a/apps/docs/content/docs/providers/openfeature/cloudbees.mdx +++ b/apps/docs/content/docs/providers/openfeature/cloudbees.mdx @@ -81,7 +81,7 @@ export const exampleFlag = flag({ _Note that OpenFeature providers may require additional configuration for optimal performance and compatibility. Setup instructions are provided on a best effort basis. Refer to each provider's own documentation._ _If there is a native Flags SDK adapter for your provider, we recommend using that instead. -Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Edge Config. +Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Global Config. See [available adapters](/docs/adapters/supported-providers#adapters)._ _If you are a feature flag provider interested in developing a native adapter please [open a GitHub issue](https://github.com/vercel/flags) to get in touch._ diff --git a/apps/docs/content/docs/providers/openfeature/confidence-by-spotify.mdx b/apps/docs/content/docs/providers/openfeature/confidence-by-spotify.mdx index 9c24b8de..759dd448 100644 --- a/apps/docs/content/docs/providers/openfeature/confidence-by-spotify.mdx +++ b/apps/docs/content/docs/providers/openfeature/confidence-by-spotify.mdx @@ -84,7 +84,7 @@ export const exampleFlag = flag({ _Note that OpenFeature providers may require additional configuration for optimal performance and compatibility. Setup instructions are provided on a best effort basis. Refer to each provider's own documentation._ _If there is a native Flags SDK adapter for your provider, we recommend using that instead. -Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Edge Config. +Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Global Config. See [available adapters](/docs/adapters/supported-providers#adapters)._ _If you are a feature flag provider interested in developing a native adapter please [open a GitHub issue](https://github.com/vercel/flags) to get in touch._ diff --git a/apps/docs/content/docs/providers/openfeature/configcat.mdx b/apps/docs/content/docs/providers/openfeature/configcat.mdx index c410dd9d..d208a0d9 100644 --- a/apps/docs/content/docs/providers/openfeature/configcat.mdx +++ b/apps/docs/content/docs/providers/openfeature/configcat.mdx @@ -81,7 +81,7 @@ export const exampleFlag = flag({ _Note that OpenFeature providers may require additional configuration for optimal performance and compatibility. Setup instructions are provided on a best effort basis. Refer to each provider's own documentation._ _If there is a native Flags SDK adapter for your provider, we recommend using that instead. -Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Edge Config. +Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Global Config. See [available adapters](/docs/adapters/supported-providers#adapters)._ _If you are a feature flag provider interested in developing a native adapter please [open a GitHub issue](https://github.com/vercel/flags) to get in touch._ diff --git a/apps/docs/content/docs/providers/openfeature/devcycle.mdx b/apps/docs/content/docs/providers/openfeature/devcycle.mdx index d1acabca..65a3390e 100644 --- a/apps/docs/content/docs/providers/openfeature/devcycle.mdx +++ b/apps/docs/content/docs/providers/openfeature/devcycle.mdx @@ -81,7 +81,7 @@ export const exampleFlag = flag({ _Note that OpenFeature providers may require additional configuration for optimal performance and compatibility. Setup instructions are provided on a best effort basis. Refer to each provider's own documentation._ _If there is a native Flags SDK adapter for your provider, we recommend using that instead. -Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Edge Config. +Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Global Config. See [available adapters](/docs/adapters/supported-providers#adapters)._ _If you are a feature flag provider interested in developing a native adapter please [open a GitHub issue](https://github.com/vercel/flags) to get in touch._ diff --git a/apps/docs/content/docs/providers/openfeature/featbit.mdx b/apps/docs/content/docs/providers/openfeature/featbit.mdx index e760b57a..64186757 100644 --- a/apps/docs/content/docs/providers/openfeature/featbit.mdx +++ b/apps/docs/content/docs/providers/openfeature/featbit.mdx @@ -85,7 +85,7 @@ export const exampleFlag = flag({ _Note that OpenFeature providers may require additional configuration for optimal performance and compatibility. Setup instructions are provided on a best effort basis. Refer to each provider's own documentation._ _If there is a native Flags SDK adapter for your provider, we recommend using that instead. -Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Edge Config. +Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Global Config. See [available adapters](/docs/adapters/supported-providers#adapters)._ _If you are a feature flag provider interested in developing a native adapter please [open a GitHub issue](https://github.com/vercel/flags) to get in touch._ diff --git a/apps/docs/content/docs/providers/openfeature/flagd.mdx b/apps/docs/content/docs/providers/openfeature/flagd.mdx index c3d7424f..5da99238 100644 --- a/apps/docs/content/docs/providers/openfeature/flagd.mdx +++ b/apps/docs/content/docs/providers/openfeature/flagd.mdx @@ -81,7 +81,7 @@ export const exampleFlag = flag({ _Note that OpenFeature providers may require additional configuration for optimal performance and compatibility. Setup instructions are provided on a best effort basis. Refer to each provider's own documentation._ _If there is a native Flags SDK adapter for your provider, we recommend using that instead. -Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Edge Config. +Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Global Config. See [available adapters](/docs/adapters/supported-providers#adapters)._ _If you are a feature flag provider interested in developing a native adapter please [open a GitHub issue](https://github.com/vercel/flags) to get in touch._ diff --git a/apps/docs/content/docs/providers/openfeature/flipt.mdx b/apps/docs/content/docs/providers/openfeature/flipt.mdx index e5e52805..1bbef72c 100644 --- a/apps/docs/content/docs/providers/openfeature/flipt.mdx +++ b/apps/docs/content/docs/providers/openfeature/flipt.mdx @@ -84,7 +84,7 @@ export const exampleFlag = flag({ _Note that OpenFeature providers may require additional configuration for optimal performance and compatibility. Setup instructions are provided on a best effort basis. Refer to each provider's own documentation._ _If there is a native Flags SDK adapter for your provider, we recommend using that instead. -Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Edge Config. +Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Global Config. See [available adapters](/docs/adapters/supported-providers#adapters)._ _If you are a feature flag provider interested in developing a native adapter please [open a GitHub issue](https://github.com/vercel/flags) to get in touch._ diff --git a/apps/docs/content/docs/providers/openfeature/go.mdx b/apps/docs/content/docs/providers/openfeature/go.mdx index 7743c160..69d788e2 100644 --- a/apps/docs/content/docs/providers/openfeature/go.mdx +++ b/apps/docs/content/docs/providers/openfeature/go.mdx @@ -82,7 +82,7 @@ export const exampleFlag = flag({ _Note that OpenFeature providers may require additional configuration for optimal performance and compatibility. Setup instructions are provided on a best effort basis. Refer to each provider's own documentation._ _If there is a native Flags SDK adapter for your provider, we recommend using that instead. -Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Edge Config. +Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Global Config. See [available adapters](/docs/adapters/supported-providers#adapters)._ _If you are a feature flag provider interested in developing a native adapter please [open a GitHub issue](https://github.com/vercel/flags) to get in touch._ diff --git a/apps/docs/content/docs/providers/openfeature/growthbook.mdx b/apps/docs/content/docs/providers/openfeature/growthbook.mdx index c6e91e58..aa3be183 100644 --- a/apps/docs/content/docs/providers/openfeature/growthbook.mdx +++ b/apps/docs/content/docs/providers/openfeature/growthbook.mdx @@ -103,7 +103,7 @@ export const exampleFlag = flag({ _Note that OpenFeature providers may require additional configuration for optimal performance and compatibility. Setup instructions are provided on a best effort basis. Refer to each provider's own documentation._ _If there is a native Flags SDK adapter for your provider, we recommend using that instead. -Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Edge Config. +Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Global Config. See [available adapters](/docs/adapters/supported-providers#adapters)._ _If you are a feature flag provider interested in developing a native adapter please [open a GitHub issue](https://github.com/vercel/flags) to get in touch._ diff --git a/apps/docs/content/docs/providers/openfeature/hypertune.mdx b/apps/docs/content/docs/providers/openfeature/hypertune.mdx index 032915f6..13af5bba 100644 --- a/apps/docs/content/docs/providers/openfeature/hypertune.mdx +++ b/apps/docs/content/docs/providers/openfeature/hypertune.mdx @@ -81,7 +81,7 @@ export const exampleFlag = flag({ _Note that OpenFeature providers may require additional configuration for optimal performance and compatibility. Setup instructions are provided on a best effort basis. Refer to each provider's own documentation._ _If there is a native Flags SDK adapter for your provider, we recommend using that instead. -Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Edge Config. +Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Global Config. See [available adapters](/docs/adapters/supported-providers#adapters)._ _If you are a feature flag provider interested in developing a native adapter please [open a GitHub issue](https://github.com/vercel/flags) to get in touch._ diff --git a/apps/docs/content/docs/providers/openfeature/index.mdx b/apps/docs/content/docs/providers/openfeature/index.mdx index 55858f3e..31d0435a 100644 --- a/apps/docs/content/docs/providers/openfeature/index.mdx +++ b/apps/docs/content/docs/providers/openfeature/index.mdx @@ -9,7 +9,7 @@ title: 'OpenFeature' -_If there is a native Flags SDK adapter for your provider, we recommend using that instead. Native Flags SDK adapters finely tune the SDK for your flag provider, optionally integrate with Edge Config and Flags Explorer, and are configured for Edge Runtime compatibility where possible. See [available adapters](/docs/adapters/supported-providers#adapters)_ +_If there is a native Flags SDK adapter for your provider, we recommend using that instead. Native Flags SDK adapters finely tune the SDK for your flag provider, optionally integrate with Global Config and Flags Explorer, and are configured for Edge Runtime compatibility where possible. See [available adapters](/docs/adapters/supported-providers#adapters)_ The `@flags-sdk/openfeature` package provides an [adapter](#provider-instance) for loading flags from OpenFeature. @@ -199,13 +199,13 @@ await openFeatureAdapter.client(); --- -## Edge Config +## Global Config -The OpenFeature adapter does not integrate with Edge Config directly. +The OpenFeature adapter does not integrate with Global Config directly. -We recommend using a native Flags SDK adapter for your provider instead of using the OpenFeature adapter. Native Flags SDK adapters finely tune the SDK for your flag provider, optionally integrate with Edge Config and Flags Explorer, and are configured for Edge Runtime compatibility where possible. See [available adapters](/docs/adapters/supported-providers#adapters). +We recommend using a native Flags SDK adapter for your provider instead of using the OpenFeature adapter. Native Flags SDK adapters finely tune the SDK for your flag provider, optionally integrate with Global Config and Flags Explorer, and are configured for Edge Runtime compatibility where possible. See [available adapters](/docs/adapters/supported-providers#adapters). -If no native Flags SDK adapter is available, your OpenFeature provider might still allow you to configure Edge Config integration. +If no native Flags SDK adapter is available, your OpenFeature provider might still allow you to configure Global Config integration. --- diff --git a/apps/docs/content/docs/providers/openfeature/kameloon.mdx b/apps/docs/content/docs/providers/openfeature/kameloon.mdx index 7e26a837..04382c18 100644 --- a/apps/docs/content/docs/providers/openfeature/kameloon.mdx +++ b/apps/docs/content/docs/providers/openfeature/kameloon.mdx @@ -84,7 +84,7 @@ export const exampleFlag = flag({ _Note that OpenFeature providers may require additional configuration for optimal performance and compatibility. Setup instructions are provided on a best effort basis. Refer to each provider's own documentation._ _If there is a native Flags SDK adapter for your provider, we recommend using that instead. -Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Edge Config. +Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Global Config. See [available adapters](/docs/adapters/supported-providers#adapters)._ _If you are a feature flag provider interested in developing a native adapter please [open a GitHub issue](https://github.com/vercel/flags) to get in touch._ diff --git a/apps/docs/content/docs/providers/openfeature/posthog.mdx b/apps/docs/content/docs/providers/openfeature/posthog.mdx index 742fc2ee..05e4477c 100644 --- a/apps/docs/content/docs/providers/openfeature/posthog.mdx +++ b/apps/docs/content/docs/providers/openfeature/posthog.mdx @@ -81,7 +81,7 @@ export const exampleFlag = flag({ _Note that OpenFeature providers may require additional configuration for optimal performance and compatibility. Setup instructions are provided on a best effort basis. Refer to each provider's own documentation._ _If there is a native Flags SDK adapter for your provider, we recommend using that instead. -Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Edge Config. +Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Global Config. See [available adapters](/docs/adapters/supported-providers#adapters)._ _If you are a feature flag provider interested in developing a native adapter please [open a GitHub issue](https://github.com/vercel/flags) to get in touch._ diff --git a/apps/docs/content/docs/providers/openfeature/split.mdx b/apps/docs/content/docs/providers/openfeature/split.mdx index ebe1061c..66cda5dd 100644 --- a/apps/docs/content/docs/providers/openfeature/split.mdx +++ b/apps/docs/content/docs/providers/openfeature/split.mdx @@ -86,7 +86,7 @@ export const exampleFlag = flag({ _Note that OpenFeature providers may require additional configuration for optimal performance and compatibility. Setup instructions are provided on a best effort basis. Refer to each provider's own documentation._ _If there is a native Flags SDK adapter for your provider, we recommend using that instead. -Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Edge Config. +Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Global Config. See [available adapters](/docs/adapters/supported-providers#adapters)._ _If you are a feature flag provider interested in developing a native adapter please [open a GitHub issue](https://github.com/vercel/flags) to get in touch._ diff --git a/apps/docs/content/docs/providers/openfeature/tggl.mdx b/apps/docs/content/docs/providers/openfeature/tggl.mdx index 9f4ff1fb..3abf5e53 100644 --- a/apps/docs/content/docs/providers/openfeature/tggl.mdx +++ b/apps/docs/content/docs/providers/openfeature/tggl.mdx @@ -82,7 +82,7 @@ export const exampleFlag = flag({ _Note that OpenFeature providers may require additional configuration for optimal performance and compatibility. Setup instructions are provided on a best effort basis. Refer to each provider's own documentation._ _If there is a native Flags SDK adapter for your provider, we recommend using that instead. -Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Edge Config. +Native Flags SDK adapters tune your flag provider's SDK for optimal performance and integrate with Flags Explorer and Global Config. See [available adapters](/docs/adapters/supported-providers#adapters)._ _If you are a feature flag provider interested in developing a native adapter please [open a GitHub issue](https://github.com/vercel/flags) to get in touch._ diff --git a/apps/docs/content/docs/providers/statsig.mdx b/apps/docs/content/docs/providers/statsig.mdx index 738b5163..a0777642 100644 --- a/apps/docs/content/docs/providers/statsig.mdx +++ b/apps/docs/content/docs/providers/statsig.mdx @@ -66,16 +66,16 @@ const statsigAdapter = createStatsigAdapter({ | `statsigServerApiKey` | `string` | Statsig server secret key | | `statsigOptions` | `StatsigOptions` | Statsig initialization options | | `statsigProjectId` | `string` | Statsig project ID | -| `edgeConfig` | `object` | Edge Config details for use with Statsig's Edge Config integration | -| `edgeConfig.connectionString` | `string` | Edge Config connection string | -| `edgeConfig.itemKey` | `string` | Key under which the Statsig configuration is stored in Edge Config | +| `globalConfig` | `object` | Global Config details for use with Statsig's Global Config integration | +| `globalConfig.connectionString` | `string` | Global Config connection string | +| `globalConfig.itemKey` | `string` | Key under which the Statsig configuration is stored in Global Config | The default statsig adapter configures itself based on the following environment variables: - `STATSIG_SERVER_API_KEY` _(required)_ → `statsigServerApiKey` - `STATSIG_PROJECT_ID` _(optional)_ → `statsigProjectId` -- `EXPERIMENTATION_CONFIG` _(optional)_ → `edgeConfig.connectionString` -- `EXPERIMENTATION_CONFIG_ITEM_KEY` _(optional)_ → `edgeConfig.itemKey` +- `EXPERIMENTATION_CONFIG` _(optional)_ → `globalConfig.connectionString` +- `EXPERIMENTATION_CONFIG_ITEM_KEY` _(optional)_ → `globalConfig.itemKey` --- @@ -354,13 +354,13 @@ Read more about initialization strategies in the [Statsig Docs](https://docs.sta --- -## Edge Config +## Global Config -The Statsig adapter can either load the experiment configuration over the network or bootstrap from [Edge Config](https://vercel.com/storage/edge-config). +The Statsig adapter can either load the experiment configuration over the network or bootstrap from [Global Config](https://vercel.com/storage/edge-config). -Using [Edge Config](https://vercel.com/docs/storage/edge-config) is optional but recommended for the best latency. Edge Config is a global, ultra-low latency store which uses active replication and is specifically designed for serving feature flag configuration. +Using [Global Config](https://vercel.com/docs/storage/edge-config) is optional but recommended for the best latency. Global Config is a global, ultra-low latency store which uses active replication and is specifically designed for serving feature flag configuration. -The default Statsig adapter, exported as `statsigAdapter`, will automatically connect to Edge Config if the `EXPERIMENTATION_CONFIG` and `EXPERIMENTATION_CONFIG_ITEM_KEY` environment variables are set. If you are using the [Statsig integration on Vercel marketplace](https://vercel.com/marketplace/statsig) these environment variables will be provided automatically, and the default Statsig adapter will read from Edge Config automatically. +The default Statsig adapter, exported as `statsigAdapter`, will automatically connect to Global Config if the `EXPERIMENTATION_CONFIG` and `EXPERIMENTATION_CONFIG_ITEM_KEY` environment variables are set. If you are using the [Statsig integration on Vercel marketplace](https://vercel.com/marketplace/statsig) these environment variables will be provided automatically, and the default Statsig adapter will read from Global Config automatically. --- diff --git a/apps/docs/next.config.ts b/apps/docs/next.config.ts index bb9b667e..07744dff 100644 --- a/apps/docs/next.config.ts +++ b/apps/docs/next.config.ts @@ -33,7 +33,7 @@ const config: NextConfig = { // ----------------------------------------------------------------------- '/docs/adapters/custom-adapters': '/providers/custom-adapters', '/docs/adapters/supported-providers': '/providers', - '/docs/api-reference/adapters/edge-config': '/providers/edge-config', + '/docs/api-reference/adapters/edge-config': '/providers/global-config', '/docs/api-reference/adapters/hypertune': '/providers/hypertune', '/docs/api-reference/adapters/launchdarkly': '/providers/launchdarkly', '/docs/api-reference/adapters/optimizely': '/providers/optimizely', @@ -90,7 +90,7 @@ const config: NextConfig = { '/api-reference/provider/split': '/providers/split', '/api-reference/provider/optimizely': '/providers/optimizely', '/api-reference/provider/hypertune': '/providers/hypertune', - '/api-reference/provider/edge-config': '/providers/edge-config', + '/api-reference/provider/edge-config': '/providers/global-config', '/docs/concepts/flags': '/principles/flags-as-code', '/docs/concepts/flags.ts': '/principles/flags-as-code', '/docs/frameworks/next/overview': '/frameworks/next', diff --git a/examples/snippets/app/concepts/adapters/flags.tsx b/examples/snippets/app/concepts/adapters/flags.tsx index b16eb8aa..a98e76e7 100644 --- a/examples/snippets/app/concepts/adapters/flags.tsx +++ b/examples/snippets/app/concepts/adapters/flags.tsx @@ -1,10 +1,12 @@ import { flag } from 'flags/next'; -import { createEdgeConfigAdapter } from './edge-config-adapter'; +import { createGlobalConfigAdapter } from './global-config-adapter'; -const edgeConfigAdapter = createEdgeConfigAdapter(process.env.EDGE_CONFIG!); +const globalConfigAdapter = createGlobalConfigAdapter( + process.env.GLOBAL_CONFIG!, +); export const customAdapterFlag = flag({ key: 'custom-adapter-flag', description: 'Shows how to use a custom flags adapter', - adapter: edgeConfigAdapter, + adapter: globalConfigAdapter, }); diff --git a/examples/snippets/app/concepts/adapters/edge-config-adapter.ts b/examples/snippets/app/concepts/adapters/global-config-adapter.ts similarity index 61% rename from examples/snippets/app/concepts/adapters/edge-config-adapter.ts rename to examples/snippets/app/concepts/adapters/global-config-adapter.ts index bebadb03..8a6c4d6f 100644 --- a/examples/snippets/app/concepts/adapters/edge-config-adapter.ts +++ b/examples/snippets/app/concepts/adapters/global-config-adapter.ts @@ -2,50 +2,50 @@ import { createClient, type GlobalConfigClient } from '@vercel/global-config'; import type { Adapter } from 'flags'; /** - * An Edge Config adapter for the Flags SDK + * An Global Config adapter for the Flags SDK */ -export function createEdgeConfigAdapter( +export function createGlobalConfigAdapter( connectionString: string | GlobalConfigClient, options?: { - edgeConfigItemKey?: string; + globalConfigItemKey?: string; teamSlug?: string; }, ) { if (!connectionString) { - throw new Error('Edge Config Adapter: Missing connection string'); + throw new Error('Global Config Adapter: Missing connection string'); } - const edgeConfigClient = + const globalConfigClient = typeof connectionString === 'string' ? createClient(connectionString) : connectionString; - const edgeConfigItemKey = options?.edgeConfigItemKey ?? 'flags'; + const globalConfigItemKey = options?.globalConfigItemKey ?? 'flags'; - return function edgeConfigAdapter(): Adapter< + return function globalConfigAdapter(): Adapter< ValueType, EntitiesType > { return { origin: options?.teamSlug - ? `https://vercel.com/${options.teamSlug}/~/stores/edge-config/${edgeConfigClient.connection.id}/items#item=${edgeConfigItemKey}` + ? `https://vercel.com/${options.teamSlug}/~/stores/edge-config/${globalConfigClient.connection.id}/items#item=${globalConfigItemKey}` : undefined, async decide({ key }): Promise { const definitions = - await edgeConfigClient.get>( - edgeConfigItemKey, + await globalConfigClient.get>( + globalConfigItemKey, ); // if a defaultValue was provided this error will be caught and the defaultValue will be used if (!definitions) { throw new Error( - `@flags-sdk/global-config: Edge Config item "${edgeConfigItemKey}" not found`, + `@flags-sdk/global-config: Global Config item "${globalConfigItemKey}" not found`, ); } // if a defaultValue was provided this error will be caught and the defaultValue will be used if (!(key in definitions)) { throw new Error( - `@flags-sdk/global-config: Flag "${key}" not found in Edge Config item "${edgeConfigItemKey}"`, + `@flags-sdk/global-config: Flag "${key}" not found in Global Config item "${globalConfigItemKey}"`, ); } return definitions[key] as ValueType; diff --git a/examples/snippets/app/examples/dashboard-pages/flags.ts b/examples/snippets/app/examples/dashboard-pages/flags.ts index d07cfa9c..a51d10c3 100644 --- a/examples/snippets/app/examples/dashboard-pages/flags.ts +++ b/examples/snippets/app/examples/dashboard-pages/flags.ts @@ -18,7 +18,7 @@ export const dashboardFlag = flag({ description: 'Flag used on the Dashboard Pages example', decide({ entities }) { if (!entities?.user) return false; - // Allowed users could be loaded from Edge Config or elsewhere + // Allowed users could be loaded from Global Config or elsewhere const allowedUsers = ['user1']; return allowedUsers.includes(entities.user.id); diff --git a/packages/adapter-global-config/README.md b/packages/adapter-global-config/README.md index 042bb8d5..f6afb881 100644 --- a/packages/adapter-global-config/README.md +++ b/packages/adapter-global-config/README.md @@ -10,19 +10,19 @@ npm install @flags-sdk/global-config ## Using the default adapter -This adapter will connect to the Edge Config available under the `EDGE_CONFIG` environment variable, and read items from a key in the Edge Config called `flags`. +This adapter will connect to the Global Config available under the `GLOBAL_CONFIG` environment variable, and read items from a key in the Global Config called `flags`. ```ts import { flag } from "flags/next"; -import { edgeConfigAdapter } from "@flags-sdk/global-config"; +import { globalConfigAdapter } from "@flags-sdk/global-config"; export const exampleFlag = flag({ key: "example-flag", - adapter: edgeConfigAdapter, + adapter: globalConfigAdapter, }); ``` -Your Edge Config should look like this: +Your Global Config should look like this: ```json { @@ -34,24 +34,24 @@ Your Edge Config should look like this: ## Using a custom adapter -You can specify a custom adapter which connects to a different Edge Config, and reads +You can specify a custom adapter which connects to a different Global Config, and reads ```ts import { flag } from "flags/next"; -import { createEdgeConfigAdapter } from "@flags-sdk/global-config"; +import { createGlobalConfigAdapter } from "@flags-sdk/global-config"; -const edgeConfigAdapter = createEdgeConfigAdapter(process.env.EDGE_CONFIG, { +const globalConfigAdapter = createGlobalConfigAdapter(process.env.GLOBAL_CONFIG, { teamSlug: "your-team-slug", - edgeConfigItemKey: "my-flags", + globalConfigItemKey: "my-flags", }); export const exampleFlag = flag({ key: "example-flag", - adapter: edgeConfigAdapter, + adapter: globalConfigAdapter, }); ``` -Your Edge Config should look like this: +Your Global Config should look like this: ```json { @@ -61,4 +61,4 @@ Your Edge Config should look like this: } ``` -Supplying the custom `teamSlug` allows the adapter to generate an `origin` for your flags, which in turn allows the Flags Explorer to link to your Edge Config. This is optional and does not affect runtime behavior. +Supplying the custom `teamSlug` allows the adapter to generate an `origin` for your flags, which in turn allows the Flags Explorer to link to your Global Config. This is optional and does not affect runtime behavior. diff --git a/packages/adapter-global-config/src/index.test.ts b/packages/adapter-global-config/src/index.test.ts index df92b289..cc43ca0c 100644 --- a/packages/adapter-global-config/src/index.test.ts +++ b/packages/adapter-global-config/src/index.test.ts @@ -1,29 +1,29 @@ -import type { EdgeConfigClient } from '@vercel/global-config'; +import type { GlobalConfigClient } from '@vercel/global-config'; import type { ReadonlyRequestCookies } from 'flags'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { - createEdgeConfigAdapter, - edgeConfigAdapter, - resetDefaultEdgeConfigAdapter, + createGlobalConfigAdapter, + globalConfigAdapter, + resetDefaultGlobalConfigAdapter, } from '.'; -describe('createEdgeConfigAdapter', () => { +describe('createGlobalConfigAdapter', () => { it('should allow creating an adapter with a client', () => { - const fakeEdgeConfigClient = {} as EdgeConfigClient; - const adapter = createEdgeConfigAdapter(fakeEdgeConfigClient); + const fakeGlobalConfigClient = {} as GlobalConfigClient; + const adapter = createGlobalConfigAdapter(fakeGlobalConfigClient); expect(adapter).toBeDefined(); }); it('returns the same adapter instance on every call', () => { - const fakeEdgeConfigClient = {} as EdgeConfigClient; - const adapter = createEdgeConfigAdapter(fakeEdgeConfigClient); + const fakeGlobalConfigClient = {} as GlobalConfigClient; + const adapter = createGlobalConfigAdapter(fakeGlobalConfigClient); expect(adapter()).toBe(adapter()); }); describe('adapterId', () => { it('shares one adapterId across all adapters from the same factory call', () => { - const fakeEdgeConfigClient = {} as EdgeConfigClient; - const adapter = createEdgeConfigAdapter(fakeEdgeConfigClient); + const fakeGlobalConfigClient = {} as GlobalConfigClient; + const adapter = createGlobalConfigAdapter(fakeGlobalConfigClient); const a = adapter(); const b = adapter(); expect(a).toBe(b); @@ -32,23 +32,23 @@ describe('createEdgeConfigAdapter', () => { }); it('uses different adapterIds across separate factory calls', () => { - const fakeEdgeConfigClient = {} as EdgeConfigClient; - const adapterA = createEdgeConfigAdapter(fakeEdgeConfigClient); - const adapterB = createEdgeConfigAdapter(fakeEdgeConfigClient); + const fakeGlobalConfigClient = {} as GlobalConfigClient; + const adapterA = createGlobalConfigAdapter(fakeGlobalConfigClient); + const adapterB = createGlobalConfigAdapter(fakeGlobalConfigClient); expect(adapterA().adapterId).not.toBe(adapterB().adapterId); }); }); describe('bulkDecide', () => { - it('resolves all requested flag keys from Edge Config in one read', async () => { - const fakeEdgeConfigClient = { + it('resolves all requested flag keys from Global Config in one read', async () => { + const fakeGlobalConfigClient = { get: vi.fn(async () => ({ 'flag-a': true, 'flag-b': false, 'flag-c': true, })), - } as unknown as EdgeConfigClient; - const adapter = createEdgeConfigAdapter(fakeEdgeConfigClient); + } as unknown as GlobalConfigClient; + const adapter = createGlobalConfigAdapter(fakeGlobalConfigClient); const headers = new Headers(); const result = await adapter().bulkDecide!({ @@ -59,14 +59,14 @@ describe('createEdgeConfigAdapter', () => { }); expect(result).toEqual({ 'flag-a': true, 'flag-b': false }); - expect(fakeEdgeConfigClient.get).toHaveBeenCalledOnce(); + expect(fakeGlobalConfigClient.get).toHaveBeenCalledOnce(); }); - it('omits keys missing from Edge Config so the SDK applies defaultValue', async () => { - const fakeEdgeConfigClient = { + it('omits keys missing from Global Config so the SDK applies defaultValue', async () => { + const fakeGlobalConfigClient = { get: vi.fn(async () => ({ 'flag-a': true })), - } as unknown as EdgeConfigClient; - const adapter = createEdgeConfigAdapter(fakeEdgeConfigClient); + } as unknown as GlobalConfigClient; + const adapter = createGlobalConfigAdapter(fakeGlobalConfigClient); const headers = new Headers(); const result = await adapter().bulkDecide!({ @@ -80,10 +80,10 @@ describe('createEdgeConfigAdapter', () => { }); it('shares the per-request cache with decide', async () => { - const fakeEdgeConfigClient = { + const fakeGlobalConfigClient = { get: vi.fn(async () => ({ 'flag-a': true, 'flag-b': false })), - } as unknown as EdgeConfigClient; - const adapter = createEdgeConfigAdapter(fakeEdgeConfigClient); + } as unknown as GlobalConfigClient; + const adapter = createGlobalConfigAdapter(fakeGlobalConfigClient); const headers = new Headers(); await adapter().decide({ @@ -100,22 +100,22 @@ describe('createEdgeConfigAdapter', () => { cookies: {} as ReadonlyRequestCookies, }); - expect(fakeEdgeConfigClient.get).toHaveBeenCalledOnce(); + expect(fakeGlobalConfigClient.get).toHaveBeenCalledOnce(); }); }); it('should allow creating an adapter with a connection string', () => { - const adapter = createEdgeConfigAdapter( + const adapter = createGlobalConfigAdapter( 'https://edge-config.vercel.com/ecfg_xxx?token=yyy', ); expect(adapter).toBeDefined(); }); it('should allow deciding', async () => { - const fakeEdgeConfigClient = { + const fakeGlobalConfigClient = { get: vi.fn(async () => ({ 'test-key': true })), - } as unknown as EdgeConfigClient; - const adapter = createEdgeConfigAdapter(fakeEdgeConfigClient); + } as unknown as GlobalConfigClient; + const adapter = createGlobalConfigAdapter(fakeGlobalConfigClient); await expect( adapter().decide({ key: 'test-key', @@ -124,15 +124,15 @@ describe('createEdgeConfigAdapter', () => { cookies: {} as ReadonlyRequestCookies, }), ).resolves.toEqual(true); - expect(fakeEdgeConfigClient.get).toHaveBeenCalledWith('flags'); + expect(fakeGlobalConfigClient.get).toHaveBeenCalledWith('flags'); }); describe('caching', () => { it('caches for the duration of a request', async () => { - const fakeEdgeConfigClient = { + const fakeGlobalConfigClient = { get: vi.fn(async () => ({ 'test-key': true })), - } as unknown as EdgeConfigClient; - const adapter = createEdgeConfigAdapter(fakeEdgeConfigClient); + } as unknown as GlobalConfigClient; + const adapter = createGlobalConfigAdapter(fakeGlobalConfigClient); const headers = new Headers(); @@ -156,14 +156,14 @@ describe('createEdgeConfigAdapter', () => { cookies: {} as ReadonlyRequestCookies, }), ).resolves.toEqual(true); - expect(fakeEdgeConfigClient.get).toHaveBeenCalledWith('flags'); - expect(fakeEdgeConfigClient.get).toHaveBeenCalledOnce(); + expect(fakeGlobalConfigClient.get).toHaveBeenCalledWith('flags'); + expect(fakeGlobalConfigClient.get).toHaveBeenCalledOnce(); }); it('does not cache between requests', async () => { - const fakeEdgeConfigClient = { + const fakeGlobalConfigClient = { get: vi.fn(async () => ({ 'test-key': true })), - } as unknown as EdgeConfigClient; - const adapter = createEdgeConfigAdapter(fakeEdgeConfigClient); + } as unknown as GlobalConfigClient; + const adapter = createGlobalConfigAdapter(fakeGlobalConfigClient); // call once await expect( @@ -186,28 +186,28 @@ describe('createEdgeConfigAdapter', () => { }), ).resolves.toEqual(true); - expect(fakeEdgeConfigClient.get).toHaveBeenCalledWith('flags'); - expect(fakeEdgeConfigClient.get).toHaveBeenCalledTimes(2); + expect(fakeGlobalConfigClient.get).toHaveBeenCalledWith('flags'); + expect(fakeGlobalConfigClient.get).toHaveBeenCalledTimes(2); }); }); }); -describe('edgeConfigAdapter', () => { +describe('globalConfigAdapter', () => { beforeEach(() => { - resetDefaultEdgeConfigAdapter(); + resetDefaultGlobalConfigAdapter(); }); - it('default adapter should throw on usage when EDGE_CONFIG is not set', () => { - expect(() => edgeConfigAdapter()).toThrowError( - '@flags-sdk/global-config: Missing EDGE_CONFIG env var', + it('default adapter should throw on usage when GLOBAL_CONFIG is not set', () => { + expect(() => globalConfigAdapter()).toThrowError( + '@flags-sdk/global-config: Missing GLOBAL_CONFIG env var', ); }); it('should export a default adapter', () => { - process.env.EDGE_CONFIG = + process.env.GLOBAL_CONFIG = 'https://edge-config.vercel.com/ecfg_xxx?token=yyy'; - const adapter = edgeConfigAdapter(); + const adapter = globalConfigAdapter(); expect(adapter).toBeDefined(); - delete process.env.EDGE_CONFIG; + delete process.env.GLOBAL_CONFIG; }); }); diff --git a/packages/adapter-global-config/src/index.ts b/packages/adapter-global-config/src/index.ts index 04c07a29..571ab3c6 100644 --- a/packages/adapter-global-config/src/index.ts +++ b/packages/adapter-global-config/src/index.ts @@ -1,89 +1,93 @@ -import { createClient, type EdgeConfigClient } from '@vercel/global-config'; +import { createClient, type GlobalConfigClient } from '@vercel/global-config'; import type { Adapter, ReadonlyHeaders } from 'flags'; -export type EdgeConfigFlags = { +export type GlobalConfigFlags = { [key: string]: boolean | number | string | null; }; // extend the adapter definition to expose a default adapter -let defaultEdgeConfigAdapter: - | ReturnType +let defaultGlobalConfigAdapter: + | ReturnType | undefined; /** - * A default Vercel adapter for Edge Config + * A default Vercel adapter for Global Config * */ -export function edgeConfigAdapter(): Adapter< +export function globalConfigAdapter(): Adapter< ValueType, EntitiesType > { // Initialized lazily to avoid warning when it is not actually used and env vars are missing. - if (!defaultEdgeConfigAdapter) { - if (!process.env.EDGE_CONFIG) { - throw new Error('@flags-sdk/global-config: Missing EDGE_CONFIG env var'); + if (!defaultGlobalConfigAdapter) { + if (!process.env.GLOBAL_CONFIG) { + throw new Error( + '@flags-sdk/global-config: Missing GLOBAL_CONFIG env var', + ); } - defaultEdgeConfigAdapter = createEdgeConfigAdapter(process.env.EDGE_CONFIG); + defaultGlobalConfigAdapter = createGlobalConfigAdapter( + process.env.GLOBAL_CONFIG, + ); } - return defaultEdgeConfigAdapter(); + return defaultGlobalConfigAdapter(); } -export function resetDefaultEdgeConfigAdapter() { - defaultEdgeConfigAdapter = undefined; +export function resetDefaultGlobalConfigAdapter() { + defaultGlobalConfigAdapter = undefined; } -type EdgeConfigItem = Record; +type GlobalConfigItem = Record; /** - * Allows creating a custom Edge Config adapter for feature flags + * Allows creating a custom Global Config adapter for feature flags */ -export function createEdgeConfigAdapter( - connectionString: string | EdgeConfigClient, +export function createGlobalConfigAdapter( + connectionString: string | GlobalConfigClient, options?: { - edgeConfigItemKey?: string; + globalConfigItemKey?: string; teamSlug?: string; }, ) { if (!connectionString) { throw new Error('@flags-sdk/global-config: Missing connection string'); } - const edgeConfigClient = + const globalConfigClient = typeof connectionString === 'string' ? createClient(connectionString) : connectionString; - const edgeConfigItemKey = options?.edgeConfigItemKey ?? 'flags'; + const globalConfigItemKey = options?.globalConfigItemKey ?? 'flags'; /** - * Per-request cache to ensure we only ever read Edge Config once per request. + * Per-request cache to ensure we only ever read Global Config once per request. * Uses the request headers reference as the cache key. * - * ReadonlyHeaders -> Promise + * ReadonlyHeaders -> Promise */ - const edgeConfigItemCache = new WeakMap< + const globalConfigItemCache = new WeakMap< ReadonlyHeaders, - Promise + Promise >(); - const adapterId = Symbol('edgeConfigAdapter'); + const adapterId = Symbol('globalConfigAdapter'); async function getDefinitions( headers: ReadonlyHeaders, - ): Promise { - const cached = edgeConfigItemCache.get(headers); + ): Promise { + const cached = globalConfigItemCache.get(headers); if (cached) return cached; const valuePromise = - edgeConfigClient.get(edgeConfigItemKey); - edgeConfigItemCache.set(headers, valuePromise); + globalConfigClient.get(globalConfigItemKey); + globalConfigItemCache.set(headers, valuePromise); return valuePromise; } const adapter: Adapter = { adapterId, origin: options?.teamSlug - ? `https://vercel.com/${options.teamSlug}/~/stores/edge-config/${edgeConfigClient.connection.id}/items#item=${edgeConfigItemKey}` + ? `https://vercel.com/${options.teamSlug}/~/stores/edge-config/${globalConfigClient.connection.id}/items#item=${globalConfigItemKey}` : undefined, async decide({ key, headers }): Promise { const definitions = await getDefinitions(headers); @@ -91,14 +95,14 @@ export function createEdgeConfigAdapter( // if a defaultValue was provided this error will be caught and the defaultValue will be used if (!definitions) { throw new Error( - `@flags-sdk/global-config: Edge Config item "${edgeConfigItemKey}" not found`, + `@flags-sdk/global-config: Global Config item "${globalConfigItemKey}" not found`, ); } // if a defaultValue was provided this error will be caught and the defaultValue will be used if (!(key in definitions)) { throw new Error( - `@flags-sdk/global-config: Flag "${key}" not found in Edge Config item "${edgeConfigItemKey}"`, + `@flags-sdk/global-config: Flag "${key}" not found in Global Config item "${globalConfigItemKey}"`, ); } return definitions[key]; @@ -108,7 +112,7 @@ export function createEdgeConfigAdapter( if (!definitions) { throw new Error( - `@flags-sdk/global-config: Edge Config item "${edgeConfigItemKey}" not found`, + `@flags-sdk/global-config: Global Config item "${globalConfigItemKey}" not found`, ); } @@ -122,7 +126,7 @@ export function createEdgeConfigAdapter( }, }; - return function edgeConfigAdapter(): Adapter< + return function globalConfigAdapter(): Adapter< ValueType, EntitiesType > { diff --git a/packages/adapter-growthbook/src/index.ts b/packages/adapter-growthbook/src/index.ts index 81533aa9..7ba13d0e 100644 --- a/packages/adapter-growthbook/src/index.ts +++ b/packages/adapter-growthbook/src/index.ts @@ -28,7 +28,7 @@ export { type StickyAssignmentsDocument, }; -type EdgeConfig = { +type GlobalConfig = { connectionString: string; /** Defaults to `options.clientKey` **/ itemKey?: string; @@ -62,8 +62,8 @@ export function createGrowthbookAdapter(options: { initOptions?: InitOptions; /** Optional StickyBucketService (reduces variation hopping, required for Bandits) **/ stickyBucketService?: StickyBucketService; - /** Provide Edge Config details to use the optional Edge Config adapter */ - edgeConfig?: EdgeConfig; + /** Provide Global Config details to use the optional Global Config adapter */ + globalConfig?: GlobalConfig; }): AdapterResponse { let trackingCallback = options.trackingCallback; let stickyBucketService = options.stickyBucketService; @@ -74,62 +74,63 @@ export function createGrowthbookAdapter(options: { ...(options.clientOptions || {}), }); - const edgeConfigClient = options.edgeConfig - ? createClient(options.edgeConfig.connectionString) + const globalConfigClient = options.globalConfig + ? createClient(options.globalConfig.connectionString) : null; - const edgeConfigKey = options.edgeConfig?.itemKey || options.clientKey; + const globalConfigKey = options.globalConfig?.itemKey || options.clientKey; const store = new AsyncLocalStorage(); const cache = new WeakMap>(); - const getEdgePayload = async (): Promise => { - if (!edgeConfigClient) return null; + const getGlobalConfigPayload = + async (): Promise => { + if (!globalConfigClient) return null; - // Only do this once per request using AsyncLocalStorage - const currentRequest = store.getStore(); - if (currentRequest) { - const cached = cache.get(currentRequest); - if (cached) { - return cached; + // Only do this once per request using AsyncLocalStorage + const currentRequest = store.getStore(); + if (currentRequest) { + const cached = cache.get(currentRequest); + if (cached) { + return cached; + } } - } - // Fetch from Edge Config - const payloadPromise = edgeConfigClient - .get(edgeConfigKey) - .then((payload) => { - if (!payload) { - console.error('No payload found in edge config'); - return null; - } else if (typeof payload === 'string') { - // Older GrowthBook integrations use WebHooks directly to store - // data in Edge Config, but they store the data as a string. - // - // We need to parse the string to JSON before passing it to GrowthBook. - // - // https://docs.growthbook.io/app/webhooks/sdk-webhooks#vercel-edge-config - // https://github.com/vercel/flags/issues/209 - try { - return JSON.parse(payload) as FeatureApiResponse; - } catch { - console.error('Invalid payload format'); + // Fetch from Global Config + const payloadPromise = globalConfigClient + .get(globalConfigKey) + .then((payload) => { + if (!payload) { + console.error('No payload found in global config'); return null; + } else if (typeof payload === 'string') { + // Older GrowthBook integrations use WebHooks directly to store + // data in Global Config, but they store the data as a string. + // + // We need to parse the string to JSON before passing it to GrowthBook. + // + // https://docs.growthbook.io/app/webhooks/sdk-webhooks#vercel-edge-config + // https://github.com/vercel/flags/issues/209 + try { + return JSON.parse(payload) as FeatureApiResponse; + } catch { + console.error('Invalid payload format'); + return null; + } + } else { + return payload; } - } else { - return payload; - } - }) - .catch((e) => { - console.error('Error fetching edge config', e); - return null; - }); + }) + .catch((e) => { + console.error('Error fetching global config', e); + return null; + }); - if (currentRequest) cache.set(currentRequest, payloadPromise); - return payloadPromise; - }; + if (currentRequest) cache.set(currentRequest, payloadPromise); + return payloadPromise; + }; const initializeGrowthBook = async (): Promise => { - const payload = await getEdgePayload(); + const payload = await getGlobalConfigPayload(); await growthbook.init({ streaming: false, payload: payload ?? undefined, @@ -155,8 +156,8 @@ export function createGrowthbookAdapter(options: { }; const refresh = async (): Promise => { - if (options.edgeConfig) { - const payload = await getEdgePayload(); + if (options.globalConfig) { + const payload = await getGlobalConfigPayload(); if (payload && payload !== growthbook.getPayload()) { await growthbook.setPayload(payload); } @@ -248,9 +249,9 @@ export function resetDefaultGrowthbookAdapter() { * Optional: * - `GROWTHBOOK_API_HOST` - Override the SDK API endpoint for self-hosted users * - `GROWTHBOOK_APP_ORIGIN` - Override the application URL for self-hosted users - * - `GROWTHBOOK_EDGE_CONNECTION_STRING` - Edge Config connection string - * - `EXPERIMENTATION_CONFIG` - fallback for GROWTHBOOK_EDGE_CONNECTION_STRING - * - `GROWTHBOOK_EDGE_CONFIG_ITEM_KEY` - Override the item key for Edge Config (defaults to GROWTHBOOK_CLIENT_KEY) + * - `GROWTHBOOK_GLOBAL_CONFIG_CONNECTION_STRING` - Global Config connection string + * - `EXPERIMENTATION_CONFIG` - fallback for GROWTHBOOK_GLOBAL_CONFIG_CONNECTION_STRING + * - `GROWTHBOOK_GLOBAL_CONFIG_ITEM_KEY` - Override the item key for Global Config (defaults to GROWTHBOOK_CLIENT_KEY) */ export function getOrCreateDefaultGrowthbookAdapter(): AdapterResponse { if (defaultGrowthbookAdapter) { @@ -263,13 +264,13 @@ export function getOrCreateDefaultGrowthbookAdapter(): AdapterResponse { const apiHost = process.env.GROWTHBOOK_API_HOST; const appOrigin = process.env.GROWTHBOOK_APP_ORIGIN; const connectionString = - process.env.GROWTHBOOK_EDGE_CONNECTION_STRING || + process.env.GROWTHBOOK_GLOBAL_CONFIG_CONNECTION_STRING || process.env.EXPERIMENTATION_CONFIG; - const itemKey = process.env.GROWTHBOOK_EDGE_CONFIG_ITEM_KEY; + const itemKey = process.env.GROWTHBOOK_GLOBAL_CONFIG_ITEM_KEY; - let edgeConfig: EdgeConfig | undefined; + let globalConfig: GlobalConfig | undefined; if (connectionString) { - edgeConfig = { + globalConfig = { connectionString, itemKey, }; @@ -279,7 +280,7 @@ export function getOrCreateDefaultGrowthbookAdapter(): AdapterResponse { clientKey, apiHost, appOrigin, - edgeConfig, + globalConfig, }); return defaultGrowthbookAdapter; diff --git a/packages/adapter-hypertune/README.md b/packages/adapter-hypertune/README.md index 533fdddf..19d56ff6 100644 --- a/packages/adapter-hypertune/README.md +++ b/packages/adapter-hypertune/README.md @@ -84,7 +84,7 @@ NEXT_PUBLIC_HYPERTUNE_TOKEN="123=" # For use with precompute, encrypted flag values, overrides, and the Flags Explorer FLAGS_SECRET="ReplaceThisWith32RandomBytesBase64UrlString" -# Optional: automatically configure with a VercelEdgeConfigInitDataProvider +# Optional: automatically configure with a VercelGlobalConfigInitDataProvider EXPERIMENTATION_CONFIG="ecfg_abc" EXPERIMENTATION_CONFIG_ITEM_KEY="hypertune_xyz" ``` diff --git a/packages/adapter-hypertune/src/adapter.ts b/packages/adapter-hypertune/src/adapter.ts index f9c660f3..effde24f 100644 --- a/packages/adapter-hypertune/src/adapter.ts +++ b/packages/adapter-hypertune/src/adapter.ts @@ -7,7 +7,7 @@ import type { } from 'flags'; import { type CreateOptions, - VercelEdgeConfigInitDataProvider, + VercelEdgeConfigInitDataProvider as VercelGlobalConfigInitDataProvider, } from 'hypertune'; type FlagDefinition = { @@ -99,7 +99,7 @@ export const createHypertuneAdapter = < const initDataProvider = process.env.EXPERIMENTATION_CONFIG && process.env.EXPERIMENTATION_CONFIG_ITEM_KEY - ? new VercelEdgeConfigInitDataProvider({ + ? new VercelGlobalConfigInitDataProvider({ edgeConfigClient: createClient( process.env.EXPERIMENTATION_CONFIG, ), diff --git a/packages/adapter-launchdarkly/README.md b/packages/adapter-launchdarkly/README.md index 9cae5cd3..9cc7fb89 100644 --- a/packages/adapter-launchdarkly/README.md +++ b/packages/adapter-launchdarkly/README.md @@ -12,7 +12,7 @@ npm i @flags-sdk/launchdarkly ## Provider Instance -**NOTE:** The [LaunchDarkly Vercel integration](https://vercel.com/integrations/launchdarkly) must be installed on your account, as this adapter loads LaunchDarkly from Edge Config. The adapter can not be used without Edge Config. +**NOTE:** The [LaunchDarkly Vercel integration](https://vercel.com/integrations/launchdarkly) must be installed on your account, as this adapter loads LaunchDarkly from Global Config. The adapter can not be used without Global Config. Import the default adapter instance `ldAdapter` from `@flags-sdk/launchdarkly`: @@ -25,14 +25,14 @@ The default adapter uses the following environment variables to configure itself ```sh export LAUNCHDARKLY_CLIENT_SIDE_ID="612376f91b8f5713a58777a1" export LAUNCHDARKLY_PROJECT_SLUG="my-project" -# Provided by the LaunchDarkly Marketplace integration when Edge Config is +# Provided by the LaunchDarkly Marketplace integration when Global Config is # enabled for the collection. export EXPERIMENTATION_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 +> the Global Config connection string from `EXPERIMENTATION_CONFIG` only. If your +> project provides the connection string as `GLOBAL_CONFIG`, set > `EXPERIMENTATION_CONFIG` to the same value, or pass it explicitly with > [`createLaunchDarklyAdapter`](#custom-adapter). @@ -65,10 +65,10 @@ import { createLaunchDarklyAdapter } from "@flags-sdk/launchdarkly"; const adapter = createLaunchDarklyAdapter({ projectSlug: "my-project", clientSideId: "612376f91b8f5713a58777a1", - // Legacy integrations that provide the connection string as `EDGE_CONFIG` + // Legacy integrations that provide the connection string as `GLOBAL_CONFIG` // can pass it explicitly here. - edgeConfigConnectionString: - process.env.EXPERIMENTATION_CONFIG ?? process.env.EDGE_CONFIG, + globalConfigConnectionString: + process.env.EXPERIMENTATION_CONFIG ?? process.env.GLOBAL_CONFIG, }); ``` diff --git a/packages/adapter-launchdarkly/package.json b/packages/adapter-launchdarkly/package.json index 29c289f1..771ea88f 100644 --- a/packages/adapter-launchdarkly/package.json +++ b/packages/adapter-launchdarkly/package.json @@ -6,7 +6,7 @@ "flags-sdk", "launchdarkly", "vercel", - "edge config", + "global config", "feature flags", "flags" ], diff --git a/packages/adapter-launchdarkly/src/index.ts b/packages/adapter-launchdarkly/src/index.ts index 38d0dce3..94d9cef7 100644 --- a/packages/adapter-launchdarkly/src/index.ts +++ b/packages/adapter-launchdarkly/src/index.ts @@ -39,19 +39,19 @@ function assertEnv(name: string): string { export function createLaunchDarklyAdapter({ projectSlug, clientSideId, - edgeConfigConnectionString, + globalConfigConnectionString, }: { projectSlug: string; clientSideId: string; - edgeConfigConnectionString: string; + globalConfigConnectionString: string; }): AdapterResponse { - const edgeConfigClient = createClient(edgeConfigConnectionString); + const globalConfigClient = createClient(globalConfigConnectionString); const store = new AsyncLocalStorage(); const cache = new WeakMap>(); const patchedGlobalConfigClient: GlobalConfigClient = { - ...edgeConfigClient, + ...globalConfigClient, get: async (key: string) => { const h = store.getStore(); if (h) { @@ -61,7 +61,7 @@ export function createLaunchDarklyAdapter({ } } - const promise = edgeConfigClient.get(key); + const promise = globalConfigClient.get(key); if (h) cache.set(h, promise); return promise; @@ -108,14 +108,14 @@ export function createLaunchDarklyAdapter({ function getOrCreateDeaultAdapter() { if (!defaultLaunchDarklyAdapter) { - const edgeConfigConnectionString = assertEnv('EXPERIMENTATION_CONFIG'); + const globalConfigConnectionString = assertEnv('EXPERIMENTATION_CONFIG'); const clientSideId = assertEnv('LAUNCHDARKLY_CLIENT_SIDE_ID'); const projectSlug = assertEnv('LAUNCHDARKLY_PROJECT_SLUG'); defaultLaunchDarklyAdapter = createLaunchDarklyAdapter({ projectSlug, clientSideId, - edgeConfigConnectionString, + globalConfigConnectionString, }); } diff --git a/packages/adapter-reflag/package.json b/packages/adapter-reflag/package.json index b228d4bf..5ee53499 100644 --- a/packages/adapter-reflag/package.json +++ b/packages/adapter-reflag/package.json @@ -6,7 +6,7 @@ "flags-sdk", "reflag", "vercel", - "edge config", + "global config", "feature flags", "flags" ], diff --git a/packages/adapter-statsig/package.json b/packages/adapter-statsig/package.json index a345718c..a7f5973f 100644 --- a/packages/adapter-statsig/package.json +++ b/packages/adapter-statsig/package.json @@ -7,7 +7,7 @@ "statsig", "dynamic config", "vercel", - "edge config", + "global config", "experiments", "experimentation", "ab testing" diff --git a/packages/adapter-statsig/src/edge-runtime-hooks.ts b/packages/adapter-statsig/src/edge-runtime-hooks.ts index ce3a4d00..a16c7afb 100644 --- a/packages/adapter-statsig/src/edge-runtime-hooks.ts +++ b/packages/adapter-statsig/src/edge-runtime-hooks.ts @@ -9,20 +9,22 @@ export const isEdgeRuntime = (): boolean => { }; /** - * The Edge Config Data Adapter is an optional peer dependency that allows - * the Statsig SDK to retrieve its data from Edge Config instead of over the network. + * The Global Config Data Adapter is an optional peer dependency that allows + * the Statsig SDK to retrieve its data from Global Config instead of over the network. */ -export async function createEdgeConfigDataAdapter(options: { - edgeConfigItemKey: string; - edgeConfigConnectionString: string; +export async function createGlobalConfigDataAdapter(options: { + globalConfigItemKey: string; + globalConfigConnectionString: string; }) { - // Edge Config adapter requires `@vercel/global-config` and `statsig-node-vercel` + // Global Config adapter requires `@vercel/global-config` and `statsig-node-vercel` // Since it is a peer dependency, we will import it dynamically - const { EdgeConfigDataAdapter } = await import('statsig-node-vercel'); + const { EdgeConfigDataAdapter: GlobalConfigDataAdapter } = await import( + 'statsig-node-vercel' + ); const { createClient } = await import('@vercel/global-config'); - return new EdgeConfigDataAdapter({ - edgeConfigItemKey: options.edgeConfigItemKey, - edgeConfigClient: createClient(options.edgeConfigConnectionString, { + return new GlobalConfigDataAdapter({ + edgeConfigItemKey: options.globalConfigItemKey, + edgeConfigClient: createClient(options.globalConfigConnectionString, { // We disable the development cache as Statsig caches for 10 seconds internally, // and we want to avoid situations where Statsig tries to read the latest value, // but hits the development cache and then caches the outdated value for another 10 seconds, @@ -46,7 +48,7 @@ export const createSyncingHandler = ( // // This needs to be fixed in statsig-node-lite in the future. // - // Ideally the Statsig SDK would not sync at all and instead always read from Edge Config, + // Ideally the Statsig SDK would not sync at all and instead always read from Global Config, // this would provide two benefits: // - changes would propagate immediately instead of being cached for 5s or 10s // - the broken syncing due to issues in Date.now in Edge Runtime would be irrelevant diff --git a/packages/adapter-statsig/src/index.ts b/packages/adapter-statsig/src/index.ts index 2518f39c..bc8cbc22 100644 --- a/packages/adapter-statsig/src/index.ts +++ b/packages/adapter-statsig/src/index.ts @@ -8,7 +8,7 @@ import Statsig, { type StatsigUser, } from 'statsig-node-lite'; import { - createEdgeConfigDataAdapter, + createGlobalConfigDataAdapter, createSyncingHandler, } from './edge-runtime-hooks'; @@ -52,18 +52,18 @@ export function createStatsigAdapter(options: { statsigOptions?: StatsigOptions; /** Provide the project ID to allow links to the Statsig console in the Vercel Toolbar */ statsigProjectId?: string; - /** Provide Edge Config details to use the optional Edge Config adapter */ - edgeConfig?: { + /** Provide Global Config details to use the optional Global Config adapter */ + globalConfig?: { connectionString: string; itemKey: string; }; }): AdapterResponse { const initializeStatsig = async (): Promise => { let dataAdapter: StatsigOptions['dataAdapter'] | undefined; - if (options.edgeConfig) { - dataAdapter = await createEdgeConfigDataAdapter({ - edgeConfigItemKey: options.edgeConfig.itemKey, - edgeConfigConnectionString: options.edgeConfig.connectionString, + if (options.globalConfig) { + dataAdapter = await createGlobalConfigDataAdapter({ + globalConfigItemKey: options.globalConfig.itemKey, + globalConfigConnectionString: options.globalConfig.connectionString, }); } @@ -101,7 +101,7 @@ export function createStatsigAdapter(options: { return user != null && typeof user === 'object'; }; - const minSyncDelayMs = options.edgeConfig ? 1_000 : 5_000; + const minSyncDelayMs = options.globalConfig ? 1_000 : 5_000; const syncHandler = createSyncingHandler(minSyncDelayMs); async function predecide(user?: StatsigUser): Promise { @@ -258,8 +258,8 @@ export function resetDefaultStatsigAdapter() { * * Optional: * - `STATSIG_PROJECT_ID` - Statsig project ID to enable link in Vercel's Flags Explorer - * - `EXPERIMENTATION_CONFIG` - Vercel Edge Config connection string - * - `EXPERIMENTATION_CONFIG_ITEM_KEY` - Vercel Edge Config item key where data is stored + * - `EXPERIMENTATION_CONFIG` - Vercel Global Config connection string + * - `EXPERIMENTATION_CONFIG_ITEM_KEY` - Vercel Global Config item key where data is stored */ export function createDefaultStatsigAdapter(): AdapterResponse { if (defaultStatsigAdapter) { @@ -267,9 +267,9 @@ export function createDefaultStatsigAdapter(): AdapterResponse { } const statsigServerApiKey = process.env.STATSIG_SERVER_API_KEY as string; const statsigProjectId = process.env.STATSIG_PROJECT_ID; - const edgeConfig = process.env.EXPERIMENTATION_CONFIG; - const edgeConfigItemKey = process.env.EXPERIMENTATION_CONFIG_ITEM_KEY; - if (!(edgeConfig && edgeConfigItemKey)) { + const globalConfig = process.env.EXPERIMENTATION_CONFIG; + const globalConfigItemKey = process.env.EXPERIMENTATION_CONFIG_ITEM_KEY; + if (!(globalConfig && globalConfigItemKey)) { defaultStatsigAdapter = createStatsigAdapter({ statsigServerApiKey, statsigProjectId, @@ -277,9 +277,9 @@ export function createDefaultStatsigAdapter(): AdapterResponse { } else { defaultStatsigAdapter = createStatsigAdapter({ statsigServerApiKey, - edgeConfig: { - connectionString: edgeConfig, - itemKey: edgeConfigItemKey, + globalConfig: { + connectionString: globalConfig, + itemKey: globalConfigItemKey, }, statsigProjectId, }); diff --git a/packages/flags/src/types.ts b/packages/flags/src/types.ts index 95e57aba..0bb9b258 100644 --- a/packages/flags/src/types.ts +++ b/packages/flags/src/types.ts @@ -26,9 +26,9 @@ export type Origin = projectId: string; } | { - provider: 'edge-config'; - edgeConfigId: string; - edgeConfigItemKey?: string; + provider: 'global-config'; + globalConfigId: string; + globalConfigItemKey?: string; teamSlug: string; } | Record; diff --git a/packages/vercel-flags-core/src/index.default.ts b/packages/vercel-flags-core/src/index.default.ts index 3431da97..b565a544 100644 --- a/packages/vercel-flags-core/src/index.default.ts +++ b/packages/vercel-flags-core/src/index.default.ts @@ -21,7 +21,7 @@ export const { * A lazily-initialized default flags client. * * - relies on process.env.FLAGS - * - does not use process.env.EDGE_CONFIG + * - does not use process.env.GLOBAL_CONFIG */ flagsClient, /** diff --git a/skills/flags-sdk/SKILL.md b/skills/flags-sdk/SKILL.md index dc3cf017..c8596e12 100644 --- a/skills/flags-sdk/SKILL.md +++ b/skills/flags-sdk/SKILL.md @@ -5,7 +5,7 @@ description: > Use when: declaring flags with `flag()`, using `vercelAdapter` or `vercel flags` CLI (add, list, enable, disable, inspect, archive, rm, sdk-keys), setting up providers/adapters (Vercel, Statsig, LaunchDarkly, PostHog, GrowthBook, Hypertune, - Edge Config, OpenFeature, Split, Flagsmith, Reflag, Optimizely, or custom adapters), + Global Config, OpenFeature, Split, Flagsmith, Reflag, Optimizely, or custom adapters), implementing precompute patterns for static pages, setting up `identify`/`dedupe`, integrating Flags Explorer/Toolbar, working with flags in Next.js (App Router, Pages Router, Middleware) or SvelteKit, @@ -365,5 +365,5 @@ Detailed framework and provider guides are in separate files to keep context lea - **[references/nextjs.md](references/nextjs.md)**: Next.js quickstart, toolbar, App Router, Pages Router, middleware/proxy, precompute, dedupe, dashboard pages, marketing pages, suspense fallbacks - **[references/sveltekit.md](references/sveltekit.md)**: SvelteKit quickstart, toolbar, hooks setup, precompute with reroute + middleware, dashboard pages, marketing pages -- **[references/providers.md](references/providers.md)**: All provider adapters — Vercel, Edge Config, Statsig, LaunchDarkly, PostHog, GrowthBook, Hypertune, Flagsmith, Reflag, Split, Optimizely, OpenFeature, and custom adapters +- **[references/providers.md](references/providers.md)**: All provider adapters — Vercel, Global Config, Statsig, LaunchDarkly, PostHog, GrowthBook, Hypertune, Flagsmith, Reflag, Split, Optimizely, OpenFeature, and custom adapters - **[references/api.md](references/api.md)**: Full API reference for `flags`, `flags/react`, `flags/next`, and `flags/sveltekit` diff --git a/skills/flags-sdk/references/providers.md b/skills/flags-sdk/references/providers.md index 81b8c289..5706bb4b 100644 --- a/skills/flags-sdk/references/providers.md +++ b/skills/flags-sdk/references/providers.md @@ -3,7 +3,7 @@ ## Table of Contents - [Vercel](#vercel) -- [Edge Config](#edge-config) +- [Global Config](#global-config) - [Statsig](#statsig) - [LaunchDarkly](#launchdarkly) - [PostHog](#posthog) @@ -192,7 +192,7 @@ Full CLI reference: https://vercel.com/docs/cli/flags --- -## Edge Config +## Global Config Package: `@flags-sdk/global-config` @@ -200,21 +200,21 @@ Package: `@flags-sdk/global-config` pnpm i @flags-sdk/global-config ``` -Env: `EDGE_CONFIG="edge-config-connection-string"` +Env: `GLOBAL_CONFIG="global-config-connection-string"` ### Usage ```ts import { flag } from 'flags/next'; -import { edgeConfigAdapter } from '@flags-sdk/global-config'; +import { globalConfigAdapter } from '@flags-sdk/global-config'; export const exampleFlag = flag({ - adapter: edgeConfigAdapter, + adapter: globalConfigAdapter, key: 'example-flag', }); ``` -Edge Config should contain: +Global Config should contain: ```json { @@ -228,12 +228,12 @@ Edge Config should contain: ### Custom configuration ```ts -import { createEdgeConfigAdapter } from '@flags-sdk/global-config'; +import { createGlobalConfigAdapter } from '@flags-sdk/global-config'; -const myAdapter = createEdgeConfigAdapter({ - connectionString: process.env.OTHER_EDGE_CONFIG, +const myAdapter = createGlobalConfigAdapter({ + connectionString: process.env.OTHER_GLOBAL_CONFIG, options: { - edgeConfigItemKey: 'other-flags-key', + globalConfigItemKey: 'other-flags-key', teamSlug: 'my-team', }, }); @@ -252,7 +252,7 @@ pnpm i @flags-sdk/statsig Env vars: - `STATSIG_SERVER_API_KEY` (required) - `STATSIG_PROJECT_ID` (optional) -- `EXPERIMENTATION_CONFIG` (optional, Edge Config) +- `EXPERIMENTATION_CONFIG` (optional, Global Config) - `EXPERIMENTATION_CONFIG_ITEM_KEY` (optional) ### Methods @@ -356,7 +356,7 @@ pnpm i @flags-sdk/launchdarkly Env vars: - `LAUNCHDARKLY_CLIENT_SIDE_ID` (required) - `LAUNCHDARKLY_PROJECT_SLUG` (required) -- `EDGE_CONFIG` (required) +- `GLOBAL_CONFIG` (required) ### Usage @@ -484,7 +484,7 @@ export const myFlag = flag({ }); ``` -### Edge Config +### Global Config Set `GROWTHBOOK_EDGE_CONNECTION_STRING` or `EXPERIMENTATION_CONFIG` (Vercel Marketplace). From 299e6f7d0c2bf37b5b034447f5198b970ceaf3ae Mon Sep 17 00:00:00 2001 From: Luis Meyer Date: Wed, 29 Jul 2026 13:04:15 +0200 Subject: [PATCH 3/5] Fix Global Config environment setup --- .github/workflows/release.yml | 4 ++-- examples/snippets/.env | 2 +- turbo.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8f6a9479..722e785e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -81,7 +81,7 @@ jobs: env: NPM_CONFIG_PROVENANCE: "true" GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - EDGE_CONFIG: ${{ secrets.EDGE_CONFIG }} + GLOBAL_CONFIG: ${{ secrets.GLOBAL_CONFIG }} FLAGS_SECRET: ${{ secrets.FLAGS_SECRET }} FLAGS: ${{ secrets.FLAGS }} HAPPYKIT_API_TOKEN: ${{ secrets.HAPPYKIT_API_TOKEN }} @@ -123,7 +123,7 @@ jobs: - name: Build run: pnpm turbo build --filter='./packages/*' env: - EDGE_CONFIG: ${{ secrets.EDGE_CONFIG }} + GLOBAL_CONFIG: ${{ secrets.GLOBAL_CONFIG }} FLAGS_SECRET: ${{ secrets.FLAGS_SECRET }} FLAGS: ${{ secrets.FLAGS }} HAPPYKIT_API_TOKEN: ${{ secrets.HAPPYKIT_API_TOKEN }} diff --git a/examples/snippets/.env b/examples/snippets/.env index ccca5b0b..60e619d3 100644 --- a/examples/snippets/.env +++ b/examples/snippets/.env @@ -1,3 +1,3 @@ # this is a random secret that can be used for testing FLAGS_SECRET=testing-secret-2pMFwxPkTiHKcrwRfFllrhT1KAc8 -EDGE_CONFIG="https://edge-config.vercel.com/ecfg_fvhsocnj9jbqprcriyscdnre3aix?token=6c514eae-1bf8-45b6-9277-ee6560280140" +GLOBAL_CONFIG="https://edge-config.vercel.com/ecfg_fvhsocnj9jbqprcriyscdnre3aix?token=6c514eae-1bf8-45b6-9277-ee6560280140" diff --git a/turbo.json b/turbo.json index 875d6057..60693278 100644 --- a/turbo.json +++ b/turbo.json @@ -15,7 +15,7 @@ "build": { "dependsOn": ["^build"], "env": [ - "EDGE_CONFIG", + "GLOBAL_CONFIG", "FLAGS_SECRET", "LAUNCHDARKLY_CLIENT_SIDE_ID", "LAUNCHDARKLY_PROJECT_SLUG", From ef03deca927ed105da01278dddf70ffe9b9e66fe Mon Sep 17 00:00:00 2001 From: Luis Meyer Date: Wed, 29 Jul 2026 13:05:52 +0200 Subject: [PATCH 4/5] Rename Global Config endpoints --- apps/docs/content/docs/providers/global-config.mdx | 2 +- apps/docs/content/docs/providers/growthbook.mdx | 2 +- apps/docs/content/docs/providers/hypertune.mdx | 4 ++-- examples/snippets/.env | 2 +- .../snippets/app/concepts/adapters/global-config-adapter.ts | 2 +- packages/adapter-global-config/src/index.test.ts | 4 ++-- packages/adapter-global-config/src/index.ts | 2 +- packages/adapter-launchdarkly/README.md | 2 +- packages/adapter-launchdarkly/src/index.test.ts | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/docs/content/docs/providers/global-config.mdx b/apps/docs/content/docs/providers/global-config.mdx index 68caf120..50ca9bc6 100644 --- a/apps/docs/content/docs/providers/global-config.mdx +++ b/apps/docs/content/docs/providers/global-config.mdx @@ -104,5 +104,5 @@ Read more about Global Config, Flags SDK, and the Global Config adapter. - [Concepts: Precompute](/principles/precompute) - [Global Config Docs](https://vercel.com/docs/storage/edge-config) - [Global Config SDK Reference](https://vercel.com/docs/storage/edge-config/edge-config-sdk) -- [Global Config Examples](https://vercel.com/templates/edge-config) +- [Global Config Examples](https://vercel.com/templates/global-config) - [Global Config Limits and Pricing](https://vercel.com/docs/storage/edge-config/edge-config-limits) diff --git a/apps/docs/content/docs/providers/growthbook.mdx b/apps/docs/content/docs/providers/growthbook.mdx index b5d6c2f5..40f66c75 100644 --- a/apps/docs/content/docs/providers/growthbook.mdx +++ b/apps/docs/content/docs/providers/growthbook.mdx @@ -196,7 +196,7 @@ Under the hood, the webhook is being configured with the following properties. I - **Endpoint URL** is being set to ``` - https://api.vercel.com/v1/edge-config/{edge_config_id}/items + https://api.vercel.com/v1/global-config/{global_config_id}/items ``` - **Method** is being set to `PATCH` - An **Authorization: Bearer token** header is being added with your Vercel API Token diff --git a/apps/docs/content/docs/providers/hypertune.mdx b/apps/docs/content/docs/providers/hypertune.mdx index 33097117..0b50725d 100644 --- a/apps/docs/content/docs/providers/hypertune.mdx +++ b/apps/docs/content/docs/providers/hypertune.mdx @@ -103,7 +103,7 @@ export const GET = createFlagsDiscoveryEndpoint(() => { If Hypertune is syncing to Vercel Global Config, you can configure that through environment variables or through the adapter. ```bash title=".env.local" -EXPERIMENTATION_CONFIG="https://edge-config.vercel.com/ecfg_xyz?token=abc" +EXPERIMENTATION_CONFIG="https://global-config.vercel.com/ecfg_xyz?token=abc" EXPERIMENTATION_CONFIG_ITEM_KEY="hypertune_99999" ``` @@ -119,7 +119,7 @@ const hypertuneAdapter = createHypertuneAdapter< createSourceOptions: { initDataProvider: new VercelGlobalConfigInitDataProvider({ edgeConfigClient: createClient( - 'https://edge-config.vercel.com/ecfg_xyz?token=abc' + 'https://global-config.vercel.com/ecfg_xyz?token=abc' ), itemKey: 'hypertune_99999', }), diff --git a/examples/snippets/.env b/examples/snippets/.env index 60e619d3..42ce1b7a 100644 --- a/examples/snippets/.env +++ b/examples/snippets/.env @@ -1,3 +1,3 @@ # this is a random secret that can be used for testing FLAGS_SECRET=testing-secret-2pMFwxPkTiHKcrwRfFllrhT1KAc8 -GLOBAL_CONFIG="https://edge-config.vercel.com/ecfg_fvhsocnj9jbqprcriyscdnre3aix?token=6c514eae-1bf8-45b6-9277-ee6560280140" +GLOBAL_CONFIG="https://global-config.vercel.com/ecfg_fvhsocnj9jbqprcriyscdnre3aix?token=6c514eae-1bf8-45b6-9277-ee6560280140" diff --git a/examples/snippets/app/concepts/adapters/global-config-adapter.ts b/examples/snippets/app/concepts/adapters/global-config-adapter.ts index 8a6c4d6f..64f93acc 100644 --- a/examples/snippets/app/concepts/adapters/global-config-adapter.ts +++ b/examples/snippets/app/concepts/adapters/global-config-adapter.ts @@ -27,7 +27,7 @@ export function createGlobalConfigAdapter( > { return { origin: options?.teamSlug - ? `https://vercel.com/${options.teamSlug}/~/stores/edge-config/${globalConfigClient.connection.id}/items#item=${globalConfigItemKey}` + ? `https://vercel.com/${options.teamSlug}/~/stores/global-config/${globalConfigClient.connection.id}/items#item=${globalConfigItemKey}` : undefined, async decide({ key }): Promise { const definitions = diff --git a/packages/adapter-global-config/src/index.test.ts b/packages/adapter-global-config/src/index.test.ts index cc43ca0c..330f07ff 100644 --- a/packages/adapter-global-config/src/index.test.ts +++ b/packages/adapter-global-config/src/index.test.ts @@ -106,7 +106,7 @@ describe('createGlobalConfigAdapter', () => { it('should allow creating an adapter with a connection string', () => { const adapter = createGlobalConfigAdapter( - 'https://edge-config.vercel.com/ecfg_xxx?token=yyy', + 'https://global-config.vercel.com/ecfg_xxx?token=yyy', ); expect(adapter).toBeDefined(); }); @@ -205,7 +205,7 @@ describe('globalConfigAdapter', () => { it('should export a default adapter', () => { process.env.GLOBAL_CONFIG = - 'https://edge-config.vercel.com/ecfg_xxx?token=yyy'; + 'https://global-config.vercel.com/ecfg_xxx?token=yyy'; const adapter = globalConfigAdapter(); expect(adapter).toBeDefined(); delete process.env.GLOBAL_CONFIG; diff --git a/packages/adapter-global-config/src/index.ts b/packages/adapter-global-config/src/index.ts index 571ab3c6..9f9a93a3 100644 --- a/packages/adapter-global-config/src/index.ts +++ b/packages/adapter-global-config/src/index.ts @@ -87,7 +87,7 @@ export function createGlobalConfigAdapter( const adapter: Adapter = { adapterId, origin: options?.teamSlug - ? `https://vercel.com/${options.teamSlug}/~/stores/edge-config/${globalConfigClient.connection.id}/items#item=${globalConfigItemKey}` + ? `https://vercel.com/${options.teamSlug}/~/stores/global-config/${globalConfigClient.connection.id}/items#item=${globalConfigItemKey}` : undefined, async decide({ key, headers }): Promise { const definitions = await getDefinitions(headers); diff --git a/packages/adapter-launchdarkly/README.md b/packages/adapter-launchdarkly/README.md index 9cc7fb89..b5fbb83b 100644 --- a/packages/adapter-launchdarkly/README.md +++ b/packages/adapter-launchdarkly/README.md @@ -27,7 +27,7 @@ export LAUNCHDARKLY_CLIENT_SIDE_ID="612376f91b8f5713a58777a1" export LAUNCHDARKLY_PROJECT_SLUG="my-project" # Provided by the LaunchDarkly Marketplace integration when Global Config is # enabled for the collection. -export EXPERIMENTATION_CONFIG="https://edge-config.vercel.com/ecfg_abdc1234?token=xxx-xxx-xxx" +export EXPERIMENTATION_CONFIG="https://global-config.vercel.com/ecfg_abdc1234?token=xxx-xxx-xxx" ``` > **Using the legacy LaunchDarkly Vercel integration?** The default adapter reads diff --git a/packages/adapter-launchdarkly/src/index.test.ts b/packages/adapter-launchdarkly/src/index.test.ts index 09cde89f..34244242 100644 --- a/packages/adapter-launchdarkly/src/index.test.ts +++ b/packages/adapter-launchdarkly/src/index.test.ts @@ -34,7 +34,7 @@ describe('ldAdapter', () => { process.env.LAUNCHDARKLY_PROJECT_SLUG = 'test-project'; process.env.LAUNCHDARKLY_CLIENT_SIDE_ID = 'test-client-side-id'; process.env.EXPERIMENTATION_CONFIG = - 'https://edge-config.com/test-experimentation-config'; + 'https://global-config.com/test-experimentation-config'; }); it('should expose the ldClient', () => { From ee10913d82d2ee81cfd5682ba3790b8ec7419d2c Mon Sep 17 00:00:00 2001 From: Luis Meyer Date: Wed, 29 Jul 2026 15:08:18 +0200 Subject: [PATCH 5/5] Update Global Config documentation links --- apps/docs/content/docs/providers/global-config.mdx | 12 ++++++------ apps/docs/content/docs/providers/growthbook.mdx | 4 ++-- apps/docs/content/docs/providers/hypertune.mdx | 2 +- apps/docs/content/docs/providers/launchdarkly.mdx | 2 +- apps/docs/content/docs/providers/statsig.mdx | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/docs/content/docs/providers/global-config.mdx b/apps/docs/content/docs/providers/global-config.mdx index 50ca9bc6..6fb85255 100644 --- a/apps/docs/content/docs/providers/global-config.mdx +++ b/apps/docs/content/docs/providers/global-config.mdx @@ -2,7 +2,7 @@ title: 'Global Config' --- -The `@flags-sdk/global-config` package provides a basic adapter for defining feature flags powered by [Vercel Global Config](https://vercel.com/docs/storage/edge-config) +The `@flags-sdk/global-config` package provides a basic adapter for defining feature flags powered by [Vercel Global Config](https://vercel.com/docs/storage/global-config) { - [GrowthBook Documentation](https://docs.growthbook.io/) - [GrowthBook JS SDK Reference](https://docs.growthbook.io/lib/js) -- [Vercel Global Config](https://vercel.com/docs/storage/edge-config) +- [Vercel Global Config](https://vercel.com/docs/storage/global-config) - [Flags Explorer](https://vercel.com/docs/flags/flags-explorer) - [Deploy the GrowthBook template](https://vercel.com/templates/next.js/growthbook-flags-sdk-example) diff --git a/apps/docs/content/docs/providers/hypertune.mdx b/apps/docs/content/docs/providers/hypertune.mdx index 0b50725d..c62097de 100644 --- a/apps/docs/content/docs/providers/hypertune.mdx +++ b/apps/docs/content/docs/providers/hypertune.mdx @@ -130,6 +130,6 @@ const hypertuneAdapter = createHypertuneAdapter< ## More resources - [Hypertune Documentation](https://docs.hypertune.com/) -- [Vercel Global Config](https://vercel.com/docs/edge-config) +- [Vercel Global Config](https://vercel.com/docs/global-config) - [Flags Explorer](https://vercel.com/docs/flags/flags-explorer) - [Hypertune OpenFeature Provider](/providers/openfeature/hypertune) diff --git a/apps/docs/content/docs/providers/launchdarkly.mdx b/apps/docs/content/docs/providers/launchdarkly.mdx index 7bbc9c98..adc00e43 100644 --- a/apps/docs/content/docs/providers/launchdarkly.mdx +++ b/apps/docs/content/docs/providers/launchdarkly.mdx @@ -146,7 +146,7 @@ ldAdapter.ldClient; ## Global Config -The LaunchDarkly adapter loads the configuration from [Global Config](https://vercel.com/storage/edge-config). +The LaunchDarkly adapter loads the configuration from [Global Config](https://vercel.com/storage/global-config). Global Config is a global, ultra-low latency store which uses active replication and is specifically designed for serving feature flag configuration. diff --git a/apps/docs/content/docs/providers/statsig.mdx b/apps/docs/content/docs/providers/statsig.mdx index a0777642..2646ee13 100644 --- a/apps/docs/content/docs/providers/statsig.mdx +++ b/apps/docs/content/docs/providers/statsig.mdx @@ -356,9 +356,9 @@ Read more about initialization strategies in the [Statsig Docs](https://docs.sta ## Global Config -The Statsig adapter can either load the experiment configuration over the network or bootstrap from [Global Config](https://vercel.com/storage/edge-config). +The Statsig adapter can either load the experiment configuration over the network or bootstrap from [Global Config](https://vercel.com/storage/global-config). -Using [Global Config](https://vercel.com/docs/storage/edge-config) is optional but recommended for the best latency. Global Config is a global, ultra-low latency store which uses active replication and is specifically designed for serving feature flag configuration. +Using [Global Config](https://vercel.com/docs/storage/global-config) is optional but recommended for the best latency. Global Config is a global, ultra-low latency store which uses active replication and is specifically designed for serving feature flag configuration. The default Statsig adapter, exported as `statsigAdapter`, will automatically connect to Global Config if the `EXPERIMENTATION_CONFIG` and `EXPERIMENTATION_CONFIG_ITEM_KEY` environment variables are set. If you are using the [Statsig integration on Vercel marketplace](https://vercel.com/marketplace/statsig) these environment variables will be provided automatically, and the default Statsig adapter will read from Global Config automatically.