Compare commits

..

No commits in common. "main" and "v0.13.1" have entirely different histories.

77 changed files with 8018 additions and 6900 deletions

View File

@ -28,9 +28,6 @@ FLAGSMITH_ENV_KEY=
# Harness SDK Key
HARNESS_KEY=
# ConfigCat SDK Key
CONFIGCAT_SDK_KEY=
###############################################
##
## Feature Flag SDK keys (web)
@ -62,7 +59,4 @@ FLAGD_PORT_WEB=
# Determines if TLS (https) should be used
# @default false
FLAGD_TLS_WEB=
# ConfigCat SDK Key
CONFIGCAT_SDK_KEY_WEB=
FLAGD_TLS_WEB=

View File

@ -14,15 +14,7 @@
"depConstraints": [
{
"sourceTag": "*",
"onlyDependOnLibsWithTags": [
"*"
]
},
{
"sourceTag": "shared",
"allowedExternalImports": [
"@openfeature/core"
]
"onlyDependOnLibsWithTags": ["*"]
}
]
}

View File

@ -7,28 +7,20 @@ on:
pull_request:
branches:
- 'main'
merge_group:
jobs:
main:
runs-on: equinix-4cpu-16gb
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- uses: actions/checkout@v3
with:
# We need to fetch all branches and commits so that Nx affected has a base to compare against.
fetch-depth: 0
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4
- uses: nrwl/nx-set-shas@v4
- uses: actions/setup-node@v4
with:
node-version: 18
cache: 'npm'
# Mark your git directory as safe for self-hosted runners
# https://github.com/nrwl/nx-set-shas?tab=readme-ov-file#self-hosted-runners
- name: Set Directory as Safe
run: |
git config --add safe.directory "$GITHUB_WORKSPACE"
shell: bash
- uses: nrwl/nx-set-shas@e2e6dc8bce4b0387a05eb687735c39c41580b792 # v4
- run: npm ci
- run: npx nx affected --target=lint --parallel=3
- run: npx nx affected --target=build --parallel=3 --ci
- run: npx nx affected --target=test --parallel=3 --ci --code-coverage

View File

@ -1,15 +0,0 @@
# based on https://github.com/onnx/onnx/blob/main/.github/workflows/dco_merge_group.yml
name: DCO
on:
merge_group:
permissions: # set top-level default permissions as security best practice
contents: read # Check https://github.com/ossf/scorecard/blob/7ce8609469289d5f3b1bf5ee3122f42b4e3054fb/docs/checks.md#token-permissions
jobs:
DCO:
runs-on: ubuntu-latest
if: ${{ github.actor != 'dependabot[bot]' }}
steps:
- run: echo "dummy DCO workflow (it won't run any check actually) to trigger by merge_group in order to enable merge queue"

View File

@ -12,6 +12,6 @@ jobs:
name: Validate PR title
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@0723387faaf9b38adef4775cd42cfd5155ed6017 # v5
- uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -13,13 +13,12 @@ jobs:
runs-on: ubuntu-latest
# Release-please creates a PR that tracks all changes
steps:
- uses: google-github-actions/release-please-action@db8f2c60ee802b3748b512940dde88eabd7b7e01 # v3
- uses: google-github-actions/release-please-action@v3
id: release
with:
command: manifest
token: ${{secrets.RELEASE_PLEASE_ACTION_TOKEN}}
token: ${{secrets.GITHUB_TOKEN}}
default-branch: main
signoff: "OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>"
outputs:
release_created: ${{ steps.release.outputs.release_created }}
release_tag_name: ${{ steps.release.outputs.tag_name }}
@ -30,12 +29,12 @@ jobs:
if: ${{ needs.release-please.outputs.release_created }}
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
uses: actions/checkout@v3
with:
ref: ${{ needs.release-please.outputs.release_tag_name }}
- name: Log in to the Container registry
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
@ -43,30 +42,31 @@ jobs:
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@818d4b7b91585d195f67373fd9cb0332e31a7175 # v4
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
#- name: Set up QEMU
# uses: docker/setup-qemu-action@master
# with:
# platforms: all
# - name: Set up Docker Buildx
# id: buildx
# uses: docker/setup-buildx-action@master
- name: Get current date
id: date
run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
- name: Set up QEMU
uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3
with:
platforms: linux/amd64,linux/arm64
- name: Build App Container
uses: docker/build-push-action@0a97817b6ade9f46837855d676c4cca3a2471fc9 # v4
uses: docker/build-push-action@v4
with:
# builder: ${{ steps.buildx.outputs.name }}
context: .
file: ./packages/app/Dockerfile
# platforms: linux/amd64,linux/arm64
push: true
provenance: false
platforms: linux/amd64,linux/arm64
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}-app:latest
${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}-app:${{ needs.release-please.outputs.release_tag_name }}
@ -77,13 +77,13 @@ jobs:
DATE=${{ steps.date.outputs.date }}
- name: Build Fibonacci Service Container
uses: docker/build-push-action@0a97817b6ade9f46837855d676c4cca3a2471fc9 # v4
uses: docker/build-push-action@v4
with:
# builder: ${{ steps.buildx.outputs.name }}
context: .
file: ./packages/fibonacci-service/Dockerfile
# platforms: linux/amd64,linux/arm64
push: true
provenance: false
platforms: linux/amd64,linux/arm64
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}-fib-service:latest
${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}-fib-service:${{ needs.release-please.outputs.release_tag_name }}

2
.gitignore vendored
View File

@ -45,5 +45,3 @@ Thumbs.db
# yalc stuff
.yalc
yalc.lock
config/flipt/flipt.db

View File

@ -1,3 +1,3 @@
{
".": "0.16.0"
".": "0.13.1"
}

View File

@ -1,144 +1,5 @@
# Changelog
## [0.16.0](https://github.com/open-feature/playground/compare/v0.15.2...v0.16.0) (2024-05-22)
### 🐛 Bug Fixes
* **deps:** update dependency flagsmith-nodejs to v3.3.0 ([d4a4468](https://github.com/open-feature/playground/commit/d4a446886a908451afd3c2d415e2c45a0895b95c))
### ✨ New Features
* add Flipt to playground ([#293](https://github.com/open-feature/playground/issues/293)) ([ab99a8e](https://github.com/open-feature/playground/commit/ab99a8e5bc8e788c053bc675b8ff442696031d76))
## [0.15.2](https://github.com/open-feature/playground/compare/v0.15.1...v0.15.2) (2024-04-21)
### 🐛 Bug Fixes
* **deps:** update dependency @openfeature/flagd-web-provider to ^0.7.0 ([#288](https://github.com/open-feature/playground/issues/288)) ([b26b52d](https://github.com/open-feature/playground/commit/b26b52dbbb38eaa1d1ff2090d49da70cd4e1d93b))
* goff ofrep provider in UI ([#289](https://github.com/open-feature/playground/issues/289)) ([3ed5edd](https://github.com/open-feature/playground/commit/3ed5edd5bfd5cc164d5316463e4c6910120520e3))
## [0.15.1](https://github.com/open-feature/playground/compare/v0.15.0...v0.15.1) (2024-04-21)
### 🐛 Bug Fixes
* **deps:** update dependency @openfeature/flagd-provider to ^0.13.0 ([#286](https://github.com/open-feature/playground/issues/286)) ([7426774](https://github.com/open-feature/playground/commit/7426774c5f6ede5c96b1d0234a21e3819ece3ed6))
* **deps:** update dependency @openfeature/web-sdk to v1.0.3 ([73937f2](https://github.com/open-feature/playground/commit/73937f240044185487c948843c482c404cd0b55d))
* **deps:** update nest monorepo to v10.3.8 ([8c3869c](https://github.com/open-feature/playground/commit/8c3869c588624877150ccbb56aeb79fdf851a0ba))
* make goff url for web configurable ([#287](https://github.com/open-feature/playground/issues/287)) ([3ccc862](https://github.com/open-feature/playground/commit/3ccc8620996d747c95388338f03990eb906d2191))
### 🧹 Chore
* **deps:** update actions/checkout action to v4 ([86b10b4](https://github.com/open-feature/playground/commit/86b10b443d9944e1fef19f2da31f6962688b4eeb))
* **deps:** update dependency core-js to v3.37.0 ([13d8c58](https://github.com/open-feature/playground/commit/13d8c583ce4175cb0faa7144ac92f18447228784))
* **deps:** update dependency typescript to v5.4.5 ([017a037](https://github.com/open-feature/playground/commit/017a037c6a70224375ed03801412ba0ea175c53b))
* **deps:** update dependency webpack to v5.91.0 ([4f08be3](https://github.com/open-feature/playground/commit/4f08be3e8be365614dcd8f6407d4e68ac0c6d072))
* **deps:** update eslint ([12855bb](https://github.com/open-feature/playground/commit/12855bb495fc7d627fb78f7b6607c0918ac16e0f))
* **deps:** update ghcr.io/open-feature/flagd docker tag to v0.10.1 ([42b13ef](https://github.com/open-feature/playground/commit/42b13efcc60186bebdcd3a243cff6e57c1938e86))
* **deps:** update node.js to v20.12.2 ([492700d](https://github.com/open-feature/playground/commit/492700ddeebd46b3004bbc8e1b697adbed4323ca))
* **deps:** update nrwl monorepo to v17.3.2 ([5203862](https://github.com/open-feature/playground/commit/52038627f812ebcfed754f021b8eb5e565a8abf6))
* **deps:** update prom/prometheus docker tag to v2.51.2 ([a1d37dc](https://github.com/open-feature/playground/commit/a1d37dca618ee0630c2655eebd1e56637d13ae33))
* **deps:** update thomaspoignant/go-feature-flag docker tag to v1.26.0 ([854cf8a](https://github.com/open-feature/playground/commit/854cf8a7d882545014228b8617fe6dd80e44237d))
* **deps:** update types ([4e702be](https://github.com/open-feature/playground/commit/4e702be79513bf17505bb2f2b136510273c614c1))
## [0.15.0](https://github.com/open-feature/playground/compare/v0.14.0...v0.15.0) (2024-04-16)
### 🐛 Bug Fixes
* **deps:** update dependency express to v4.19.2 [security] ([4c41fb9](https://github.com/open-feature/playground/commit/4c41fb9614886e1f34f74265a2eca1e340c7ea01))
### ✨ New Features
* add OFREP and update dependencies ([#280](https://github.com/open-feature/playground/issues/280)) ([e25a169](https://github.com/open-feature/playground/commit/e25a169c3c87138d8e1def37cbf0f3ef88fa0f71))
### 🧹 Chore
* **deps:** update dependency @mui/material to v5.15.10 ([129402c](https://github.com/open-feature/playground/commit/129402c94fa6dad8f9e9939540feac0f8ca656df))
* **deps:** update dependency core-js to v3.35.1 ([0170cfd](https://github.com/open-feature/playground/commit/0170cfdc0579ed40dabf0de444a2eb9370e4aa50))
* **deps:** update dependency ts-jest to v29.1.2 ([7aa6dc6](https://github.com/open-feature/playground/commit/7aa6dc6de26c360971f0b3d6b68859fa5df780d5))
* **deps:** update eslint ([8a15364](https://github.com/open-feature/playground/commit/8a15364bd7107d347579e3b3014fd2ed906b9ea6))
* **deps:** update ghcr.io/open-feature/flagd docker tag to v0.8.1 ([be8778e](https://github.com/open-feature/playground/commit/be8778e929ef0198e1f93ed5ecd4f18fdc269a1d))
* **deps:** update ghcr.io/open-feature/flagd docker tag to v0.8.2 ([5c1c758](https://github.com/open-feature/playground/commit/5c1c758cdaa560ddd66e89f7d81db813fa003bb0))
* **deps:** update jaegertracing/all-in-one docker tag to v1.53.0 ([489edaa](https://github.com/open-feature/playground/commit/489edaabd6007b1dd0a3b05a19eefa2191e2fa2b))
* **deps:** update node.js to v20.11.0 ([1655635](https://github.com/open-feature/playground/commit/1655635fb5f023f832a8a3d1bfb8796927924df0))
* **deps:** update prom/prometheus docker tag to v2.49.1 ([5da9932](https://github.com/open-feature/playground/commit/5da9932b49d2c28183006897766952eec2a53589))
* **deps:** update thomaspoignant/go-feature-flag-relay-proxy docker tag to v1.21.0 ([cd44fb8](https://github.com/open-feature/playground/commit/cd44fb81a36f2ba40d6df52452481a46e4506b49))
* **deps:** update types ([86b797e](https://github.com/open-feature/playground/commit/86b797e1d85a5cc40b356003e9635c5e9e522f4a))
* **deps:** update types ([085de92](https://github.com/open-feature/playground/commit/085de92f125e3dd7049ee419194a9b05bbebd71d))
## [0.14.0](https://github.com/open-feature/playground/compare/v0.13.4...v0.14.0) (2024-01-22)
### 🐛 Bug Fixes
* **deps:** update dependency @harnessio/ff-javascript-client-sdk to v1.21.0 ([1ae889f](https://github.com/open-feature/playground/commit/1ae889fd124850177a7f578b753687961ddc911c))
* **deps:** update dependency @openfeature/open-telemetry-hooks to ^0.3.0 ([#264](https://github.com/open-feature/playground/issues/264)) ([10ec74b](https://github.com/open-feature/playground/commit/10ec74b98d9501061dec7857a2dd415387822101))
* **deps:** update dependency flagsmith-nodejs to v3 ([#226](https://github.com/open-feature/playground/issues/226)) ([ddaba6d](https://github.com/open-feature/playground/commit/ddaba6d5c6249a995314238889c95ac0e71cb4e3))
* **deps:** update dependency react-router-dom to v6.20.1 ([e233ccb](https://github.com/open-feature/playground/commit/e233ccb5943cf002ecba98a90f59c606f11f34a7))
* docker-compose.yaml image instead of build ([#274](https://github.com/open-feature/playground/issues/274)) ([2fc3ccb](https://github.com/open-feature/playground/commit/2fc3ccbe998d18c62fbf49ecac4529362233cffa))
### ✨ New Features
* client-side flags in e2e k8s demo ([#267](https://github.com/open-feature/playground/issues/267)) ([c782315](https://github.com/open-feature/playground/commit/c782315c6cc4a99554a6bf76413fde05e430681f))
* use Nest.js SDK in backend ([#273](https://github.com/open-feature/playground/issues/273)) ([d4b18d8](https://github.com/open-feature/playground/commit/d4b18d88afc38accc201329c2a5eb72e63b6f78c))
### 🧹 Chore
* **deps:** update dependency @emotion/react to v11.11.3 ([f44f35c](https://github.com/open-feature/playground/commit/f44f35c3f891c9c88f7108d22a26cdbc1acb58d7))
* **deps:** update dependency @mui/material to v5.14.20 ([8a0a90b](https://github.com/open-feature/playground/commit/8a0a90bbcb27e93d80a3d70d419f1634fa728800))
* **deps:** update dependency @mui/material to v5.15.6 ([919102d](https://github.com/open-feature/playground/commit/919102d1dd6da5b61a3fcf5360d0bcb2cd093650))
* **deps:** update dependency @types/node to v18.19.3 ([75da9ab](https://github.com/open-feature/playground/commit/75da9abd9c9168a2f2ed710add6c7304f5cb20d3))
* **deps:** update dependency core-js to v3.34.0 ([d6133d4](https://github.com/open-feature/playground/commit/d6133d440e603db039cbb63c8809137196951c3c))
* **deps:** update dependency ts-node to v10.9.2 ([fba8985](https://github.com/open-feature/playground/commit/fba89858dd4ae16d2ed6f6e8ada469706f857ebf))
* **deps:** update dependency typescript to v5.3.3 ([58e00be](https://github.com/open-feature/playground/commit/58e00bea46cbe74c458c6d80dc1f754be00fde92))
* **deps:** update eslint ([a32d0fd](https://github.com/open-feature/playground/commit/a32d0fd9deaaa5b880e12d7d652205c43827783a))
* **deps:** update ghcr.io/open-feature/flagd docker tag to v0.7.2 ([424fe2f](https://github.com/open-feature/playground/commit/424fe2f36fa831c0aec2fc8971fcc78181518151))
* **deps:** update jaegertracing/all-in-one docker tag to v1.52.0 ([aa2afbe](https://github.com/open-feature/playground/commit/aa2afbe0a3424ed7be6bf108db34dec421156469))
* **deps:** update prom/prometheus docker tag to v2.48.1 ([1827862](https://github.com/open-feature/playground/commit/1827862ea61f0f07ce968f1fd13ee9efe7f17698))
* **deps:** update types ([721b4e8](https://github.com/open-feature/playground/commit/721b4e8fcc2a601e43fb9ba32894330366cbdada))
* various dep updates ([#271](https://github.com/open-feature/playground/issues/271)) ([9764184](https://github.com/open-feature/playground/commit/9764184ef0afd62e9ee2235b73c941b585a69ad5))
## [0.13.4](https://github.com/open-feature/playground/compare/v0.13.3...v0.13.4) (2023-12-01)
### 🐛 Bug Fixes
* fix docker metadat for arm image ([#265](https://github.com/open-feature/playground/issues/265)) ([1c40f4e](https://github.com/open-feature/playground/commit/1c40f4e8ca966a9914f98bc290e23c98de36726d))
## [0.13.3](https://github.com/open-feature/playground/compare/v0.13.2...v0.13.3) (2023-12-01)
### 🧹 Chore
* **deps:** update node.js to v20.10 ([bc94bcc](https://github.com/open-feature/playground/commit/bc94bcc037198a7bac5883971c47cc5b0636da2b))
* **deps:** update prom/prometheus docker tag to v2.48.0 ([e27584c](https://github.com/open-feature/playground/commit/e27584c09da9605df9e9c9ef5d1e28b920b48b6d))
* **deps:** update thomaspoignant/go-feature-flag-relay-proxy docker tag to v1.19.0 ([0358b4f](https://github.com/open-feature/playground/commit/0358b4ff1f7a9544d5e02283c2c7a68313fdac41))
* **deps:** update types ([22bb451](https://github.com/open-feature/playground/commit/22bb45182cec97e1a5add3556d4cb7a04c157723))
* support arm image ([#261](https://github.com/open-feature/playground/issues/261)) ([b895a4c](https://github.com/open-feature/playground/commit/b895a4cc1e7fb0ef675f9fabc137cca28af7cfec))
## [0.13.2](https://github.com/open-feature/playground/compare/v0.13.1...v0.13.2) (2023-11-30)
### 🐛 Bug Fixes
* fix dependencies ([#260](https://github.com/open-feature/playground/issues/260)) ([6606d14](https://github.com/open-feature/playground/commit/6606d1434e2dcce50036820674c8018dd9c43758))
### 🧹 Chore
* **deps:** update ghcr.io/open-feature/flagd docker tag to v0.7.1 ([ce9ea0e](https://github.com/open-feature/playground/commit/ce9ea0e8203d9e08fe25383aae88975d21c22193))
* **deps:** update jaegertracing/all-in-one docker tag to v1.51.0 ([60134dc](https://github.com/open-feature/playground/commit/60134dc9bbb635e119bdfe1ed9a9072d911d8238))
* migrate from js-sdk to server-sdk ([#258](https://github.com/open-feature/playground/issues/258)) ([b537c90](https://github.com/open-feature/playground/commit/b537c902aca495302672967b637db0181c08b3e4))
## [0.13.1](https://github.com/open-feature/playground/compare/v0.13.0...v0.13.1) (2023-11-30)

View File

@ -28,8 +28,6 @@ If you're brand new to feature flagging, consider reviewing the [What are featur
- [Harness](#harness)
- [LaunchDarkly](#launchdarkly)
- [Flagsmith](#flagsmith)
- [Flipt](#flipt)
- [ConfigCat](#configcat)
- [Experimenting beyond the demo](#experimenting-beyond-the-demo)
- [Evaluation context](#evaluation-context)
- [Troubleshooting](#troubleshooting)
@ -422,45 +420,6 @@ Now that everything is configured, you should be able to [start the demo](#how-t
Now that everything is configured, you should be able to [start the demo](#how-to-run-the-demo). Once it's started, select `flagsmith` from the provider list located at the bottom right of your screen. You should now be able to control the demo app via Flagsmith!
</details>
### Flipt
[Flipt](https://www.flipt.io/) is an open-source feature management platform that's fully self-hosted.
It's easy to set up, has no seat limits, and is built for developers from scale-ups to enterprises.
After [starting the demo](#how-to-run-the-demo), the Flipt UI is available at [http://localhost:8080](http://localhost:8080).
### ConfigCat
[ConfigCat](https://configcat.com/) is a user-friendly, scalable and secure feature flagging solution with clear [pricing](https://configcat.com/#pricing). ConfigCat allows for unlimited team members and MAUs across all plans, including the free tier. All ConfigCat plans come with all security measures, including audit logs, two-factor authentication, SSO, SAML and SCIM for secure feature management. ConfigCat offers users the choice to keep data within the EU to comply with GDPR more easily. ConfigCat provides SDKs for all major programming languages and platforms.
<details>
<summary>Follow these steps to set up ConfigCat for the demo:</summary>
1. Sign in to your ConfigCat account. If you don't already have an account, you can [sign up](https://app.configcat.com/auth/signup) for free.
1. Create a new feature flag with the key `new-welcome-message`.
<img src="./images/configcat/new-welcome-message.png">
1. Create a new text setting with the key `hex-color`. Add three percentage options (`+ %` button) with the following values: `c05543`, `2f5230`, and `0d507b`. Set `c05543` to 100%. Set the `To unindentified` value to `c05543`.
<img src="./images/configcat/hex-color.png">
1. Create a new text setting with the key `fib-algo`.
- Add a targeting rule (`+ IF` button) that looks for the `Email` user attribute to end with `@faas.com` and serves `binet`.
- Add five percentage options (`+ %` button) with the following values: `recursive`, `memo`, `loop`, `binet`, and `default`. Set `recursive` to 100%.
- Set the `To unindentified` value to `default`.
<img src="./images/configcat/fib-algo.png">
1. Click on `VIEW SDK KEY` and copy the `SDK Key`.
<img src="./images/configcat/sdk-key.png">
1. Open the `.env` file and set the values of `CONFIGCAT_SDK_KEY` and `CONFIGCAT_SDK_KEY_WEB` to the key copied above.
Now that everything is configured, you should be able to [start the demo](#how-to-run-the-demo). Once it's started, select `configcat` from the provider list located at the bottom right of your screen. You should now be able to control the demo app via ConfigCat!
</details>
## Experimenting beyond the demo
### Evaluation context

View File

@ -1,79 +0,0 @@
version: "1.2"
namespace: default
flags:
- key: new-welcome-message
name: new-welcome-message
type: BOOLEAN_FLAG_TYPE
description: Controls the welcome banner message
enabled: true
rollouts:
- threshold:
percentage: 100
value: true
- key: hex-color
name: hex-color
type: VARIANT_FLAG_TYPE
description: Controls the UI color
enabled: true
variants:
- key: c05543
name: red
- key: 2f5230
name: green
- key: 0d507b
name: blue
- key: d4ac0d
name: yellow
rules:
- segment: Signed-In-Users
distributions:
- variant: d4ac0d
rollout: 100
- segment: All-Users
distributions:
- variant: 2f5230
rollout: 100
- key: use-remote-fib-service
name: use-remote-fib-service
type: BOOLEAN_FLAG_TYPE
description: Controls whether the remote fib service is used
enabled: true
rollouts:
- segment:
key: Signed-In-Users
value: true
- segment:
key: All-Users
- key: fib-algo
name: fib-algo
type: VARIANT_FLAG_TYPE
description: The algorithm to calculate the fibbonaci sequence
enabled: true
variants:
- key: binet
name: binet
- key: memo
name: memo
- key: loop
name: loop
- key: recursive
name: recursive
rules:
- segment: All-Users
distributions:
- variant: memo
rollout: 100
segments:
- key: All-Users
name: All Users
description: All users are matched
match_type: ALL_MATCH_TYPE
- key: Signed-In-Users
name: Signed In Users
description: Users that are signed in
constraints:
- type: STRING_COMPARISON_TYPE
property: email
operator: suffix
value: '@faas.com'
match_type: ALL_MATCH_TYPE

View File

@ -22,15 +22,6 @@ hex-color:
default: 2f5230
percentage: 100
# Controls whether the remote fib service is used
# - true
# - false
use-remote-fib-service:
true: true
false: false
default: true
percentage: 100
# Must be a valid algorithm name
# - recurive
# - memo

View File

@ -1,131 +0,0 @@
# Flags for our UI
apiVersion: core.openfeature.dev/v1beta1
kind: FeatureFlag
metadata:
name: ui-flags
labels:
app: open-feature-demo
spec:
flagSpec:
flags:
new-welcome-message:
state: ENABLED
variants:
'on': true
'off': false
defaultVariant: 'off'
hex-color:
variants:
red: c05543
green: 2f5230
blue: 0d507b
yellow: d4ac0d
defaultVariant: blue
state: ENABLED
targeting:
if:
- in:
- '@faas.com'
- var:
- email
- yellow
- null
---
# Feature flag source custom resource, configuring flagd to source flags from FeatureFlag CRDs
apiVersion: core.openfeature.dev/v1beta1
kind: FeatureFlagSource
metadata:
name: ui-flag-source
labels:
app: open-feature-demo
spec:
sources:
- source: ui-flags
provider: kubernetes
---
# Standalone flagd for serving UI
apiVersion: core.openfeature.dev/v1beta1
kind: Flagd
metadata:
name: flagd-ui
spec:
replicas: 1
serviceAccountName: default
featureFlagSource: ui-flag-source
ingress:
enabled: true
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: 'false'
hosts:
- localhost
- ''
ingressClassName: nginx
pathType: Prefix
---
# Deployment of a demo-app using our custom resources
apiVersion: apps/v1
kind: Deployment
metadata:
name: open-feature-demo-deployment
labels:
app: open-feature-demo
spec:
replicas: 1
selector:
matchLabels:
app: open-feature-demo
template:
metadata:
labels:
app: open-feature-demo
annotations:
openfeature.dev/enabled: 'true'
openfeature.dev/inprocessconfiguration: 'in-process-config'
spec:
containers:
- name: open-feature-demo
image: ghcr.io/open-feature/playground-app:v0.16.0 # x-release-please-version
ports:
- containerPort: 30000
args:
- flagd
env:
- name: FLAGD_PORT_WEB
value: '80'
- name: FLAGD_OFREP_PORT_WEB
value: '80'
---
# Service to expose our application
apiVersion: v1
kind: Service
metadata:
name: open-feature-demo-app-service
labels:
app: open-feature-demo
spec:
type: NodePort
selector:
app: open-feature-demo
ports:
- port: 30000
targetPort: 30000
nodePort: 30000
---
# Ingress for our application
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: open-feature-demo-ingress
spec:
ingressClassName: nginx
rules:
- host: localhost
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: open-feature-demo-app-service
port:
number: 30000

View File

@ -1,8 +1,8 @@
# Flags for our UI
# A basic flag custom resource
apiVersion: core.openfeature.dev/v1beta1
kind: FeatureFlag
metadata:
name: ui-flags
name: end-to-end
labels:
app: open-feature-demo
spec:
@ -25,22 +25,11 @@ spec:
targeting:
if:
- in:
- '@faas.com'
- var:
- email
- "@faas.com"
- var:
- email
- yellow
- null
---
# Flags for our backend application
apiVersion: core.openfeature.dev/v1beta1
kind: FeatureFlag
metadata:
name: app-flags
labels:
app: open-feature-demo
spec:
flagSpec:
flags:
fib-algo:
variants:
recursive: recursive
@ -52,9 +41,9 @@ spec:
targeting:
if:
- in:
- '@faas.com'
- var:
- email
- "@faas.com"
- var:
- email
- binet
- null
use-remote-fib-service:
@ -64,22 +53,20 @@ spec:
'off': false
defaultVariant: 'off'
---
# Feature flag source custom resource, configuring flagd to source flags from FeatureFlag CRDs
# Feature flag source custom resource, configuring flagd to source flags from FeatureFlag crd
apiVersion: core.openfeature.dev/v1beta1
kind: FeatureFlagSource
metadata:
name: flag-sources
name: end-to-end
labels:
app: open-feature-demo
spec:
sources:
- source: app-flags
provider: kubernetes
- source: ui-flags
- source: end-to-end
provider: kubernetes
---
# Deployment of a demo-app using our custom resources
# Deployment of a demo-app using our custom resource
apiVersion: apps/v1
kind: Deployment
metadata:
@ -96,25 +83,23 @@ spec:
labels:
app: open-feature-demo
annotations:
openfeature.dev/enabled: 'true'
openfeature.dev/featureflagsource: 'flag-sources'
openfeature.dev/enabled: "true"
openfeature.dev/featureflagsource: "end-to-end"
spec:
containers:
- name: open-feature-demo
image: ghcr.io/open-feature/playground-app:v0.16.0 # x-release-please-version
image: ghcr.io/open-feature/playground-app:v0.13.1 # x-release-please-version
args:
- flagd
ports:
- containerPort: 30000
env:
- name: FLAGD_PORT_WEB
value: '30002'
---
# Service to expose our application
# Service exposed using NodePort
apiVersion: v1
kind: Service
metadata:
name: open-feature-demo-app-service
name: open-feature-demo-service
labels:
app: open-feature-demo
spec:
@ -122,23 +107,7 @@ spec:
selector:
app: open-feature-demo
ports:
# By default and for convenience, the `targetPort` is set to the same value as the `port` field.
- port: 30000
targetPort: 30000
nodePort: 30000
---
# Service to expose flagd for client-side evaluations
# Note that in production, it's recommended to run a dedicated flagd deployment to serve client-side evaluations.
apiVersion: v1
kind: Service
metadata:
name: open-feature-demo-ui-service
labels:
app: open-feature-demo
spec:
type: NodePort
selector:
app: open-feature-demo
ports:
- port: 30002
targetPort: 8013
nodePort: 30002

View File

@ -1,125 +0,0 @@
# Flags for our backend application
apiVersion: core.openfeature.dev/v1beta1
kind: FeatureFlag
metadata:
name: app-flags
labels:
app: open-feature-demo
spec:
flagSpec:
flags:
fib-algo:
variants:
recursive: recursive
memo: memo
loop: loop
binet: binet
defaultVariant: recursive
state: ENABLED
use-remote-fib-service:
state: ENABLED
variants:
'on': true
'off': false
defaultVariant: 'off'
---
# Feature flag source custom resource, configuring flagd to source flags from FeatureFlag CRDs
apiVersion: core.openfeature.dev/v1beta1
kind: FeatureFlagSource
metadata:
name: app-flag-source
labels:
app: open-feature-demo
spec:
sources:
- source: app-flags
provider: kubernetes
---
# Standalone flagd for serving in-process provider
apiVersion: core.openfeature.dev/v1beta1
kind: Flagd
metadata:
name: flagd-in-process
spec:
replicas: 1
serviceType: ClusterIP
serviceAccountName: default
featureFlagSource: app-flag-source
---
# In-process provider configuration
apiVersion: core.openfeature.dev/v1beta1
kind: InProcessConfiguration
metadata:
name: in-process-config
spec:
host: flagd-in-process
---
# Deployment of a demo-app using our custom resources
apiVersion: apps/v1
kind: Deployment
metadata:
name: open-feature-demo-deployment
labels:
app: open-feature-demo
spec:
replicas: 1
selector:
matchLabels:
app: open-feature-demo
template:
metadata:
labels:
app: open-feature-demo
annotations:
openfeature.dev/enabled: 'true'
openfeature.dev/inprocessconfiguration: 'in-process-config'
spec:
containers:
- name: open-feature-demo
image: ghcr.io/open-feature/playground-app:v0.16.0 # x-release-please-version
ports:
- containerPort: 30000
args:
- flagd
env:
- name: FLAGD_PORT_WEB
value: '80'
- name: FLAGD_PATH_PREFIX
value: 'flagd'
- name: FLAGD_OFREP_PORT_WEB
value: '80'
---
# Service to expose our application
apiVersion: v1
kind: Service
metadata:
name: open-feature-demo-app-service
labels:
app: open-feature-demo
spec:
type: NodePort
selector:
app: open-feature-demo
ports:
- port: 30000
targetPort: 30000
nodePort: 30000
---
# Ingress for our application
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: open-feature-demo-ingress
spec:
ingressClassName: nginx
rules:
- host: localhost
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: open-feature-demo-app-service
port:
number: 30000

View File

@ -1,7 +1,7 @@
version: '3.8'
services:
demo:
image: ghcr.io/open-feature/playground-app:v0.16.0 # x-release-please-version
image: ghcr.io/open-feature/playground-app:v0.13.1 # x-release-please-version
# build:
# dockerfile: ./packages/app/Dockerfile
# context: .
@ -21,10 +21,7 @@ services:
- OTEL_EXPORTER_JAEGER_AGENT_HOST=jaeger
- OTEL_EXPORTER_JAEGER_AGENT_PORT=6832
- GO_FEATURE_FLAG_URL=http://go-feature-flag:1031
- GO_FEATURE_FLAG_WEB_URL=http://localhost:1031
- FIB_SERVICE_URL=http://fib-service:30001
- FLIPT_URL=http://flipt:8080
- FLIPT_WEB_URL=http://localhost:8080
- FIB_SERVICE_USER
- FIB_SERVICE_PASS
# Provider values come from the .env
@ -38,7 +35,6 @@ services:
- LD_KEY
- FLAGSMITH_ENV_KEY
- CLOUDBEES_APP_KEY
- CONFIGCAT_SDK_KEY
## Web
- HARNESS_KEY_WEB
- SPLIT_KEY_WEB
@ -47,11 +43,10 @@ services:
- CLOUDBEES_APP_KEY_WEB
- FLAGD_HOST_WEB
- FLAGD_PORT_WEB
- FLAGD_TLS_WEB
- CONFIGCAT_SDK_KEY_WEB
- FLAGD_TLS_WEB
fib-service:
image: ghcr.io/open-feature/playground-fib-service:v0.16.0 # x-release-please-version
image: ghcr.io/open-feature/playground-fib-service:v0.13.1 # x-release-please-version
# build:
# dockerfile: ./packages/fibonacci-service/Dockerfile
# context: .
@ -62,8 +57,6 @@ services:
- OTEL_EXPORTER_JAEGER_AGENT_HOST=jaeger
- OTEL_EXPORTER_JAEGER_AGENT_PORT=6832
- OTEL_SERVICE_NAME=fibonacci-service
- GO_FEATURE_FLAG_URL=http://go-feature-flag:1031
- FLIPT_URL=http://flipt:8080
- FIB_SERVICE_USER
- FIB_SERVICE_PASS
# Provider values come from the .env
@ -76,10 +69,9 @@ services:
- LD_KEY
- FLAGSMITH_ENV_KEY
- CLOUDBEES_APP_KEY
- CONFIGCAT_SDK_KEY
jaeger:
image: jaegertracing/all-in-one:1.60
image: jaegertracing/all-in-one:1.49.0
expose:
- '6832/udp'
- '4317'
@ -87,7 +79,7 @@ services:
- '16686:16686'
otel-collector:
image: otel/opentelemetry-collector-contrib:0.105.0
image: otel/opentelemetry-collector-contrib:0.85.0
restart: always
command: [ "--config=/etc/otel-collector-config.yaml" ]
volumes:
@ -103,7 +95,7 @@ services:
prometheus:
container_name: prometheus
image: prom/prometheus:v2.55.1
image: prom/prometheus:v2.47.2
restart: always
volumes:
- ./config/prometheus/prometheus.yaml:/etc/prometheus/prometheus.yml
@ -111,7 +103,7 @@ services:
- "9090:9090"
flagd:
image: ghcr.io/open-feature/flagd:v0.11.5
image: ghcr.io/open-feature/flagd:v0.6.8
command:
- start
- --cors-origin
@ -126,43 +118,13 @@ services:
- ./config/flagd/flags.json:/etc/flagd/flags.json
ports:
- '8013:8013'
- '8016:8016'
go-feature-flag:
image: thomaspoignant/go-feature-flag:v1.40.0
image: thomaspoignant/go-feature-flag-relay-proxy:v1.12.1
volumes:
- ./config/go-feature-flag:/goff/
ports:
- "1031:1031"
init_flipt:
image: docker.flipt.io/flipt/flipt:v1.53.2
command: ["./flipt", "import", "/var/opt/flipt/flipt.yml"]
environment:
FLIPT_LOG_LEVEL: debug
FLIPT_META_TELEMETRY_ENABLED: false
FLIPT_DB_URL: "/var/opt/flipt/flipt.db"
volumes:
- "./config/flipt/flipt.yml:/var/opt/flipt/flipt.yml"
- "flipt:/var/opt/flipt"
flipt:
image: docker.flipt.io/flipt/flipt:v1.53.2
command: ["./flipt", "--force-migrate"]
environment:
FLIPT_CORS_ENABLED: true
FLIPT_TRACING_ENABLED: true
FLIPT_TRACING_EXPORTER: otlp
FLIPT_TRACING_OTLP_ENDPOINT: "otel-collector:4317"
FLIPT_DB_URL: "/var/opt/flipt/flipt.db"
volumes:
- "./config/flipt/flipt.yml:/var/opt/flipt/flipt.yml"
- "flipt:/var/opt/flipt"
depends_on:
- init_flipt
ports:
- '8080:8080'
expose:
- 1031
volumes:
flagd-flags:
flipt:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

View File

@ -2,18 +2,87 @@
"migrations": [
{
"cli": "nx",
"version": "17.2.1-beta.0",
"description": "Add webpack.config.js file when webpackConfig is not defined",
"implementation": "./src/migrations/update-17-2-1/webpack-config-setup",
"package": "@nx/webpack",
"name": "update-17-2-1-webpack-config-setup"
"version": "16.7.0-beta.2",
"description": "Add @babel/core to package.json if @babel/preset-react is present",
"implementation": "./src/migrations/update-16-7-0/add-babel-core",
"package": "@nx/react",
"name": "add-babel-core"
},
{
"version": "17.2.0-beta.0",
"description": "Simplify eslintFilePatterns",
"implementation": "./src/migrations/update-17-2-0/simplify-eslint-patterns",
"cli": "nx",
"version": "16.7.0-beta.2",
"description": "Add @nx/react types to tsconfig types array",
"implementation": "./src/migrations/update-16-7-0-add-typings/update-16-7-0-add-typings",
"package": "@nx/react",
"name": "update-16-7-0-add-typings"
},
{
"cli": "nx",
"version": "16.5.0-beta.2",
"description": "Add test-setup.ts to ignored files in production input",
"implementation": "./src/migrations/update-16-5-0/add-test-setup-to-inputs-ignore",
"package": "@nx/jest",
"name": "add-test-setup-to-inputs-ignore"
},
{
"version": "17.1.0-beta.2",
"description": "Move jest executor options to nx.json targetDefaults",
"implementation": "./src/migrations/update-17-1-0/move-options-to-target-defaults",
"package": "@nx/jest",
"name": "move-options-to-target-defaults"
},
{
"cli": "nx",
"version": "16.6.0-beta.0",
"description": "Explicitly set 'updateBuildableProjectDepsInPackageJson' to 'true' in targets that rely on that value as the default.",
"factory": "./src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps",
"package": "@nx/js",
"name": "explicitly-set-projects-to-update-buildable-deps"
},
{
"cli": "nx",
"version": "16.8.2-beta.0",
"description": "Remove invalid options (strict, noInterop) for ES6 type modules.",
"factory": "./src/migrations/update-16-8-2/update-swcrc",
"package": "@nx/js",
"name": "16-8-2-update-swcrc"
},
{
"cli": "nx",
"version": "17.0.2",
"description": "Remove deprecated build options",
"implementation": "./src/migrations/update-17-0-0/remove-deprecated-build-options",
"package": "@nx/js",
"name": "update-17-0-0-remove-deprecated-build-options"
},
{
"cli": "nx",
"version": "16.9.0-beta.1",
"description": "Replace imports of Module Federation utils frm @nx/devkit to @nx/webpack",
"implementation": "./src/migrations/update-16-9-0/migrate-mf-util-usage",
"package": "@nx/devkit",
"name": "update-16-9-0-migrate-mf-usage-to-webpack"
},
{
"version": "16.8.0",
"description": "update-16-8-0-add-ignored-files",
"implementation": "./src/migrations/update-16-8-0-add-ignored-files/update-16-8-0-add-ignored-files",
"package": "@nx/linter",
"name": "simplify-eslint-patterns"
"name": "update-16-8-0-add-ignored-files"
},
{
"version": "17.0.0-beta.7",
"description": "update-17-0-0-rename-to-eslint",
"implementation": "./src/migrations/update-17-0-0-rename-to-eslint/update-17-0-0-rename-to-eslint",
"package": "@nx/linter",
"name": "update-17-0-0-rename-to-eslint"
},
{
"version": "17.1.0-beta.1",
"description": "Updates for @typescript-utils/utils v6.9.1+",
"implementation": "./src/migrations/update-17-1-0/update-typescript-eslint",
"package": "@nx/linter",
"name": "update-typescript-eslint"
}
]
}

13298
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,12 @@
{
"name": "openfeature",
"version": "0.16.0",
"version": "0.13.1",
"license": "Apache-2.0",
"scripts": {
"ui": "nx run ui:serve",
"app": "nx run app:serve",
"fib-service": "nx run fibonacci-service:serve",
"build": "nx run-many --all --target=build",
"temp": "nx build",
"build:app": "nx build app && nx build ui",
"build:fib-service": "nx build fibonacci-service",
"lint": "nx run-many --all --target=lint",
@ -16,137 +16,119 @@
},
"private": true,
"dependencies": {
"@harnessio/ff-javascript-client-sdk": "^1.21.0",
"@harnessio/ff-nodejs-server-sdk": "^1.4.0",
"@nestjs/axios": "^3.0.2",
"@nestjs/common": "10.4.15",
"@nestjs/core": "10.4.15",
"@nestjs/platform-express": "10.4.15",
"@nestjs/serve-static": "^4.0.2",
"@openfeature/config-cat-web-provider": "^0.1.3",
"@openfeature/config-cat-provider": "^0.7.2",
"@openfeature/env-var-provider": "^0.3.0",
"@openfeature/flagd-provider": "^0.13.0",
"@openfeature/flagd-web-provider": "^0.7.0",
"@openfeature/flipt-provider": "^0.1.0",
"@openfeature/flipt-web-provider": "^0.1.0",
"@openfeature/go-feature-flag-provider": "^0.7.0",
"@openfeature/go-feature-flag-web-provider": "^0.2.0",
"@openfeature/nestjs-sdk": "^0.1.3-experimental",
"@openfeature/ofrep-provider": "^0.1.3",
"@openfeature/ofrep-web-provider": "^0.1.3",
"@openfeature/open-telemetry-hooks": "^0.4.0",
"@openfeature/web-sdk": "1.0.3",
"@opentelemetry/api": "^1.8.0",
"@opentelemetry/auto-instrumentations-node": "^0.44.0",
"@opentelemetry/core": "^1.23.0",
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.50.0",
"@opentelemetry/exporter-trace-otlp-grpc": "^0.50.0",
"@opentelemetry/resources": "^1.23.0",
"@opentelemetry/sdk-metrics": "^1.23.0",
"@opentelemetry/sdk-node": "^0.50.0",
"@opentelemetry/semantic-conventions": "^1.23.0",
"@splitsoftware/openfeature-js-split-provider": "^1.0.7",
"@splitsoftware/splitio": "^10.24.1",
"@splitsoftware/splitio-browserjs": "^0.14.0",
"@types/rox-browser": "^5.0.7",
"@harnessio/ff-javascript-client-sdk": "^1.10.0",
"@harnessio/ff-nodejs-server-sdk": "^1.2.8",
"@nestjs/axios": "^2.0.0",
"@nestjs/common": "9.4.3",
"@nestjs/core": "9.4.3",
"@nestjs/platform-express": "9.4.3",
"@nestjs/serve-static": "^3.0.0",
"@openfeature/env-var-provider": "^0.1.1",
"@openfeature/flagd-provider": "^0.8.2",
"@openfeature/flagd-web-provider": "^0.4.0",
"@openfeature/go-feature-flag-provider": "^0.5.14",
"@openfeature/js-sdk": "^1.4.1",
"@openfeature/open-telemetry-hooks": "^0.2.3",
"@openfeature/web-sdk": "0.4.0",
"@opentelemetry/api": "~1.6.0",
"@opentelemetry/auto-instrumentations-node": "^0.39.2",
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.43.0",
"@opentelemetry/exporter-trace-otlp-grpc": "^0.43.0",
"@opentelemetry/sdk-metrics": "^1.15.1",
"@opentelemetry/sdk-node": "^0.43.0",
"@splitsoftware/openfeature-js-split-provider": "^1.0.5",
"@splitsoftware/splitio": "^10.22.3",
"@splitsoftware/splitio-browserjs": "^0.10.0",
"@types/rox-browser": "^5.0.2",
"change-case": "^4.1.2",
"class-validator": "^0.14.1",
"class-validator": "^0.14.0",
"cloudbees-openfeature-provider-node": "^1.0.0",
"clsx": "^1.2.1",
"eventemitter3": "^5.0.1",
"events": "^3.3.0",
"express": "4.21.2",
"express-validator": "^7.0.1",
"flagsmith": "^3.21.0",
"flagsmith-nodejs": "^3.2.0",
"launchdarkly-js-client-sdk": "^3.1.4",
"launchdarkly-node-server-sdk": "^7.0.3",
"nestjs-pino": "^4.0.0",
"pino-http": "^9.0.0",
"pino-pretty": "^11.0.0",
"react-router-dom": "^6.21.1",
"reflect-metadata": "^0.2.0",
"rox-browser": "^5.4.9",
"rox-node": "^5.4.9",
"express": "4.18.2",
"express-validator": "^7.0.0",
"flagsmith": "^3.14.2",
"flagsmith-nodejs": "^2.5.0",
"launchdarkly-js-client-sdk": "^3.0.0",
"launchdarkly-node-server-sdk": "^7.0.0",
"nestjs-pino": "^3.1.2",
"pino-http": "^8.3.1",
"pino-pretty": "^10.0.0",
"react-router-dom": "^6.11.2",
"reflect-metadata": "^0.1.13",
"rox-browser": "^5.4.2",
"rox-node": "^5.4.2",
"rxjs": "^7.8.0"
},
"devDependencies": {
"@babel/preset-react": "^7.23.3",
"@emotion/react": "11.14.0",
"@emotion/styled": "11.14.0",
"@mui/material": "^5.15.2",
"@nestjs/schematics": "10.2.3",
"@nestjs/testing": "10.4.15",
"@nrwl/tao": "17.3.2",
"@nx/devkit": "17.3.2",
"@nx/eslint-plugin": "17.3.2",
"@nx/express": "17.3.2",
"@nx/jest": "17.3.2",
"@nx/js": "17.3.2",
"@nx/linter": "17.3.2",
"@nx/nest": "17.3.2",
"@nx/node": "17.3.2",
"@nx/react": "17.3.2",
"@nx/web": "17.3.2",
"@nx/webpack": "17.3.2",
"@nx/workspace": "17.3.2",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.11",
"@reactour/tour": "^3.6.1",
"@svgr/webpack": "^8.1.0",
"@babel/preset-react": "^7.18.6",
"@emotion/react": "11.11.1",
"@emotion/styled": "11.11.0",
"@mui/material": "^5.11.3",
"@nestjs/schematics": "9.2.0",
"@nestjs/testing": "9.4.3",
"@nrwl/tao": "17.1.3",
"@nx/devkit": "17.1.3",
"@nx/eslint-plugin": "17.1.3",
"@nx/express": "17.1.3",
"@nx/jest": "17.1.3",
"@nx/js": "17.1.3",
"@nx/linter": "17.1.3",
"@nx/nest": "17.1.3",
"@nx/node": "17.1.3",
"@nx/react": "17.1.3",
"@nx/web": "17.1.3",
"@nx/webpack": "17.1.3",
"@nx/workspace": "17.1.3",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
"@reactour/tour": "^3.1.8",
"@svgr/webpack": "^8.0.0",
"@testing-library/react": "^12.1.5",
"@types/events": "^3.0.3",
"@types/events": "^3.0.0",
"@types/express": "4.17.21",
"@types/jest": "^29.5.11",
"@types/node": "18.19.68",
"@types/react": "18.3.18",
"@types/react-dom": "18.3.5",
"@types/react-json-editor-ajrm": "^2.5.6",
"@types/react-modal": "^3.16.3",
"@types/rox-node": "^5.0.5",
"@typescript-eslint/eslint-plugin": "6.21.0",
"@typescript-eslint/parser": "6.21.0",
"@types/jest": "^29.2.5",
"@types/node": "18.18.9",
"@types/react": "18.2.24",
"@types/react-dom": "18.2.9",
"@types/react-json-editor-ajrm": "^2.5.3",
"@types/react-modal": "^3.13.1",
"@types/rox-node": "^5.0.1",
"@typescript-eslint/eslint-plugin": "6.13.1",
"@typescript-eslint/parser": "6.13.1",
"ajv": "^8.12.0",
"babel-jest": "^29.7.0",
"core-js": "^3.35.0",
"css-loader": "^6.8.1",
"eslint": "8.57.1",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-import": "2.31.0",
"eslint-plugin-jsx-a11y": "6.10.2",
"eslint-plugin-react": "7.37.2",
"eslint-plugin-react-hooks": "4.6.2",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"json-schema-to-typescript": "^11.0.5",
"babel-jest": "^29.3.1",
"core-js": "^3.27.1",
"css-loader": "^6.7.3",
"eslint": "8.54.0",
"eslint-config-prettier": "9.0.0",
"eslint-plugin-import": "2.29.0",
"eslint-plugin-jsx-a11y": "6.8.0",
"eslint-plugin-react": "7.33.2",
"eslint-plugin-react-hooks": "4.6.0",
"jest": "^29.3.1",
"jest-environment-jsdom": "^29.3.1",
"json-schema-to-typescript": "^11.0.2",
"jsoneditor-react": "^3.1.2",
"markdown-toc": "^1.2.0",
"prettier": "2.8.8",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-json-editor-ajrm": "^2.5.14",
"react-json-editor-ajrm": "^2.5.13",
"react-json-view": "^1.21.3",
"react-modal": "^3.16.1",
"react-refresh": "^0.16.0",
"regenerator-runtime": "^0.14.0",
"style-loader": "^3.3.3",
"react-refresh": "^0.14.0",
"regenerator-runtime": "^0.13.11",
"style-loader": "^3.3.1",
"styled-components": "5.3.11",
"stylus": "^0.64.0",
"stylus-loader": "^7.1.3",
"ts-jest": "29.2.5",
"ts-node": "10.9.2",
"tslib": "^2.6.2",
"typescript": "5.7.2",
"stylus": "^0.59.0",
"stylus-loader": "^7.1.0",
"ts-jest": "29.1.1",
"ts-node": "10.9.1",
"tslib": "^2.4.1",
"typescript": "5.3.2",
"url-loader": "^4.1.1",
"webpack": "5.97.1",
"webpack-merge": "^5.10.0"
},
"overrides": {
"braces": ">=3.0.3",
"ws": ">=8.17.1",
"@grpc/grpc-js": ">=1.10.9",
"@openfeature/config-cat-provider": {
"@openfeature/server-sdk": "1.13.4"
}
"webpack": "5.89.0",
"webpack-merge": "^5.8.0"
}
}

View File

@ -1,4 +1,4 @@
FROM node:20.18-bullseye AS builder
FROM node:20.3-bullseye AS builder
WORKDIR /tmp/playground/
COPY package*.json tsconfig*.json nx.json babel.config.json ./
COPY schemas/ ./schemas/

View File

@ -13,8 +13,7 @@
"tsConfig": "packages/app/tsconfig.app.json",
"assets": ["packages/app/src/assets"],
"target": "node",
"compiler": "tsc",
"webpackConfig": "packages/app/webpack.config.js"
"compiler": "tsc"
},
"configurations": {
"production": {

View File

@ -1,18 +1,27 @@
import { HttpModule } from '@nestjs/axios';
import { ExecutionContext, Module } from '@nestjs/common';
import { ServeStaticModule } from '@nestjs/serve-static';
import { LoggingHook, OpenFeatureLogger } from '@openfeature/extra';
import { MetricsHook, TracingHook as SpanEventBasedTracingHook } from '@openfeature/open-telemetry-hooks';
import { ProviderService } from '@openfeature/provider';
import { Request } from 'express';
import { Agent } from 'http';
import { LoggerModule } from 'nestjs-pino';
import { join } from 'path';
import { FibonacciAsAServiceController } from './fibonacci-as-a-service.controller';
import { FibonacciService } from './fibonacci/fibonacci.service';
import { ProvidersController } from './providers.controller';
import { UtilsController } from './utils.controller';
import { EvaluationContext, FlagMetadata, OpenFeatureModule } from '@openfeature/nestjs-sdk';
import {HttpModule} from '@nestjs/axios';
import {MiddlewareConsumer, Module, NestModule, Scope} from '@nestjs/common';
import {REQUEST} from '@nestjs/core';
import {ServeStaticModule} from '@nestjs/serve-static';
import {AsyncLocalStorageTransactionContext, LoggingHook, OpenFeatureLogger} from '@openfeature/extra';
import {FlagMetadata, OpenFeature} from '@openfeature/js-sdk';
import {MetricsHook, TracingHook as SpanEventBasedTracingHook} from '@openfeature/open-telemetry-hooks';
import {ProviderService} from '@openfeature/provider';
import {Request} from 'express';
import {Agent} from 'http';
import {LoggerModule} from 'nestjs-pino';
import {join} from 'path';
import {OPENFEATURE_CLIENT, REQUEST_DATA} from './constants';
import {FibonacciAsAServiceController} from './fibonacci-as-a-service.controller';
import {FibonacciService} from './fibonacci/fibonacci.service';
import {ProvidersController} from './providers.controller';
import {TransactionContextMiddleware} from './transaction-context.middleware';
import {RequestData} from './types';
import {UtilsController} from './utils.controller';
/**
* Set a global logger for OpenFeature. This is logger will available in hooks.
*/
OpenFeature.setLogger(new OpenFeatureLogger('OpenFeature'));
function attributeMapper(flagMetadata: FlagMetadata) {
return {
@ -20,6 +29,22 @@ function attributeMapper(flagMetadata: FlagMetadata) {
};
}
/**
* Adding hooks to at the global level will ensure they always run
* as part of a flag evaluation lifecycle.
*/
OpenFeature.addHooks(
new LoggingHook(),
new SpanEventBasedTracingHook({attributeMapper}),
new MetricsHook({attributeMapper}));
/**
* The transaction context propagator is an experimental feature
* that allows evaluation context to be set anywhere in a request
* and have it automatically available during a flag evaluation.
*/
OpenFeature.setTransactionContextPropagator(new AsyncLocalStorageTransactionContext());
@Module({
imports: [
LoggerModule.forRoot({
@ -48,22 +73,24 @@ function attributeMapper(flagMetadata: FlagMetadata) {
HttpModule.register({
httpAgent: new Agent({ keepAlive: true }),
}),
OpenFeatureModule.forRoot({
// Set a global logger for OpenFeature. This is logger will available in hooks.
logger: new OpenFeatureLogger('OpenFeature'),
//Adding hooks to at the global level will ensure they always run as part of a flag evaluation lifecycle.
hooks: [
new LoggingHook(),
new SpanEventBasedTracingHook({ attributeMapper }),
new MetricsHook({ attributeMapper }),
],
// This context will be used for all flag evaluations in the callstack
contextFactory: async (context: ExecutionContext): Promise<EvaluationContext> => {
const req = await context.switchToHttp().getRequest<Request>();
],
controllers: [FibonacciAsAServiceController, UtilsController, ProvidersController],
providers: [
FibonacciService,
ProviderService,
{
provide: OPENFEATURE_CLIENT,
useFactory: () => {
const client = OpenFeature.getClient('app');
return client;
},
},
{
provide: REQUEST_DATA,
useFactory: (req: Request): RequestData => {
const authHeaderValue = req.header('Authorization') || 'anonymous';
const userAgent = req.header('user-agent');
return {
ts: new Date().getTime(),
ip: (req.headers['x-forwarded-for'] as string) || (req.socket.remoteAddress as string),
email: authHeaderValue,
method: req.method,
@ -72,9 +99,13 @@ function attributeMapper(flagMetadata: FlagMetadata) {
targetingKey: authHeaderValue,
};
},
}),
scope: Scope.REQUEST,
inject: [REQUEST],
},
],
controllers: [FibonacciAsAServiceController, UtilsController, ProvidersController],
providers: [FibonacciService, ProviderService],
})
export class AppModule {}
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(TransactionContextMiddleware).forRoutes(FibonacciAsAServiceController);
}
}

View File

@ -0,0 +1,2 @@
export const OPENFEATURE_CLIENT = Symbol.for('OPENFEATURE_CLIENT');
export const REQUEST_DATA = Symbol.for('REQUEST_DATA');

View File

@ -1,15 +1,15 @@
import {HttpService} from '@nestjs/axios';
import {Injectable} from '@nestjs/common';
import {fibonacci} from '@openfeature/fibonacci';
import {lastValueFrom, map} from 'rxjs';
import {Client, FeatureClient} from "@openfeature/nestjs-sdk";
import { HttpService } from '@nestjs/axios';
import { Inject, Injectable } from '@nestjs/common';
import { fibonacci } from '@openfeature/fibonacci';
import { Client } from '@openfeature/js-sdk';
import { OPENFEATURE_CLIENT } from '../constants';
import { lastValueFrom, map } from 'rxjs';
@Injectable()
export class FibonacciService {
private readonly FIB_SERVICE_URL = process.env.FIB_SERVICE_URL || 'http://localhost:30001';
constructor(private readonly httpService: HttpService, @FeatureClient() private client: Client) {
}
constructor(private readonly httpService: HttpService, @Inject(OPENFEATURE_CLIENT) private client: Client) {}
async calculateFibonacci(num: number): Promise<{ result: number }> {
const useRemoteFibService = await this.client.getBooleanValue('use-remote-fib-service', false);
@ -18,7 +18,7 @@ export class FibonacciService {
return lastValueFrom(
this.httpService
.get<{ result: number }>(`${this.FIB_SERVICE_URL}/calculate`, {
params: {num},
params: { num },
auth: {
username: process.env.FIB_SERVICE_USER || '',
password: process.env.FIB_SERVICE_PASS || '',

View File

@ -0,0 +1,19 @@
import { Injectable, NestMiddleware, Inject } from '@nestjs/common';
import { OpenFeature } from '@openfeature/js-sdk';
import { NextFunction, Request, Response } from 'express';
import { REQUEST_DATA } from './constants';
import { RequestData } from './types';
@Injectable()
export class TransactionContextMiddleware implements NestMiddleware {
constructor(@Inject(REQUEST_DATA) private requestData: RequestData) {}
/**
* Adds our request data to the OpenFeature context via the configured TransactionContextManager
*/
use(_req: Request, _res: Response, next: NextFunction) {
OpenFeature.setTransactionContext({ ts: new Date().getTime(), ...this.requestData }, () => {
next();
});
}
}

View File

@ -0,0 +1,13 @@
export type RequestData = {
targetingKey: string;
ip: string;
method: string;
path: string;
userAgent?: string;
email?: string;
};
export type InstallTemplateData = {
os: string;
installationInstruction: string;
};

View File

@ -1,8 +0,0 @@
const { composePlugins, withNx } = require('@nx/webpack');
// Nx plugins for webpack.
module.exports = composePlugins(withNx(), (config) => {
// Note: This was added by an Nx migration. Webpack builds are required to have a corresponding Webpack config file.
// See: https://nx.dev/recipes/webpack/webpack-config-setup
return config;
});

View File

@ -1,4 +1,4 @@
FROM node:20.18-bullseye-slim AS builder
FROM node:20.3-bullseye-slim AS builder
WORKDIR /tmp/playground/
COPY package*.json tsconfig*.json nx.json babel.config.json ./
RUN npm ci

View File

@ -12,8 +12,7 @@
"compiler": "tsc",
"outputPath": "dist/packages/fibonacci-service",
"main": "packages/fibonacci-service/src/main.ts",
"tsConfig": "packages/fibonacci-service/tsconfig.app.json",
"webpackConfig": "packages/fibonacci-service/webpack.config.js"
"tsConfig": "packages/fibonacci-service/tsconfig.app.json"
},
"configurations": {
"production": {

View File

@ -1,11 +1,17 @@
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { LoggerModule } from 'nestjs-pino';
import { LoggingHook, OpenFeatureLogger } from '@openfeature/extra';
import { MetricsHook, TracingHook as SpanEventBasedTracingHook } from '@openfeature/open-telemetry-hooks';
import { ProviderService } from '@openfeature/provider';
import { ProvidersController } from './providers.controller';
import { OpenFeatureModule, FlagMetadata } from '@openfeature/nestjs-sdk';
import {MiddlewareConsumer, Module, NestModule} from '@nestjs/common';
import {AppController} from './app.controller';
import {LoggerModule} from 'nestjs-pino';
import {FlagMetadata, OpenFeature} from '@openfeature/js-sdk';
import {AsyncLocalStorageTransactionContext, LoggingHook, OpenFeatureLogger} from '@openfeature/extra';
import {MetricsHook, TracingHook as SpanEventBasedTracingHook} from '@openfeature/open-telemetry-hooks';
import {TransactionContextMiddleware} from './transaction-context.middleware';
import {ProviderService} from '@openfeature/provider';
import {ProvidersController} from './providers.controller';
/**
* Set a global logger for OpenFeature. This is logger will available in hooks.
*/
OpenFeature.setLogger(new OpenFeatureLogger('OpenFeature'));
function attributeMapper(flagMetadata: FlagMetadata) {
return {
@ -13,6 +19,22 @@ function attributeMapper(flagMetadata: FlagMetadata) {
};
}
/**
* Adding hooks to at the global level will ensure they always run
* as part of a flag evaluation lifecycle.
*/
OpenFeature.addHooks(
new LoggingHook(),
new SpanEventBasedTracingHook({attributeMapper}),
new MetricsHook({ attributeMapper }));
/**
* The transaction context propagator is an experimental feature
* that allows evaluation context to be set anywhere in a request
* and have it automatically available during a flag evaluation.
*/
OpenFeature.setTransactionContextPropagator(new AsyncLocalStorageTransactionContext());
@Module({
imports: [
LoggerModule.forRoot({
@ -35,18 +57,12 @@ function attributeMapper(flagMetadata: FlagMetadata) {
: undefined,
},
}),
OpenFeatureModule.forRoot({
// Set a global logger for OpenFeature. This is logger will available in hooks.
logger: new OpenFeatureLogger('OpenFeature'),
//Adding hooks to at the global level will ensure they always run as part of a flag evaluation lifecycle.
hooks: [
new LoggingHook(),
new SpanEventBasedTracingHook({ attributeMapper }),
new MetricsHook({ attributeMapper }),
],
}),
],
controllers: [AppController, ProvidersController],
providers: [ProviderService],
})
export class AppModule {}
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(TransactionContextMiddleware).forRoutes(AppController);
}
}

View File

@ -0,0 +1,22 @@
import { Injectable, NestMiddleware } from '@nestjs/common';
import { EvaluationContext, OpenFeature } from '@openfeature/js-sdk';
import { NextFunction, Request, Response } from 'express';
import { propagation, context } from '@opentelemetry/api';
@Injectable()
export class TransactionContextMiddleware implements NestMiddleware {
/**
* Adds our request data to the OpenFeature context via the configured TransactionContextManager
*/
use(_req: Request, _res: Response, next: NextFunction) {
const baggage = propagation.getBaggage(context.active());
const currentBaggage = baggage?.getAllEntries();
const evaluationContext: EvaluationContext = {};
currentBaggage?.forEach(([key, value]) => {
evaluationContext[key] = value.value;
});
OpenFeature.setTransactionContext(evaluationContext, next);
}
}

View File

@ -1,8 +0,0 @@
const { composePlugins, withNx } = require('@nx/webpack');
// Nx plugins for webpack.
module.exports = composePlugins(withNx(), (config) => {
// Note: This was added by an Nx migration. Webpack builds are required to have a corresponding Webpack config file.
// See: https://nx.dev/recipes/webpack/webpack-config-setup
return config;
});

View File

@ -11,8 +11,7 @@
"main": "packages/fibonacci/src/index.ts",
"tsConfig": "packages/fibonacci/tsconfig.lib.json",
"target": "node",
"compiler": "tsc",
"webpackConfig": "packages/fibonacci/webpack.config.js"
"compiler": "tsc"
},
"configurations": {
"production": {

View File

@ -1,4 +1,4 @@
import { OpenFeature } from '@openfeature/nestjs-sdk';
import { OpenFeature } from '@openfeature/js-sdk';
const oFeatClient = OpenFeature.getClient('fibonacci');

View File

@ -1,8 +0,0 @@
const { composePlugins, withNx } = require('@nx/webpack');
// Nx plugins for webpack.
module.exports = composePlugins(withNx(), (config) => {
// Note: This was added by an Nx migration. Webpack builds are required to have a corresponding Webpack config file.
// See: https://nx.dev/recipes/webpack/webpack-config-setup
return config;
});

View File

@ -12,8 +12,7 @@
"main": "packages/js-flagsmith-provider/src/index.ts",
"tsConfig": "packages/js-flagsmith-provider/tsconfig.lib.json",
"target": "node",
"compiler": "tsc",
"webpackConfig": "packages/js-flagsmith-provider/webpack.config.js"
"compiler": "tsc"
},
"configurations": {
"production": {

View File

@ -1,14 +1,4 @@
import {
EvaluationContext,
EvaluationContextValue,
FlagNotFoundError,
JsonValue,
Logger,
ParseError,
Provider,
ResolutionDetails,
TypeMismatchError,
} from '@openfeature/server-sdk';
import { EvaluationContext, EvaluationContextValue, FlagNotFoundError, JsonValue, Logger, ParseError, Provider, ResolutionDetails, TypeMismatchError } from '@openfeature/js-sdk';
import { parseValidJsonObject } from '@openfeature/utils';
import Flagsmith from 'flagsmith-nodejs';

View File

@ -1,8 +0,0 @@
const { composePlugins, withNx } = require('@nx/webpack');
// Nx plugins for webpack.
module.exports = composePlugins(withNx(), (config) => {
// Note: This was added by an Nx migration. Webpack builds are required to have a corresponding Webpack config file.
// See: https://nx.dev/recipes/webpack/webpack-config-setup
return config;
});

View File

@ -11,8 +11,7 @@
"main": "packages/js-harness-provider/src/index.ts",
"tsConfig": "packages/js-harness-provider/tsconfig.lib.json",
"target": "node",
"compiler": "tsc",
"webpackConfig": "packages/js-harness-provider/webpack.config.js"
"compiler": "tsc"
}
},
"lint": {

View File

@ -1,5 +1,5 @@
import { Client, Target } from '@harnessio/ff-nodejs-server-sdk';
import { EvaluationContext, Provider, ResolutionDetails, JsonValue } from '@openfeature/server-sdk';
import { EvaluationContext, Provider, ResolutionDetails, JsonValue } from '@openfeature/js-sdk';
/**
* NOTE: This is an unofficial provider that was created for demonstration

View File

@ -1,8 +0,0 @@
const { composePlugins, withNx } = require('@nx/webpack');
// Nx plugins for webpack.
module.exports = composePlugins(withNx(), (config) => {
// Note: This was added by an Nx migration. Webpack builds are required to have a corresponding Webpack config file.
// See: https://nx.dev/recipes/webpack/webpack-config-setup
return config;
});

View File

@ -11,8 +11,7 @@
"main": "packages/js-launchdarkly-provider/src/index.ts",
"tsConfig": "packages/js-launchdarkly-provider/tsconfig.lib.json",
"target": "node",
"compiler": "tsc",
"webpackConfig": "packages/js-launchdarkly-provider/webpack.config.js"
"compiler": "tsc"
},
"configurations": {
"production": {

View File

@ -1,5 +1,5 @@
import { FlagValue, JsonValue, ParseError, TypeMismatchError } from '@openfeature/server-sdk';
import { EvaluationContext, Provider, ResolutionDetails, Logger } from '@openfeature/server-sdk';
import { FlagValue, JsonValue, ParseError, TypeMismatchError } from '@openfeature/js-sdk';
import { EvaluationContext, Provider, ResolutionDetails, Logger } from '@openfeature/js-sdk';
import { init, LDClient, LDUser } from 'launchdarkly-node-server-sdk';
export interface LaunchDarklyProviderOptions {

View File

@ -1,8 +0,0 @@
const { composePlugins, withNx } = require('@nx/webpack');
// Nx plugins for webpack.
module.exports = composePlugins(withNx(), (config) => {
// Note: This was added by an Nx migration. Webpack builds are required to have a corresponding Webpack config file.
// See: https://nx.dev/recipes/webpack/webpack-config-setup
return config;
});

View File

@ -11,8 +11,7 @@
"main": "packages/js-split-provider/src/index.ts",
"tsConfig": "packages/js-split-provider/tsconfig.lib.json",
"target": "node",
"compiler": "tsc",
"webpackConfig": "packages/js-split-provider/webpack.config.js"
"compiler": "tsc"
},
"configurations": {
"production": {

View File

@ -1,10 +1,10 @@
import { JsonValue, TypeMismatchError } from '@openfeature/server-sdk';
import { EvaluationContext, Provider, ResolutionDetails, Logger } from '@openfeature/server-sdk';
import { JsonValue, TypeMismatchError } from '@openfeature/js-sdk';
import { EvaluationContext, Provider, ResolutionDetails, Logger } from '@openfeature/js-sdk';
import type { Attributes, IClient } from '@splitsoftware/splitio/types/splitio';
import { parseValidNumber, parseValidJsonObject } from '@openfeature/utils';
/**
*
*
* NOTE: This is an unofficial provider that was created for demonstration
* purposes only. The playground environment will be updated to use official
* providers once they're available.

View File

@ -1,8 +0,0 @@
const { composePlugins, withNx } = require('@nx/webpack');
// Nx plugins for webpack.
module.exports = composePlugins(withNx(), (config) => {
// Note: This was added by an Nx migration. Webpack builds are required to have a corresponding Webpack config file.
// See: https://nx.dev/recipes/webpack/webpack-config-setup
return config;
});

View File

@ -11,8 +11,7 @@
"main": "packages/openfeature-extra/src/index.ts",
"tsConfig": "packages/openfeature-extra/tsconfig.lib.json",
"target": "node",
"compiler": "tsc",
"webpackConfig": "packages/openfeature-extra/webpack.config.js"
"compiler": "tsc"
},
"configurations": {
"production": {

View File

@ -1,2 +1,3 @@
export * from './lib/hooks';
export * from './lib/transaction-context';
export * from './lib/logger';

View File

@ -1,4 +1,4 @@
import { EvaluationDetails, Hook, HookContext, JsonObject } from '@openfeature/nestjs-sdk';
import { EvaluationDetails, Hook, HookContext, JsonObject } from '@openfeature/js-sdk';
import { validateSync } from 'class-validator';
/* eslint-disable @typescript-eslint/no-explicit-any */

View File

@ -1,4 +1,4 @@
import { EvaluationDetails, FlagValue, Hook, HookContext, HookHints } from '@openfeature/nestjs-sdk';
import { EvaluationDetails, FlagValue, Hook, HookContext, HookHints } from '@openfeature/js-sdk';
/**
* A hook that simply logs at every life-cycle stage.

View File

@ -1,4 +1,4 @@
import { Logger as OFLogger } from '@openfeature/nestjs-sdk';
import { Logger as OFLogger } from '@openfeature/js-sdk';
import { Logger } from '@nestjs/common';
/**

View File

@ -0,0 +1,13 @@
import { EvaluationContext, TransactionContextPropagator } from '@openfeature/js-sdk';
import { AsyncLocalStorage } from 'async_hooks';
export class AsyncLocalStorageTransactionContext implements TransactionContextPropagator {
private asyncLocalStorage = new AsyncLocalStorage<EvaluationContext>();
getTransactionContext(): EvaluationContext {
return this.asyncLocalStorage.getStore() ?? {};
}
setTransactionContext(context: EvaluationContext, callback: () => void): void {
this.asyncLocalStorage.run(context, callback);
}
}

View File

@ -0,0 +1 @@
export * from './async-local-storage';

View File

@ -1,8 +0,0 @@
const { composePlugins, withNx } = require('@nx/webpack');
// Nx plugins for webpack.
module.exports = composePlugins(withNx(), (config) => {
// Note: This was added by an Nx migration. Webpack builds are required to have a corresponding Webpack config file.
// See: https://nx.dev/recipes/webpack/webpack-config-setup
return config;
});

View File

@ -7,7 +7,7 @@ import {
BaggageEntry,
} from '@opentelemetry/api';
import { isTracingSuppressed } from '@opentelemetry/core';
import { OpenFeature, EvaluationContext } from '@openfeature/nestjs-sdk';
import { OpenFeature, EvaluationContext } from '@openfeature/js-sdk';
const KEY_PAIR_SEPARATOR = '=';
const PROPERTIES_SEPARATOR = ';';

View File

@ -4,7 +4,7 @@ import { GoFeatureFlagProvider } from '@openfeature/go-feature-flag-provider';
import { EnvVarProvider } from '@openfeature/env-var-provider';
import { FlagsmithProvider } from '@openfeature/js-flagsmith-provider';
import { OpenFeatureLaunchDarklyProvider } from '@openfeature/js-launchdarkly-provider';
import { OpenFeature, Provider } from '@openfeature/server-sdk';
import { OpenFeature, Provider } from '@openfeature/js-sdk';
import { OpenFeatureSplitProvider } from '@openfeature/js-split-provider';
import { SplitFactory } from '@splitsoftware/splitio';
import { CloudbeesProvider } from 'cloudbees-openfeature-provider-node';
@ -15,22 +15,14 @@ import { OpenFeatureLogger } from '@openfeature/extra';
import {
AvailableProvider,
CB_PROVIDER_ID,
CONFIGCAT_PROVIDER_ID,
ENV_PROVIDER_ID,
FLAGD_OFREP_PROVIDER_ID,
FLAGD_PROVIDER_ID,
FLAGSMITH_PROVIDER_ID,
FLIPT_PROVIDER_ID,
GO_OFREP_PROVIDER_ID,
GO_PROVIDER_ID,
HARNESS_PROVIDER_ID,
ProviderId,
SPLIT_PROVIDER_ID,
} from '@openfeature/utils';
import { OFREPProvider } from '@openfeature/ofrep-provider';
import { FliptProvider } from '@openfeature/flipt-provider';
import { ConfigCatProvider } from '@openfeature/config-cat-provider';
import { PollingMode } from 'configcat-node';
type ProviderMap = Record<
ProviderId,
@ -53,18 +45,6 @@ export class ProviderService {
port: Number.parseInt(process.env.FLAGD_PORT_WEB || '8013') || 8013,
tls: process.env.FLAGD_TLS_WEB === 'true',
},
[FLAGD_OFREP_PROVIDER_ID]: {
factory: () => {
const host = process.env.FLAGD_HOST ?? 'localhost';
const port = Number.parseInt(process.env.FLAGD_OFREP_PORT || '8016') || 8016;
const tls = process.env.FLAGD_OFREP_TLS === 'true';
const baseUrl = `${tls ? 'https' : 'http'}://${host}:${port}`;
return new OFREPProvider({ baseUrl });
},
host: process.env.FLAGD_HOST_WEB ?? 'localhost',
port: Number.parseInt(process.env.FLAGD_OFREP_PORT_WEB || '8016') || 8016,
tls: process.env.FLAGD_TLS_WEB === 'true',
},
launchdarkly: {
factory: () => {
const sdkKey = process.env.LD_KEY;
@ -119,14 +99,6 @@ export class ProviderService {
endpoint: process.env.GO_FEATURE_FLAG_URL as string,
}),
available: () => !!process.env.GO_FEATURE_FLAG_URL,
url: process.env.GO_FEATURE_FLAG_WEB_URL as string,
},
[GO_OFREP_PROVIDER_ID]: {
factory: () => {
return new OFREPProvider({ baseUrl: process.env.GO_FEATURE_FLAG_URL as string });
},
available: () => !!process.env.GO_FEATURE_FLAG_URL,
url: process.env.GO_FEATURE_FLAG_WEB_URL as string,
},
[FLAGSMITH_PROVIDER_ID]: {
factory: () => {
@ -167,25 +139,6 @@ export class ProviderService {
available: () => !!process.env.HARNESS_KEY && !!process.env.HARNESS_KEY_WEB,
webCredential: process.env.HARNESS_KEY_WEB,
},
[FLIPT_PROVIDER_ID]: {
factory: () => {
return new FliptProvider('default', { url: process.env.FLIPT_URL as string });
},
available: () => !!process.env.FLIPT_URL,
url: process.env.FLIPT_WEB_URL,
},
[CONFIGCAT_PROVIDER_ID]: {
factory: () => {
const sdkKey = process.env.CONFIGCAT_SDK_KEY;
if (!sdkKey) {
throw new Error('"CONFIGCAT_SDK_KEY" must be defined.');
} else {
return ConfigCatProvider.create(sdkKey, PollingMode.AutoPoll, { pollIntervalSeconds: 5 });
}
},
available: () => !!process.env.CONFIGCAT_SDK_KEY && !!process.env.CONFIGCAT_SDK_KEY_WEB,
webCredential: process.env.CONFIGCAT_SDK_KEY_WEB,
},
};
constructor() {
@ -230,7 +183,6 @@ export class ProviderService {
host: p[1].host,
port: p[1].port,
tls: p[1].tls,
url: p[1].url,
};
});
}

View File

@ -3,13 +3,8 @@ import { FlagdWebProvider } from '@openfeature/flagd-web-provider';
import {
AvailableProvider,
CB_PROVIDER_ID,
CONFIGCAT_PROVIDER_ID,
FLAGD_OFREP_PROVIDER_ID,
FLAGD_PROVIDER_ID,
FLAGSMITH_PROVIDER_ID,
FLIPT_PROVIDER_ID,
GO_OFREP_PROVIDER_ID,
GO_PROVIDER_ID,
HARNESS_PROVIDER_ID,
LD_PROVIDER_ID,
ProviderId,
@ -21,7 +16,6 @@ import { HarnessWebProvider } from '@openfeature/web-harness-provider';
import { LaunchDarklyProvider } from '@openfeature/web-launchdarkly-provider';
import { NOOP_PROVIDER, OpenFeature, Provider } from '@openfeature/web-sdk';
import { SplitWebProvider } from '@openfeature/web-split-provider';
import { OFREPWebProvider } from '@openfeature/ofrep-web-provider';
import { TourProvider } from '@reactour/tour';
import Ajv, { AnySchema, ErrorObject, ValidateFunction } from 'ajv';
import EventEmitter from 'eventemitter3';
@ -34,9 +28,6 @@ import { JsonEditor, JsonOutput } from './json-editor';
import { styledFib3rSteps } from './demos/fib3r/tour';
import { JSON_UPDATED } from './types';
import { getData } from './utils';
import { GoFeatureFlagWebProvider } from '@openfeature/go-feature-flag-web-provider';
import { FliptWebProvider } from '@openfeature/flipt-web-provider';
import { ConfigCatWebProvider } from '@openfeature/config-cat-web-provider';
type ProviderMap = Record<
string,
@ -82,30 +73,6 @@ export class Demos extends Component<
);
},
},
[FLAGD_OFREP_PROVIDER_ID]: {
factory: () => {
const ofrepConfig = this.state.availableProviders.find((p) => p.id === FLAGD_OFREP_PROVIDER_ID);
const tls = ofrepConfig?.tls ?? false;
const host = ofrepConfig?.host ?? 'localhost';
const port = ofrepConfig?.port ?? 8016;
const baseUrl = `${tls ? 'https' : 'http'}://${host}:${port}`;
return new OFREPWebProvider({ baseUrl, pollInterval: 1000 }, console);
},
},
[GO_PROVIDER_ID]: {
factory: () => {
const ofrepConfig = this.state.availableProviders.find((p) => p.id === GO_PROVIDER_ID);
const endpoint = ofrepConfig?.url ?? 'http://localhost:1031';
return new GoFeatureFlagWebProvider({ endpoint }, console);
},
},
[GO_OFREP_PROVIDER_ID]: {
factory: () => {
const ofrepConfig = this.state.availableProviders.find((p) => p.id === GO_OFREP_PROVIDER_ID);
const baseUrl = ofrepConfig?.url ?? 'http://localhost:1031';
return new OFREPWebProvider({ baseUrl, pollInterval: 1000 }, console);
},
},
[HARNESS_PROVIDER_ID]: {
factory: () => {
return new HarnessWebProvider(this.getProviderCredential(HARNESS_PROVIDER_ID), console);
@ -134,20 +101,11 @@ export class Demos extends Component<
return new SplitWebProvider(this.getProviderCredential(SPLIT_PROVIDER_ID));
},
},
[FLIPT_PROVIDER_ID]: {
factory: () => {
const fliptConfig = this.state.availableProviders.find((p) => p.id === FLIPT_PROVIDER_ID);
return new FliptWebProvider('default', { url: fliptConfig?.url });
},
},
[CONFIGCAT_PROVIDER_ID]: {
factory: () => {
return ConfigCatWebProvider.create(this.getProviderCredential(CONFIGCAT_PROVIDER_ID), { pollIntervalSeconds: 5 });
},
},
};
constructor(props: Record<string, never>) {
constructor(
props: Record<string, never>
) {
super(props);
this.state = {
json: {},

View File

@ -30,5 +30,5 @@
}
}
},
"tags": ["shared"]
"tags": []
}

View File

@ -1,4 +1,5 @@
export * from './lib/parse-valid-boolean';
export * from './lib/parse-valid-json-object';
export * from './lib/parse-valid-number';
export * from './lib/errors';
export * from './lib/types';

View File

@ -0,0 +1,7 @@
export enum ErrorCode {
PROVIDER_NOT_READY = 'PROVIDER_NOT_READY',
FLAG_NOT_FOUND = 'FLAG_NOT_FOUND',
PARSE_ERROR = 'PARSE_ERROR',
TYPE_MISMATCH = 'TYPE_MISMATCH',
GENERAL = 'GENERAL',
}

View File

@ -0,0 +1,5 @@
import { ErrorCode } from './codes';
export abstract class OpenFeatureError extends Error {
abstract code: ErrorCode;
}

View File

@ -0,0 +1,11 @@
import { ErrorCode } from './codes';
import { OpenFeatureError } from './error.abstract';
export class FlagNotFoundError extends OpenFeatureError {
code: ErrorCode;
constructor(message?: string) {
super(message);
Object.setPrototypeOf(this, FlagNotFoundError.prototype);
this.code = ErrorCode.FLAG_NOT_FOUND;
}
}

View File

@ -0,0 +1,11 @@
import { ErrorCode } from './codes';
import { OpenFeatureError } from './error.abstract';
export class GeneralError extends OpenFeatureError {
code: ErrorCode;
constructor(message?: string) {
super(message);
Object.setPrototypeOf(this, GeneralError.prototype);
this.code = ErrorCode.GENERAL;
}
}

View File

@ -0,0 +1,5 @@
export * from './codes';
export * from './flag-not-found';
export * from './general';
export * from './parse';
export * from './type-mismatch';

View File

@ -0,0 +1,11 @@
import { ErrorCode } from './codes';
import { OpenFeatureError } from './error.abstract';
export class ParseError extends OpenFeatureError {
code: ErrorCode;
constructor(message?: string) {
super(message);
Object.setPrototypeOf(this, ParseError.prototype);
this.code = ErrorCode.PARSE_ERROR;
}
}

View File

@ -0,0 +1,11 @@
import { ErrorCode } from './codes';
import { OpenFeatureError } from './error.abstract';
export class TypeMismatchError extends OpenFeatureError {
code: ErrorCode;
constructor(message?: string) {
super(message);
Object.setPrototypeOf(this, TypeMismatchError.prototype);
this.code = ErrorCode.TYPE_MISMATCH;
}
}

View File

@ -1,4 +1,4 @@
import { TypeMismatchError } from '@openfeature/core';
import { TypeMismatchError } from '@openfeature/js-sdk';
export const parseValidBoolean = (stringValue: string | undefined) => {
const asUnknown = stringValue as unknown;

View File

@ -1,4 +1,4 @@
import { JsonValue, ParseError, TypeMismatchError } from '@openfeature/core';
import { JsonValue, ParseError, TypeMismatchError } from '@openfeature/js-sdk';
export const parseValidJsonObject = <T extends JsonValue>(stringValue: string): T => {
if (stringValue === undefined) {

View File

@ -1,4 +1,4 @@
import { ParseError, TypeMismatchError } from '@openfeature/core';
import { ParseError, TypeMismatchError } from '@openfeature/js-sdk';
export const parseValidNumber = (stringValue: string | undefined) => {
if (stringValue === undefined) {

View File

@ -1,34 +1,25 @@
export const ENV_PROVIDER_ID = 'env';
export const FLAGD_OFREP_PROVIDER_ID = 'flagd-ofrep';
export const FLAGD_PROVIDER_ID = 'flagd';
export const GO_PROVIDER_ID = 'go-feature-flag';
export const GO_OFREP_PROVIDER_ID = 'go-feature-flag-ofrep';
export const LD_PROVIDER_ID = 'launchdarkly';
export const SPLIT_PROVIDER_ID = 'split';
export const CB_PROVIDER_ID = 'cloudbees';
export const FLAGSMITH_PROVIDER_ID = 'flagsmith';
export const HARNESS_PROVIDER_ID = 'harness';
export const FLIPT_PROVIDER_ID = 'flipt';
export const CONFIGCAT_PROVIDER_ID = 'configcat';
export type ProviderId =
| typeof ENV_PROVIDER_ID
| typeof FLAGD_PROVIDER_ID
| typeof FLAGD_OFREP_PROVIDER_ID
| typeof GO_PROVIDER_ID
| typeof GO_OFREP_PROVIDER_ID
| typeof LD_PROVIDER_ID
| typeof SPLIT_PROVIDER_ID
| typeof CB_PROVIDER_ID
| typeof FLAGSMITH_PROVIDER_ID
| typeof HARNESS_PROVIDER_ID
| typeof FLIPT_PROVIDER_ID
| typeof CONFIGCAT_PROVIDER_ID;
| typeof HARNESS_PROVIDER_ID;
export interface AvailableProvider {
id: ProviderId;
webCredential?: string;
url?: string;
host?: string;
tls?: boolean;
port?: number;

View File

@ -1,18 +1,19 @@
import {parseValidJsonObject, parseValidNumber} from '@openfeature/utils';
import { parseValidJsonObject, parseValidNumber } from '@openfeature/utils';
import {
EvaluationContext,
OpenFeatureEventEmitter,
FlagValue,
Hook,
JsonValue,
Logger,
OpenFeatureEventEmitter,
Provider,
ProviderEvents,
ProviderMetadata,
ProviderStatus,
ResolutionDetails,
TypeMismatchError,
ProviderStatus,
} from '@openfeature/web-sdk';
import {SplitFactory} from '@splitsoftware/splitio-browserjs';
import { SplitFactory } from '@splitsoftware/splitio-browserjs';
const ANONYMOUS = 'anonymous';
@ -57,7 +58,7 @@ export class SplitWebProvider implements Provider {
name: 'Split web provider',
};
hooks?: Hook[] | undefined;
hooks?: Hook<FlagValue>[] | undefined;
async onContextChange?(oldContext: EvaluationContext, newContext: EvaluationContext): Promise<void> {
if (oldContext.targetingKey !== newContext.targetingKey) {

View File

@ -1,8 +1,15 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"description": "Default preset for use with OpenFeature's repos",
"extends": [ "github>open-feature/community-tooling" ],
"extends": ["config:recommended"],
"semanticCommits": "enabled",
"automergeType": "branch",
"configMigration": true,
"dependencyDashboard": true,
"prCreation": "not-pending",
"rebaseWhen": "behind-base-branch",
"platformAutomerge": true,
"platformCommit": true,
"npm": {
"packageRules": [
{
@ -13,10 +20,6 @@
"matchPackagePatterns": ["@opentelemtry/"],
"groupName": "OpenTelemetry"
},
{
"matchPackagePatterns": ["@openfeature/"],
"groupName": "OpenFeature"
},
{
"matchPackagePatterns": ["@typescript-eslint", "eslint"],
"groupName": "ESLint"
@ -36,4 +39,16 @@
}
]
},
"packageRules": [
{
"description": "Automerge non-major updates",
"matchUpdateTypes": ["minor", "patch"],
"matchCurrentVersion": "!/^0/",
"automerge": true
},
{
"matchManagers": ["github-actions"],
"automerge": true
}
]
}