diff --git a/docs/docs/clients/server-side.mdx b/docs/docs/clients/server-side.mdx index 925f8e46b8a4..dbfa6500606f 100644 --- a/docs/docs/clients/server-side.mdx +++ b/docs/docs/clients/server-side.mdx @@ -8,7 +8,13 @@ import CodeBlock from '@theme/CodeBlock'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -import { JavaVersion, RustVersion, DotnetVersion, ElixirVersion } from '@site/src/components/SdkVersions.js'; +import { + JavaVersion, + RustVersion, + DotnetVersion, + ElixirVersion, + NodejsVersion, +} from '@site/src/components/SdkVersions.js'; # Server Side SDKs @@ -40,11 +46,10 @@ Server Side SDKs can run in 2 different modes: Local Evaluation and Remote Evalu - Source Code: https://github.com/Flagsmith/flagsmith-dotnet-client - + -- Version Compatibility: **Node 14+** -- Source Code: - - https://github.com/Flagsmith/flagsmith-nodejs-client +- Version Compatibility: **Node 18+** +- Source Code: https://github.com/Flagsmith/flagsmith-nodejs-client @@ -140,11 +145,10 @@ pip install flagsmith - + ```bash -# Via NPM -npm i flagsmith-nodejs --save +npm install flagsmith-nodejs ``` @@ -245,10 +249,10 @@ _flagsmithClient = new("FLAGSMITH_SERVER_SIDE_ENVIRONMENT_KEY"); ``` - + ```javascript -const Flagsmith = require('flagsmith-nodejs'); +import { Flagsmith } from 'flagsmith-nodejs'; const flagsmith = new Flagsmith({ environmentKey: 'FLAGSMITH_SERVER_SIDE_ENVIRONMENT_KEY', @@ -367,12 +371,12 @@ var buttonData = await flags.GetFeatureValue("secret_button"); ``` - + ```javascript const flags = await flagsmith.getEnvironmentFlags(); -var showButton = flags.isFeatureEnabled('secret_button'); -var buttonData = flags.getFeatureValue('secret_button'); +const showButton = flags.isFeatureEnabled('secret_button'); +const buttonData = flags.getFeatureValue('secret_button'); ``` @@ -479,7 +483,7 @@ var showButton = await flags.IsFeatureEnabled("secret_button"); ``` - + ```javascript const identifier = 'delboy@trotterstraders.co.uk'; @@ -662,7 +666,7 @@ static Flag defaultFlagHandler(string featureName) ``` - + ```javascript const flagsmith = new Flagsmith({ @@ -853,18 +857,32 @@ public class MyCustomOfflineHandler: BaseOfflineHandler ``` - + -```javascript -// Using the built-in local file handler -const localFileHandler = new LocalFileHandler('path_to_environment_file/environment_file.json'); -const flagsmith = new Flagsmith({ offlineMode: true, offlineHandler: localFileHandler }); +Use LocalFileHandler +to read an environment file generated by the [Flagsmith CLI](/clients/CLI): -// Defining a custom offline handler -class CustomOfflineHandler extends BaseOfflineHandler { - getEnvironment(): EnvironmentModel { - return someMethodToGetTheEnvironment(); - } +```typescript +import { Flagsmith, LocalFileHandler } from 'flagsmith-nodejs'; + +const flagsmith = new Flagsmith({ + offlineMode: true, + offlineHandler: new LocalFileHandler('./flagsmith.json'), +}); +``` + +To create your own offline handler, implement the `BaseOfflineHandler` interface. It must return an +{/* prettier-ignore */}EnvironmentModel +object: + +```typescript +import type { BaseOfflineHandler, EnvironmentModel } from 'flagsmith-nodejs'; + +class CustomOfflineHandler implements BaseOfflineHandler { + getEnvironment(): EnvironmentModel { + // ... + } } ``` @@ -1015,10 +1033,9 @@ flagsmith.close(); ``` - + ```javascript -// available from v2.2.1 flagsmith.close(); ``` @@ -1413,10 +1430,11 @@ $flagsmith = Flagsmith::Client.new( ``` - + ```typescript -import { bool, number } from 'prop-types'; +import { Flagsmith } from 'flagsmith-nodejs'; +import type { EnvironmentModel } from 'flagsmith-nodejs'; const flagsmith = new Flagsmith({ /* @@ -1440,9 +1458,8 @@ const flagsmith = new Flagsmith({ See https://docs.flagsmith.com/clients/server-side#caching */ cache: { - has: (key: string) => bool, - get: (key: string) => string | number | null, - set: (k: string, v: Flags) => (cache[k] = v), + get: (key: string) => Promise.resolve(), + set: (k: string, v: Flags) => Promise.resolve(), }, /* @@ -1780,7 +1797,8 @@ client_configuration = Flagsmith.Client.new( ## Caching -The following SDKs have code and functionality related to caching flags. +Some SDKs support caching flags retrieved from the Flagsmith API, or calculated from your environment definition if +using Local Evaluation. @@ -1874,68 +1892,37 @@ final FlagsAndTraits flags = cache.getIfPresent(projectLevelCacheKey); ``` - + -You can initialise the SDK with something like this: +The `cache` option in the `Flagsmith` constructor accepts a cache implementation. This cache must implement the +{/* prettier-ignore */}FlagsmithCache +interface. -```javascript -flagsmith.init({ - cache: { - has:(key)=> return Promise.resolve(!!cache[key]) , // true | false - get: (k)=> cache[k] // return flags or flags for user - set: (k,v)=> cache[k] = v // gets called if has returns false with response from API for Identify or getFlags - } -}) -``` +For example, this cache implementation uses Redis as a backing store: -The core concept is that if `has` returns false, the SDK will make the required API calls under the hood. The keys are -either `flags` or `flags_traits-${identity}`. - -An example of a concrete implemention is below. - -```javascript -const flagsmith = require('flagsmith-nodejs'); -const redis = require('redis'); +```typescript +import { Flagsmith } from 'flagsmith-nodejs'; +import type { BaseOfflineHandler, EnvironmentModel, Flags, FlagsmithCache } from 'flagsmith-nodejs'; +import * as redis from 'redis'; const redisClient = redis.createClient({ - host: 'localhost', - port: 6379, + url: 'localhost:6379', }); -flagsmith.init({ - environmentID: 'FLAGSMITH_SERVER_SIDE_ENVIRONMENT_KEY', - cache: { - has: (key) => - new Promise((resolve, reject) => { - redisClient.exists(key, (err, reply) => { - console.log('check ' + key + ' from cache', err, reply); - resolve(reply === 1); - }); - }), - get: (key) => - new Promise((resolve) => { - redisClient.get(key, (err, cacheValue) => { - console.log('get ' + key + ' from cache'); - resolve(cacheValue && JSON.parse(cacheValue)); - }); - }), - set: (key, value) => - new Promise((resolve) => { - // Expire the key after 60 seconds - redisClient.set(key, JSON.stringify(value), 'EX', 60, (err, reply) => { - console.log('set ' + key + ' to cache', err); - resolve(); - }); - }), +const redisFlagsmithCache = { + async get(key: string): Promise { + const cachedValue = await redisClient.get(key); + return Promise.resolve(cachedValue && JSON.parse(cachedValue)); }, -}); + async set(key: string, value: Flags): Promise { + await redisClient.set(key, JSON.stringify(value), { EX: 60 }); + return Promise.resolve(); + }, +} satisfies FlagsmithCache; -router.get('/', function (req, res, next) { - flagsmith.getValue('background_colour').then((value) => { - res.render('index', { - title: value, - }); - }); +const flagsmith = new Flagsmith({ + environmentKey: 'ser...', + cache: redisFlagsmithCache, }); ``` @@ -2037,7 +2024,7 @@ https://github.com/Flagsmith/flagsmith-java-client https://github.com/Flagsmith/flagsmith-dotnet-client - + https://github.com/Flagsmith/flagsmith-nodejs-client diff --git a/docs/plugins/flagsmith-versions/index.js b/docs/plugins/flagsmith-versions/index.js index b68835d55499..2c43dcb16d07 100644 --- a/docs/plugins/flagsmith-versions/index.js +++ b/docs/plugins/flagsmith-versions/index.js @@ -69,9 +69,10 @@ export default async function fetchFlagsmithVersions(context, options) { return { name: 'flagsmith-versions', async loadContent() { - const [js, java, android, swiftpm, cocoapods, dotnet, rust, elixir] = await Promise.all( + const [js, nodejs, java, android, swiftpm, cocoapods, dotnet, rust, elixir] = await Promise.all( [ fetchNpmVersions('flagsmith'), + fetchNpmVersions('flagsmith-nodejs'), fetchJavaVersions(), fetchAndroidVersions(), fetchSwiftPMVersions(), @@ -83,6 +84,7 @@ export default async function fetchFlagsmithVersions(context, options) { ); return { js, + nodejs, java, android, swiftpm, diff --git a/docs/src/components/SdkVersions.js b/docs/src/components/SdkVersions.js index 47c96bf871d7..e0426a1d0695 100644 --- a/docs/src/components/SdkVersions.js +++ b/docs/src/components/SdkVersions.js @@ -27,3 +27,4 @@ export const DotnetVersion = ({ spec = '~5' }) => Version({ sdk: 'dotnet', spec export const ElixirVersion = ({ spec = '~2' }) => Version({ sdk: 'elixir', spec }); export const RustVersion = ({ spec = '~2' }) => Version({ sdk: 'rust', spec }); export const JsVersion = ({ spec = '~7' }) => Version({ sdk: 'js', spec }); +export const NodejsVersion = ({ spec } = { spec: '~5' }) => Version({ sdk: 'nodejs', spec });