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..788d3a4b46 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 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. -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..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 @@ -2,36 +2,40 @@ 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..29f446819e 100644 --- a/packages/sdk/vercel/example-vercel/src/app/page.tsx +++ b/packages/sdk/vercel/example-vercel/src/app/page.tsx @@ -8,8 +8,7 @@ export default function Home() {

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