Skip to content

Commit 708f33e

Browse files
kyle-ssglukas-reiningtoddbaert
authored andcommitted
feat: Add Flagsmith Provider (open-feature#836)
Signed-off-by: kyle-ssg <kyle@solidstategroup.com> Signed-off-by: Kyle Johnson <kyle@solidstategroup.com> Co-authored-by: Lukas Reining <lukas.reining@codecentric.de> Co-authored-by: Todd Baert <todd.baert@dynatrace.com> Signed-off-by: Michael Samper <msamper@growthbook.io>
1 parent dd52d1c commit 708f33e

20 files changed

+1097
-2
lines changed

.release-please-manifest.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@
1111
"libs/shared/ofrep-core": "0.1.1",
1212
"libs/providers/ofrep": "0.1.1",
1313
"libs/providers/ofrep-web": "0.1.1",
14-
"libs/providers/flipt": "0.1.0"
14+
"libs/providers/flipt": "0.1.0",
15+
"libs/providers/flagsmith-client": "0.1.0"
1516
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"extends": ["../../../.eslintrc.json"],
3+
"ignorePatterns": ["!**/*","node_modules/**/*"],
4+
"overrides": [
5+
{
6+
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7+
"rules": {}
8+
},
9+
{
10+
"files": ["*.ts", "*.tsx"],
11+
"rules": {}
12+
},
13+
{
14+
"files": ["*.js", "*.jsx"],
15+
"rules": {}
16+
},
17+
{
18+
"files": ["*.json"],
19+
"parser": "jsonc-eslint-parser",
20+
"rules": {
21+
"@nx/dependency-checks": "error"
22+
}
23+
}
24+
]
25+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Flagsmith Provider
2+
3+
This provider is an implementation for the [JavaScript SDK](https://docs.flagsmith.com/clients/javascript/) of [Flagsmith](https://flagsmith.com).
4+
5+
## Installation
6+
7+
```
8+
npm install @openfeature/flagsmith-client-provider
9+
```
10+
11+
## Initialising the provider
12+
13+
The Flagsmith Provider can be created with the standard [initialization options](https://docs.flagsmith.com/clients/javascript/#example-initialising-the-sdk) and an optional Flagsmith instance to use.
14+
15+
```javascript
16+
import { FlagsmithClientProvider } from '@openfeature/flagsmith-client-provider';
17+
import { OpenFeature } from '@openfeature/web-sdk';
18+
19+
const flagsmithClientProvider = new FlagsmithClientProvider({
20+
environmentID: '<ENVIRONMENT_ID>'
21+
});
22+
OpenFeature.setProvider(flagsmithClientProvider); // Attach the provider to OpenFeature
23+
```
24+
25+
## Usage with React Native, SSR or custom instances
26+
27+
The Flagsmith Provider can be constructed with a custom Flagsmith instance and optional server-side generated state, [initialization options](https://docs.flagsmith.com/clients/javascript/#example-initialising-the-sdk).
28+
29+
Note: In order to use the React Native implementation of OpenFeature you will need to install both Flagsmith and react-native-flagsmith.
30+
31+
```javascript
32+
import flagsmith from 'react-native-flagsmith' // Could also be flagsmith/isomorphic, flagsmith-es or createFlagsmithInstance()
33+
import { FlagsmithClientProvider } from '@openfeature/flagsmith-client-provider';
34+
import { OpenFeature } from '@openfeature/web-sdk';
35+
36+
const flagsmithClientProvider = new FlagsmithClientProvider({
37+
environmentID: '<ENVIRONMENT_ID>',
38+
flagsmithInstance: flagsmith,
39+
state:serverState
40+
});
41+
OpenFeature.setProvider(flagsmithClientProvider); // Attach the provider to OpenFeature
42+
```
43+
44+
## Identifying and setting Traits
45+
46+
In Flagsmith, users are [identified](https://docs.flagsmith.com/clients/javascript/#identifying-users) in order to allow for segmentation and percentage rollouts.
47+
48+
To identify and set traits you can specify a targetingKey(identity) and optionally a set of traits. This will do the equivalent of ``flagsmith.identify(id, traits)`` or pass these to ``flagsmith.init`` if you are calling this before ``OpenFeature.setProvider``.
49+
50+
```javascript
51+
const flagsmithClientProvider = new FlagsmithClientProvider({
52+
environmentID: '<ENVIRONMENT_ID>',
53+
});
54+
await OpenFeature.setContext({ targetingKey, traits });
55+
OpenFeature.setProvider(flagsmithClientProvider); // Attach the provider to OpenFeature
56+
```
57+
58+
To reset the identity you can simply reset the context. This will do the equivalent of ``flagsmith.logout()``
59+
60+
```javascript
61+
await OpenFeature.setContext({ });
62+
```
63+
64+
## Resolution reasoning
65+
66+
In Flagsmith, features are evaluated based on the following [Resolution reasons](https://openfeature.dev/specification/types/#resolution-details):
67+
68+
```typescript
69+
StandardResolutionReasons.CACHED | StandardResolutionReasons.STATIC | StandardResolutionReasons.DEFAULT | StandardResolutionReasons.ERROR
70+
```
71+
72+
Note that resolutions of type SPLIT may be the result of targetted matching or percentage split however Flagsmith does not expose this information to client-side SDKs.
73+
74+
75+
## Events
76+
77+
The Flagsmith provider emits the
78+
following [OpenFeature events](https://openfeature.dev/specification/types#provider-events):
79+
80+
- PROVIDER_READY
81+
- PROVIDER_ERROR
82+
- PROVIDER_CONFIGURATION_CHANGED
83+
84+
## Building
85+
86+
Run `nx package providers-flagsmith` to build the library.
87+
88+
## Running unit tests
89+
90+
Run `nx test providers-flagsmith` to execute the unit tests via [Jest](https://jestjs.io).
91+
92+
## Examples
93+
94+
You can find examples using this provider in several frameworks [Here](https://github.com/Flagsmith/flagsmith-js-examples/tree/main/open-feature).
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"presets": [["minify", { "builtIns": false }]]
3+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/* eslint-disable */
2+
export default {
3+
displayName: 'providers-flagsmith-client',
4+
preset: '../../../jest.preset.js',
5+
transform: {
6+
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
7+
},
8+
moduleFileExtensions: ['ts', 'js', 'html']
9+
};

libs/providers/flagsmith-client/package-lock.json

Lines changed: 45 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "@openfeature/flagsmith-client-provider",
3+
"version": "0.0.1",
4+
"dependencies": {
5+
"tslib": "^2.3.0"
6+
},
7+
"main": "./src/index.js",
8+
"typings": "./src/index.d.ts",
9+
"scripts": {
10+
"publish-if-not-exists": "cp $NPM_CONFIG_USERCONFIG .npmrc && if [ \"$(npm show $npm_package_name@$npm_package_version version)\" = \"$(npm run current-version -s)\" ]; then echo 'already published, skipping'; else npm publish --access public; fi",
11+
"current-version": "echo $npm_package_version"
12+
},
13+
"peerDependencies": {
14+
"@openfeature/web-sdk": "^1.0.0",
15+
"flagsmith": "4.0.0"
16+
}
17+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{
2+
"name": "providers-flagsmith-client",
3+
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
4+
"sourceRoot": "libs/providers/flagsmith-client/src",
5+
"projectType": "library",
6+
"targets": {
7+
"publish": {
8+
"executor": "nx:run-commands",
9+
"options": {
10+
"command": "npm run publish-if-not-exists",
11+
"cwd": "dist/libs/providers/flagsmith"
12+
},
13+
"dependsOn": [
14+
{
15+
"projects": "self",
16+
"target": "package"
17+
}
18+
]
19+
},
20+
"lint": {
21+
"executor": "@nx/linter:eslint",
22+
"outputs": ["{options.outputFile}"],
23+
"options": {
24+
"lintFilePatterns": ["libs/providers/flagsmith-client/**/*.ts", "libs/providers/flagsmith-client/package.json"]
25+
}
26+
},
27+
"test": {
28+
"executor": "@nx/jest:jest",
29+
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
30+
"options": {
31+
"jestConfig": "libs/providers/flagsmith-client/jest.config.ts",
32+
"passWithNoTests": true
33+
},
34+
"configurations": {
35+
"ci": {
36+
"ci": true,
37+
"codeCoverage": true
38+
}
39+
}
40+
},
41+
"package": {
42+
"executor": "@nx/rollup:rollup",
43+
"outputs": ["{options.outputPath}"],
44+
"options": {
45+
"project": "libs/providers/flagsmith-client/package.json",
46+
"outputPath": "dist/libs/providers/flagsmith-client",
47+
"entryFile": "libs/providers/flagsmith-client/src/index.ts",
48+
"tsConfig": "libs/providers/flagsmith-client/tsconfig.lib.json",
49+
"buildableProjectDepsInPackageJsonType": "dependencies",
50+
"compiler": "tsc",
51+
"generateExportsField": true,
52+
"umdName": "flagsmith",
53+
"external": "all",
54+
"format": ["cjs", "esm"],
55+
"assets": [
56+
{
57+
"glob": "package.json",
58+
"input": "./assets",
59+
"output": "./src/"
60+
},
61+
{
62+
"glob": "LICENSE",
63+
"input": "./",
64+
"output": "./"
65+
},
66+
{
67+
"glob": "README.md",
68+
"input": "./libs/providers/flagsmith",
69+
"output": "./"
70+
}
71+
]
72+
}
73+
}
74+
},
75+
"tags": []
76+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './lib/flagsmith-client-provider';

0 commit comments

Comments
 (0)