From 6b066ac8ee9fbf05393c74889418f0d49578ec01 Mon Sep 17 00:00:00 2001 From: Henry Barrow Date: Fri, 2 Jun 2023 14:40:24 +0100 Subject: [PATCH 1/3] Update Vercel example --- packages/sdk/vercel/example-vercel/.gitignore | 147 ++++++++++++++---- packages/sdk/vercel/example-vercel/README.md | 44 ++++-- .../sdk/vercel/example-vercel/next-env.d.ts | 5 + .../sdk/vercel/example-vercel/package.json | 12 +- .../example-vercel/src/app/api/hello/route.ts | 52 ++++--- .../vercel/example-vercel/src/app/page.tsx | 19 ++- 6 files changed, 203 insertions(+), 76 deletions(-) create mode 100644 packages/sdk/vercel/example-vercel/next-env.d.ts diff --git a/packages/sdk/vercel/example-vercel/.gitignore b/packages/sdk/vercel/example-vercel/.gitignore index 983df7c7d3..caf544da4e 100644 --- a/packages/sdk/vercel/example-vercel/.gitignore +++ b/packages/sdk/vercel/example-vercel/.gitignore @@ -1,36 +1,131 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* -# dependencies -/node_modules -/.pnp -.pnp.js +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json -# testing -/coverage +# Runtime data +pids +*.pid +*.seed +*.pid.lock -# next.js -/.next/ -/out/ +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov -# production -/build +# Coverage directory used by tools like istanbul +coverage +*.lcov -# misc -.DS_Store -*.pem +# nyc test coverage +.nyc_output -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt -# local env files -.env*.local +# Bower dependency directory (https://bower.io/) +bower_components -# vercel -.vercel +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release -# typescript +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache *.tsbuildinfo -next-env.d.ts -.vscode + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* +.vercel diff --git a/packages/sdk/vercel/example-vercel/README.md b/packages/sdk/vercel/example-vercel/README.md index 5a60fc48eb..52bf2f6a32 100644 --- a/packages/sdk/vercel/example-vercel/README.md +++ b/packages/sdk/vercel/example-vercel/README.md @@ -1,30 +1,54 @@ # Example test app for Vercel LaunchDarkly SDK This is an example test app to showcase the usage of the Vercel LaunchDarkly -SDK. This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). +SDK to evaluate a feature flag in a [Route Handler](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) using [Vercel's edge runtime](https://nextjs.org/docs/app/building-your-application/routing/router-handlers#edge-and-nodejs-runtimes). This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). + +Most of the LaunchDarkly-related code can be found in [src/app/api/hello/route.ts](src/app/api/hello/route.ts). ## Prerequisites A node environment of version 16 and yarn are required to develop in this repository. -You will also need the vercel cli installed and a Vercel account to setup -the test data required by this example. See the [Vercel docs](https://vercel.com/docs/storage/edge-config/get-started) on how to setup your edge config store. +You will also need the [Vercel CLI](https://vercel.com/docs/cli) installed and a Vercel account to setup +the test data required by this example. See the [Vercel docs](https://vercel.com/docs/storage/edge-config/get-started) on how to setup your Edge Config store. + +## Setting up your LaunchDarkly environment + +For simplicity, we recommend [creating a new LaunchDarkly project](https://docs.launchdarkly.com/home/organize/projects/?q=create+proj) for this example app. After creating a new project, create the following feature flags with Client-side SDK availability: -## Usage +- `test-flag` - (Boolean) - This flag is evaluated in [src/app/api/hello/route.ts](src/app/api/hello/route.ts). -1. Follow the [Vercel docs](https://vercel.com/docs/storage/edge-config/get-started) to insert [testData.json](https://github.com/launchdarkly/js-core/blob/main/packages/sdk/vercel/testData.json) to your edge config store. +After creating your project, You will need to have the LaunchDarkly Vercel integration configured to push feature flag data to your Vercel Edge Config. Read [Vercel](https://docs.launchdarkly.com/integrations/vercel/) to set up the integration. Be sure to connect the **Test** environment for project you created above. -2. After completing the guide above, you should have linked this example app to your Vercel project and created an `.env.development.local`. +## Setting up your development environment + +1. Copy this directory in a new repository. +2. Create a new Vercel project based on the new repository. +3. [Add a new environment variable to your project](https://vercel.com/docs/concepts/projects/environment-variables) named `LD_CLIENT_SIDE_ID` and set it to the LaunchDarkly client-side ID for the **Test** environment in the project you created above. +4. Follow [Vercel's documentation](https://vercel.com/docs/storage/edge-config/get-started) to connect an Edge Config to your new project. +5. Run the following command to link your local codebase to your Vercel project: + +```shell +vercel link +``` + +6. Run the following command to sync your projects environment variables in your development environment: + +```shell +vercel env pull .env.development.local +``` -3. At the root of the js-core repo: +7. After completing the guide above, you should have linked this example app to your Vercel project and created an `.env.development.local`. +8. Verify the contents of `.env.development.local` have values for the `LD_CLIENT_SIDE_ID` and `EDGE_CONFIG`. +9. Run the following command to install all dependencies: ```shell -yarn && yarn build +yarn ``` -4. Then back in this example folder: +10. Run the following command to start your development environment: ```shell yarn dev ``` -5. Open [http://localhost:3000/api/hello](http://localhost:3000/api/hello). +11. Open [http://localhost:3000/api/hello](http://localhost:3000/api/hello). diff --git a/packages/sdk/vercel/example-vercel/next-env.d.ts b/packages/sdk/vercel/example-vercel/next-env.d.ts new file mode 100644 index 0000000000..4f11a03dc6 --- /dev/null +++ b/packages/sdk/vercel/example-vercel/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/packages/sdk/vercel/example-vercel/package.json b/packages/sdk/vercel/example-vercel/package.json index 627f6bd73a..e88d520997 100644 --- a/packages/sdk/vercel/example-vercel/package.json +++ b/packages/sdk/vercel/example-vercel/package.json @@ -4,21 +4,21 @@ "packageManager": "yarn@3.4.1", "scripts": { "dev": "next dev", - "build": "tsc", + "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "@launchdarkly/vercel-server-sdk": "0.3.0", - "@vercel/edge-config": "^0.1.8", - "next": "13.3.1", - "react": "18.2.0", + "@vercel/edge-config": "^0.2.1", + "next": "^13.4.4", + "react": "^18.2.0", "react-dom": "18.2.0" }, "devDependencies": { "@types/node": "18.16.2", - "@types/react": "18.2.0", - "@types/react-dom": "18.2.1", + "@types/react": "^18.2.7", + "@types/react-dom": "^18.2.4", "autoprefixer": "10.4.14", "postcss": "8.4.23", "tailwindcss": "3.3.2", diff --git a/packages/sdk/vercel/example-vercel/src/app/api/hello/route.ts b/packages/sdk/vercel/example-vercel/src/app/api/hello/route.ts index 391d75db28..ebd718b498 100644 --- a/packages/sdk/vercel/example-vercel/src/app/api/hello/route.ts +++ b/packages/sdk/vercel/example-vercel/src/app/api/hello/route.ts @@ -1,37 +1,41 @@ -import { NextResponse } from 'next/server'; -import { createClient } from '@vercel/edge-config'; -import { init as initLD } from '@launchdarkly/vercel-server-sdk'; +import { NextResponse } from "next/server"; +import { createClient } from "@vercel/edge-config"; +import { init as initLD } from "@launchdarkly/vercel-server-sdk"; -export const config = { - runtime: 'edge', -}; +export const runtime = "edge"; export async function GET() { - const sdkKey = 'test-sdk-key'; - const flagKey = 'testFlag1'; + const clientSideID = process.env.LD_CLIENT_SIDE_ID; + if (!clientSideID) { + return NextResponse.json( + { + error: "LD_CLIENT_SIDE_ID environment variable is missing.", + }, + { status: 500 } + ); + } + const flagKey = "test-flag"; - // default fallthrough evaluates to true - const contextFallthrough = { kind: 'user', key: 'test-user-key-1' }; - - // matches email targeting rule evaluates to false - const contextEmailRule = { kind: 'user', key: 'test-user-key-1', email: 'test@gmail.com' }; + // This is just a simple example context. You can also include request information such as headers and path or user ID + // if the request is authenticated. + const flagContext = { kind: "user", key: "test-user-key-1" }; const vercelClient = createClient(process.env.EDGE_CONFIG); - // start using ld - const client = initLD(sdkKey, vercelClient); + const client = initLD(clientSideID, vercelClient); await client.waitForInitialization(); - const fallthrough = await client.variation(flagKey, contextFallthrough, false); - const emailRule = await client.variation(flagKey, contextEmailRule, false); - const flagDetail = await client.variationDetail(flagKey, contextEmailRule, false); - const allFlags = await client.allFlagsState(contextEmailRule); + + // Use .variation() to evaluate a single feature flag for a given context. + const testFlagVariation = await client.variation(flagKey, flagContext, false); + + // allFlagsState() returns an object containing the variations served for all feature flags for a given context. + // This is useful for bootstrapping flags for use in the LaunchDarkly React SDK or JS client-side SDK. + const allFlags = await client.allFlagsState(flagContext); return NextResponse.json({ flagKey: `${flagKey}`, - contextKey: `${contextFallthrough.key}`, - fallthrough, - emailRule, - emailRuleDetail: `${JSON.stringify(flagDetail)}`, - allFlags: `${JSON.stringify(allFlags)}`, + context: flagContext, + variationServed: testFlagVariation, + allFlags: allFlags.toJSON(), }); } diff --git a/packages/sdk/vercel/example-vercel/src/app/page.tsx b/packages/sdk/vercel/example-vercel/src/app/page.tsx index b83bb1bb26..e46c38cb02 100644 --- a/packages/sdk/vercel/example-vercel/src/app/page.tsx +++ b/packages/sdk/vercel/example-vercel/src/app/page.tsx @@ -1,15 +1,14 @@ -import Image from 'next/image'; -import { Inter } from 'next/font/google'; +import Image from "next/image"; +import { Inter } from "next/font/google"; -const inter = Inter({ subsets: ['latin'] }); +const inter = Inter({ subsets: ["latin"] }); export default function Home() { return (

- Get started by editing  - src/app/page.tsx + Get started by visiting /api/hello

- By{' '} + By{" "} Vercel Logo

- Docs{' '} + Docs{" "} -> @@ -67,7 +66,7 @@ export default function Home() { rel="noopener noreferrer" >

- Learn{' '} + Learn{" "} -> @@ -84,7 +83,7 @@ export default function Home() { rel="noopener noreferrer" >

- Templates{' '} + Templates{" "} -> @@ -101,7 +100,7 @@ export default function Home() { rel="noopener noreferrer" >

- Deploy{' '} + Deploy{" "} -> From 7546240e31dd8bf706748a5fa0373e95711d407a Mon Sep 17 00:00:00 2001 From: Henry Barrow Date: Fri, 2 Jun 2023 14:45:28 +0100 Subject: [PATCH 2/3] run prettier --- .../example-vercel/src/app/api/hello/route.ts | 14 +++++++------- .../sdk/vercel/example-vercel/src/app/page.tsx | 16 ++++++++-------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/sdk/vercel/example-vercel/src/app/api/hello/route.ts b/packages/sdk/vercel/example-vercel/src/app/api/hello/route.ts index ebd718b498..9008ea7a82 100644 --- a/packages/sdk/vercel/example-vercel/src/app/api/hello/route.ts +++ b/packages/sdk/vercel/example-vercel/src/app/api/hello/route.ts @@ -1,24 +1,24 @@ -import { NextResponse } from "next/server"; -import { createClient } from "@vercel/edge-config"; -import { init as initLD } from "@launchdarkly/vercel-server-sdk"; +import { NextResponse } from 'next/server'; +import { createClient } from '@vercel/edge-config'; +import { init as initLD } from '@launchdarkly/vercel-server-sdk'; -export const runtime = "edge"; +export const runtime = 'edge'; export async function GET() { const clientSideID = process.env.LD_CLIENT_SIDE_ID; if (!clientSideID) { return NextResponse.json( { - error: "LD_CLIENT_SIDE_ID environment variable is missing.", + error: 'LD_CLIENT_SIDE_ID environment variable is missing.', }, { status: 500 } ); } - const flagKey = "test-flag"; + const flagKey = 'test-flag'; // This is just a simple example context. You can also include request information such as headers and path or user ID // if the request is authenticated. - const flagContext = { kind: "user", key: "test-user-key-1" }; + const flagContext = { kind: 'user', key: 'test-user-key-1' }; const vercelClient = createClient(process.env.EDGE_CONFIG); diff --git a/packages/sdk/vercel/example-vercel/src/app/page.tsx b/packages/sdk/vercel/example-vercel/src/app/page.tsx index e46c38cb02..29f446819e 100644 --- a/packages/sdk/vercel/example-vercel/src/app/page.tsx +++ b/packages/sdk/vercel/example-vercel/src/app/page.tsx @@ -1,7 +1,7 @@ -import Image from "next/image"; -import { Inter } from "next/font/google"; +import Image from 'next/image'; +import { Inter } from 'next/font/google'; -const inter = Inter({ subsets: ["latin"] }); +const inter = Inter({ subsets: ['latin'] }); export default function Home() { return ( @@ -17,7 +17,7 @@ export default function Home() { target="_blank" rel="noopener noreferrer" > - By{" "} + By{' '} Vercel Logo

- Docs{" "} + Docs{' '} -> @@ -66,7 +66,7 @@ export default function Home() { rel="noopener noreferrer" >

- Learn{" "} + Learn{' '} -> @@ -83,7 +83,7 @@ export default function Home() { rel="noopener noreferrer" >

- Templates{" "} + Templates{' '} -> @@ -100,7 +100,7 @@ export default function Home() { rel="noopener noreferrer" >

- Deploy{" "} + Deploy{' '} -> From b7ee75bb27812546c2f5dff54cc70263ccc3e305 Mon Sep 17 00:00:00 2001 From: Henry Barrow Date: Fri, 2 Jun 2023 14:54:24 +0100 Subject: [PATCH 3/3] Update packages/sdk/vercel/example-vercel/README.md Co-authored-by: Fabian --- packages/sdk/vercel/example-vercel/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sdk/vercel/example-vercel/README.md b/packages/sdk/vercel/example-vercel/README.md index 52bf2f6a32..788d3a4b46 100644 --- a/packages/sdk/vercel/example-vercel/README.md +++ b/packages/sdk/vercel/example-vercel/README.md @@ -17,7 +17,7 @@ For simplicity, we recommend [creating a new LaunchDarkly project](https://docs. - `test-flag` - (Boolean) - This flag is evaluated in [src/app/api/hello/route.ts](src/app/api/hello/route.ts). -After creating your project, You will need to have the LaunchDarkly Vercel integration configured to push feature flag data to your Vercel Edge Config. Read [Vercel](https://docs.launchdarkly.com/integrations/vercel/) to set up the integration. Be sure to connect the **Test** environment for project you created above. +After creating your project, you will need to configure the LaunchDarkly Vercel integration to push feature flag data to your Vercel Edge Config. Read the [Vercel integration documentation](https://docs.launchdarkly.com/integrations/vercel/) to set up the integration. Be sure to connect the **Test** environment from the project you created above. ## Setting up your development environment