Skip to content

Commit bd83124

Browse files
feat: flagd-web provider (open-feature#142)
Signed-off-by: James-Milligan <[email protected]> Co-authored-by: Todd Baert <[email protected]> Signed-off-by: James-Milligan <[email protected]> Co-authored-by: James-Milligan <[email protected]>
1 parent 78dd3ea commit bd83124

37 files changed

+2115
-121
lines changed

.github/workflows/ci.yml

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ jobs:
1212
- uses: actions/checkout@v3
1313
with:
1414
fetch-depth: 0
15+
submodules: recursive
16+
1517
- uses: bufbuild/[email protected]
1618
with:
1719
version: '1.1.1'

.github/workflows/release-please.yml

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ jobs:
2020
- name: Checkout Repository
2121
if: ${{ steps.release.outputs.releases_created }}
2222
uses: actions/checkout@v3
23+
with:
24+
fetch-depth: 0
25+
submodules: recursive
26+
2327
- uses: bufbuild/[email protected]
2428
with:
2529
version: "1.1.1"

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,8 @@ Thumbs.db
4040

4141
# generated files
4242
proto
43+
44+
45+
# yalc stuff
46+
.yalc
47+
yalc.lock

.gitmodules

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
[submodule "libs/providers/flagd/schemas"]
22
path = libs/providers/flagd/schemas
3-
url = https://github.com/open-feature/schemas
3+
url = https://github.com/open-feature/schemas.git
4+
[submodule "libs/providers/flagd-web/schemas"]
5+
path = libs/providers/flagd-web/schemas
6+
url = https://github.com/open-feature/schemas.git

.prettierrc

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
{
2+
"printWidth": 120,
23
"singleQuote": true
34
}

.release-please-manifest.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"libs/hooks/open-telemetry": "5.0.0",
33
"libs/providers/go-feature-flag": "0.5.0",
4-
"libs/providers/flagd": "0.7.0"
4+
"libs/providers/flagd": "0.7.0",
5+
"libs/providers/flagd-web": "0.1.0"
56
}
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"presets": ["minify"]
2+
"presets": [["minify", { "builtIns": false }]]
33
}

libs/providers/flagd-web/.babelrc

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"presets": [
3+
[
4+
"@nrwl/web/babel",
5+
{
6+
"useBuiltIns": "usage"
7+
}
8+
]
9+
]
10+
}
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"extends": ["../../../.eslintrc.json"],
3+
"ignorePatterns": ["!**/*"],
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+
}

libs/providers/flagd-web/README.md

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# flagd-web Provider for OpenFeature
2+
3+
![Experimental](https://img.shields.io/badge/experimental-breaking%20changes%20allowed-yellow)
4+
5+
A feature flag daemon with a Unix philosophy.
6+
7+
## Installation
8+
9+
:warning: This provider requires an experimental version of the JS-SDK:
10+
11+
```
12+
npm i @openfeature/js-sdk@1.0.99-experimental-55bf085fbdec8a76753b02b3efee8bec3eac53c0
13+
```
14+
15+
```sh
16+
npm install @openfeature/flagd-web-provider
17+
```
18+
19+
## Usage
20+
21+
The `FlagdWebProvider` communicates with flagd via the [connect protocol](https://buf.build/blog/connect-a-better-grpc).
22+
23+
### Reconnection
24+
25+
If the connection to the flagd instance fails, the provider will attempt to reconnect with an exponential back-off. The `maxDelay` and `maxRetries` can be specified to customize reconnect behavior.
26+
27+
### Event streaming
28+
29+
The `FlagdWebProvider` can be configured to receive events for flag changes. Combined with the event API in the JS SDK, this allows for subscription to flag value changes in clients.
30+
31+
### Caching
32+
33+
The `FlagdWebProvider` will cache resolve flag values based on the associated flag-key and context. Values are cached in localstorage. A TTL for cached values can be specified. If [event-streaming](#event-streaming) is enabled, the cache will be invalidated intelligently when flag configuration change events are received.
34+
35+
### Available options
36+
37+
| Option name | Type | Default | Description |
38+
| -------------- | ------- | --------- | ------------------------------------------------------------------------------------------------------------------ |
39+
| host | string | localhost | sets the host used to connect to the flagd instance |
40+
| port | number | 8013 | sets the port used to connect to the flagd instance |
41+
| tls | boolean | false | when set to true the provider will attempt to connect to flagd via https |
42+
| maxRetries | number | 0 | sets the maximum number of retries for a connection to be made to the flagd instance, a value of 0 means unlimited |
43+
| maxDelay | number | 60000 | sets the maximum time in ms to wait between reconnect intervals |
44+
| caching | boolean | true | when set to true the provider will use client side caching |
45+
| cacheTtl | number | 300 | sets the timeout in ms for items in the cache, a value of 0 disables the ttl |
46+
| eventStreaming | boolean | true | enables or disables streaming and event features. |
47+
48+
## Example
49+
50+
```typescript
51+
OpenFeature.setProvider(
52+
new FlagdWebProvider({
53+
host: 'localhost',
54+
port: 8013,
55+
tls: true,
56+
maxRetries: 10,
57+
maxDelay: 30000,
58+
cache: true,
59+
cacheTTL: 60000,
60+
})
61+
);
62+
```
63+
64+
## Building
65+
66+
Run `npx nx package providers-flagd-web` to build the library.
67+
68+
> NOTE: [Buf](https://docs.buf.build/installation) must be installed to build locally.
69+
70+
## Running unit tests
71+
72+
Run `npx nx test providers-flagd-web` to execute the unit tests via [Jest](https://jestjs.io).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"presets": [["minify", { "builtIns": false }]]
3+
}
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/* eslint-disable */
2+
export default {
3+
displayName: 'providers-flagd-web',
4+
preset: '../../../jest.preset.js',
5+
globals: {
6+
'ts-jest': {
7+
tsconfig: '<rootDir>/tsconfig.spec.json',
8+
},
9+
},
10+
transform: {
11+
'^.+\\.[tj]s$': 'ts-jest',
12+
},
13+
testEnvironment: 'jsdom',
14+
moduleFileExtensions: ['ts', 'js', 'html'],
15+
coverageDirectory: '../../../coverage/libs/providers/flagd-web',
16+
};

libs/providers/flagd-web/package-lock.json

+12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libs/providers/flagd-web/package.json

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "@openfeature/flagd-web-provider",
3+
"version": "0.1.0",
4+
"type": "commonjs",
5+
"scripts": {
6+
"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",
7+
"current-version": "echo $npm_package_version"
8+
},
9+
"peerDependencies": {
10+
"@openfeature/js-sdk": "1.1.0-experimental-9d746fab8c970534ef33d8da3fa80a5e44601b1e"
11+
}
12+
}

libs/providers/flagd-web/project.json

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
{
2+
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
3+
"sourceRoot": "libs/providers/flagd-web/src",
4+
"projectType": "library",
5+
"targets": {
6+
"publish": {
7+
"executor": "@nrwl/workspace:run-commands",
8+
"options": {
9+
"command": "npm run publish-if-not-exists",
10+
"cwd": "dist/libs/providers/flagd-web"
11+
},
12+
"dependsOn": [
13+
{
14+
"projects": "self",
15+
"target": "package"
16+
}
17+
]
18+
},
19+
"lint": {
20+
"executor": "@nrwl/linter:eslint",
21+
"outputs": ["{options.outputFile}"],
22+
"options": {
23+
"lintFilePatterns": ["libs/providers/flagd-web/**/*.ts"]
24+
},
25+
"dependsOn": [
26+
{
27+
"projects": "self",
28+
"target": "generate"
29+
}
30+
]
31+
},
32+
"test": {
33+
"executor": "@nrwl/jest:jest",
34+
"outputs": ["coverage/libs/providers/flagd-web"],
35+
"options": {
36+
"jestConfig": "libs/providers/flagd-web/jest.config.ts",
37+
"passWithNoTests": true
38+
},
39+
"dependsOn": [
40+
{
41+
"projects": "self",
42+
"target": "generate"
43+
}
44+
]
45+
},
46+
"generate": {
47+
"executor": "@nrwl/workspace:run-commands",
48+
"options": {
49+
"commands": [
50+
"git submodule update --init --recursive",
51+
"rm -f -r ./src/proto",
52+
"cd schemas && buf generate buf.build/open-feature/flagd --template protobuf/buf.gen.ts-connect.yaml",
53+
"mv -v ./proto ./src"
54+
],
55+
"cwd": "libs/providers/flagd-web",
56+
"parallel": false
57+
}
58+
},
59+
"package": {
60+
"executor": "@nrwl/web:rollup",
61+
"outputs": ["{options.outputPath}"],
62+
"options": {
63+
"buildableProjectDepsInPackageJsonType": "dependencies",
64+
"project": "libs/providers/flagd-web/package.json",
65+
"outputPath": "dist/libs/providers/flagd-web",
66+
"entryFile": "libs/providers/flagd-web/src/index.ts",
67+
"tsConfig": "libs/providers/flagd-web/tsconfig.lib.json",
68+
"compiler": "babel",
69+
"umdName": "flagd-web",
70+
"external": ["typescript"],
71+
"format": ["cjs", "esm"],
72+
"assets": [
73+
{
74+
"glob": "LICENSE",
75+
"input": "./",
76+
"output": "./"
77+
},
78+
{
79+
"glob": "README.md",
80+
"input": "./libs/providers/flagd-web",
81+
"output": "./"
82+
}
83+
]
84+
},
85+
"dependsOn": [
86+
{
87+
"projects": "self",
88+
"target": "generate"
89+
}
90+
]
91+
}
92+
},
93+
"tags": []
94+
}

libs/providers/flagd-web/schemas

Submodule schemas added at d638ecf

libs/providers/flagd-web/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './lib/flagd-web-provider';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { EvaluationContext, FlagValue, ResolutionDetails } from '@openfeature/js-sdk';
2+
3+
export interface FlagdCache {
4+
/**
5+
* Sets the evaluation details indexed by the specified key and context
6+
*
7+
* @param key
8+
* @param context
9+
* @param obj
10+
*/
11+
set<T extends FlagValue>(key: string, context: EvaluationContext, obj: ResolutionDetails<T>): Promise<void>;
12+
13+
/**
14+
* Gets the object indexed by the specified key and context
15+
*
16+
* @param key
17+
* @param context
18+
*/
19+
get<T extends FlagValue>(key: string, context: EvaluationContext): Promise<ResolutionDetails<T> | void>;
20+
21+
/**
22+
* Deletes the evaluation details indexed by the specified key and context
23+
*
24+
* @param key
25+
* @param context
26+
*/
27+
del(key: string, context: EvaluationContext): Promise<void>;
28+
29+
/**
30+
* Flushes all records for the specified key. If no key is specified, all records are flushed.
31+
* @param flagKey
32+
*/
33+
flush(flagKey?: string): Promise<void>;
34+
}

0 commit comments

Comments
 (0)