Compare commits
No commits in common. "main" and "v0.13.1" have entirely different histories.
|
@ -28,9 +28,6 @@ FLAGSMITH_ENV_KEY=
|
||||||
# Harness SDK Key
|
# Harness SDK Key
|
||||||
HARNESS_KEY=
|
HARNESS_KEY=
|
||||||
|
|
||||||
# ConfigCat SDK Key
|
|
||||||
CONFIGCAT_SDK_KEY=
|
|
||||||
|
|
||||||
###############################################
|
###############################################
|
||||||
##
|
##
|
||||||
## Feature Flag SDK keys (web)
|
## Feature Flag SDK keys (web)
|
||||||
|
@ -62,7 +59,4 @@ FLAGD_PORT_WEB=
|
||||||
|
|
||||||
# Determines if TLS (https) should be used
|
# Determines if TLS (https) should be used
|
||||||
# @default false
|
# @default false
|
||||||
FLAGD_TLS_WEB=
|
FLAGD_TLS_WEB=
|
||||||
|
|
||||||
# ConfigCat SDK Key
|
|
||||||
CONFIGCAT_SDK_KEY_WEB=
|
|
|
@ -14,15 +14,7 @@
|
||||||
"depConstraints": [
|
"depConstraints": [
|
||||||
{
|
{
|
||||||
"sourceTag": "*",
|
"sourceTag": "*",
|
||||||
"onlyDependOnLibsWithTags": [
|
"onlyDependOnLibsWithTags": ["*"]
|
||||||
"*"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceTag": "shared",
|
|
||||||
"allowedExternalImports": [
|
|
||||||
"@openfeature/core"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,28 +7,20 @@ on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- 'main'
|
- 'main'
|
||||||
merge_group:
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
main:
|
main:
|
||||||
runs-on: equinix-4cpu-16gb
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
# We need to fetch all branches and commits so that Nx affected has a base to compare against.
|
# We need to fetch all branches and commits so that Nx affected has a base to compare against.
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4
|
- uses: nrwl/nx-set-shas@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
cache: 'npm'
|
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: npm ci
|
||||||
- run: npx nx affected --target=lint --parallel=3
|
- 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
|
- run: npx nx affected --target=test --parallel=3 --ci --code-coverage
|
||||||
|
|
|
@ -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"
|
|
|
@ -12,6 +12,6 @@ jobs:
|
||||||
name: Validate PR title
|
name: Validate PR title
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: amannn/action-semantic-pull-request@0723387faaf9b38adef4775cd42cfd5155ed6017 # v5
|
- uses: amannn/action-semantic-pull-request@v5
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
|
@ -13,13 +13,12 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
# Release-please creates a PR that tracks all changes
|
# Release-please creates a PR that tracks all changes
|
||||||
steps:
|
steps:
|
||||||
- uses: google-github-actions/release-please-action@db8f2c60ee802b3748b512940dde88eabd7b7e01 # v3
|
- uses: google-github-actions/release-please-action@v3
|
||||||
id: release
|
id: release
|
||||||
with:
|
with:
|
||||||
command: manifest
|
command: manifest
|
||||||
token: ${{secrets.RELEASE_PLEASE_ACTION_TOKEN}}
|
token: ${{secrets.GITHUB_TOKEN}}
|
||||||
default-branch: main
|
default-branch: main
|
||||||
signoff: "OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>"
|
|
||||||
outputs:
|
outputs:
|
||||||
release_created: ${{ steps.release.outputs.release_created }}
|
release_created: ${{ steps.release.outputs.release_created }}
|
||||||
release_tag_name: ${{ steps.release.outputs.tag_name }}
|
release_tag_name: ${{ steps.release.outputs.tag_name }}
|
||||||
|
@ -30,12 +29,12 @@ jobs:
|
||||||
if: ${{ needs.release-please.outputs.release_created }}
|
if: ${{ needs.release-please.outputs.release_created }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
ref: ${{ needs.release-please.outputs.release_tag_name }}
|
ref: ${{ needs.release-please.outputs.release_tag_name }}
|
||||||
|
|
||||||
- name: Log in to the Container registry
|
- name: Log in to the Container registry
|
||||||
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
registry: ${{ env.REGISTRY }}
|
registry: ${{ env.REGISTRY }}
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
|
@ -43,30 +42,31 @@ jobs:
|
||||||
|
|
||||||
- name: Extract metadata (tags, labels) for Docker
|
- name: Extract metadata (tags, labels) for Docker
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@818d4b7b91585d195f67373fd9cb0332e31a7175 # v4
|
uses: docker/metadata-action@v4
|
||||||
with:
|
with:
|
||||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
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
|
- name: Get current date
|
||||||
id: date
|
id: date
|
||||||
run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
|
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
|
- name: Build App Container
|
||||||
uses: docker/build-push-action@0a97817b6ade9f46837855d676c4cca3a2471fc9 # v4
|
uses: docker/build-push-action@v4
|
||||||
with:
|
with:
|
||||||
|
# builder: ${{ steps.buildx.outputs.name }}
|
||||||
context: .
|
context: .
|
||||||
file: ./packages/app/Dockerfile
|
file: ./packages/app/Dockerfile
|
||||||
|
# platforms: linux/amd64,linux/arm64
|
||||||
push: true
|
push: true
|
||||||
provenance: false
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
tags: |
|
tags: |
|
||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}-app:latest
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}-app:latest
|
||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}-app:${{ needs.release-please.outputs.release_tag_name }}
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}-app:${{ needs.release-please.outputs.release_tag_name }}
|
||||||
|
@ -77,13 +77,13 @@ jobs:
|
||||||
DATE=${{ steps.date.outputs.date }}
|
DATE=${{ steps.date.outputs.date }}
|
||||||
|
|
||||||
- name: Build Fibonacci Service Container
|
- name: Build Fibonacci Service Container
|
||||||
uses: docker/build-push-action@0a97817b6ade9f46837855d676c4cca3a2471fc9 # v4
|
uses: docker/build-push-action@v4
|
||||||
with:
|
with:
|
||||||
|
# builder: ${{ steps.buildx.outputs.name }}
|
||||||
context: .
|
context: .
|
||||||
file: ./packages/fibonacci-service/Dockerfile
|
file: ./packages/fibonacci-service/Dockerfile
|
||||||
|
# platforms: linux/amd64,linux/arm64
|
||||||
push: true
|
push: true
|
||||||
provenance: false
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
tags: |
|
tags: |
|
||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}-fib-service:latest
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}-fib-service:latest
|
||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}-fib-service:${{ needs.release-please.outputs.release_tag_name }}
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}-fib-service:${{ needs.release-please.outputs.release_tag_name }}
|
||||||
|
|
|
@ -45,5 +45,3 @@ Thumbs.db
|
||||||
# yalc stuff
|
# yalc stuff
|
||||||
.yalc
|
.yalc
|
||||||
yalc.lock
|
yalc.lock
|
||||||
|
|
||||||
config/flipt/flipt.db
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
".": "0.16.0"
|
".": "0.13.1"
|
||||||
}
|
}
|
139
CHANGELOG.md
139
CHANGELOG.md
|
@ -1,144 +1,5 @@
|
||||||
# Changelog
|
# 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)
|
## [0.13.1](https://github.com/open-feature/playground/compare/v0.13.0...v0.13.1) (2023-11-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
41
README.md
41
README.md
|
@ -28,8 +28,6 @@ If you're brand new to feature flagging, consider reviewing the [What are featur
|
||||||
- [Harness](#harness)
|
- [Harness](#harness)
|
||||||
- [LaunchDarkly](#launchdarkly)
|
- [LaunchDarkly](#launchdarkly)
|
||||||
- [Flagsmith](#flagsmith)
|
- [Flagsmith](#flagsmith)
|
||||||
- [Flipt](#flipt)
|
|
||||||
- [ConfigCat](#configcat)
|
|
||||||
- [Experimenting beyond the demo](#experimenting-beyond-the-demo)
|
- [Experimenting beyond the demo](#experimenting-beyond-the-demo)
|
||||||
- [Evaluation context](#evaluation-context)
|
- [Evaluation context](#evaluation-context)
|
||||||
- [Troubleshooting](#troubleshooting)
|
- [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!
|
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>
|
</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
|
## Experimenting beyond the demo
|
||||||
|
|
||||||
### Evaluation context
|
### Evaluation context
|
||||||
|
|
|
@ -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
|
|
|
@ -22,15 +22,6 @@ hex-color:
|
||||||
default: 2f5230
|
default: 2f5230
|
||||||
percentage: 100
|
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
|
# Must be a valid algorithm name
|
||||||
# - recurive
|
# - recurive
|
||||||
# - memo
|
# - memo
|
||||||
|
|
|
@ -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
|
|
|
@ -1,8 +1,8 @@
|
||||||
# Flags for our UI
|
# A basic flag custom resource
|
||||||
apiVersion: core.openfeature.dev/v1beta1
|
apiVersion: core.openfeature.dev/v1beta1
|
||||||
kind: FeatureFlag
|
kind: FeatureFlag
|
||||||
metadata:
|
metadata:
|
||||||
name: ui-flags
|
name: end-to-end
|
||||||
labels:
|
labels:
|
||||||
app: open-feature-demo
|
app: open-feature-demo
|
||||||
spec:
|
spec:
|
||||||
|
@ -25,22 +25,11 @@ spec:
|
||||||
targeting:
|
targeting:
|
||||||
if:
|
if:
|
||||||
- in:
|
- in:
|
||||||
- '@faas.com'
|
- "@faas.com"
|
||||||
- var:
|
- var:
|
||||||
- email
|
- email
|
||||||
- yellow
|
- yellow
|
||||||
- null
|
- 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:
|
fib-algo:
|
||||||
variants:
|
variants:
|
||||||
recursive: recursive
|
recursive: recursive
|
||||||
|
@ -52,9 +41,9 @@ spec:
|
||||||
targeting:
|
targeting:
|
||||||
if:
|
if:
|
||||||
- in:
|
- in:
|
||||||
- '@faas.com'
|
- "@faas.com"
|
||||||
- var:
|
- var:
|
||||||
- email
|
- email
|
||||||
- binet
|
- binet
|
||||||
- null
|
- null
|
||||||
use-remote-fib-service:
|
use-remote-fib-service:
|
||||||
|
@ -64,22 +53,20 @@ spec:
|
||||||
'off': false
|
'off': false
|
||||||
defaultVariant: 'off'
|
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
|
apiVersion: core.openfeature.dev/v1beta1
|
||||||
kind: FeatureFlagSource
|
kind: FeatureFlagSource
|
||||||
metadata:
|
metadata:
|
||||||
name: flag-sources
|
name: end-to-end
|
||||||
labels:
|
labels:
|
||||||
app: open-feature-demo
|
app: open-feature-demo
|
||||||
spec:
|
spec:
|
||||||
sources:
|
sources:
|
||||||
- source: app-flags
|
- source: end-to-end
|
||||||
provider: kubernetes
|
|
||||||
- source: ui-flags
|
|
||||||
provider: kubernetes
|
provider: kubernetes
|
||||||
|
|
||||||
---
|
---
|
||||||
# Deployment of a demo-app using our custom resources
|
# Deployment of a demo-app using our custom resource
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
|
@ -96,25 +83,23 @@ spec:
|
||||||
labels:
|
labels:
|
||||||
app: open-feature-demo
|
app: open-feature-demo
|
||||||
annotations:
|
annotations:
|
||||||
openfeature.dev/enabled: 'true'
|
openfeature.dev/enabled: "true"
|
||||||
openfeature.dev/featureflagsource: 'flag-sources'
|
openfeature.dev/featureflagsource: "end-to-end"
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: open-feature-demo
|
- 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:
|
args:
|
||||||
- flagd
|
- flagd
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 30000
|
- containerPort: 30000
|
||||||
env:
|
|
||||||
- name: FLAGD_PORT_WEB
|
|
||||||
value: '30002'
|
|
||||||
---
|
---
|
||||||
# Service to expose our application
|
# Service exposed using NodePort
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: open-feature-demo-app-service
|
name: open-feature-demo-service
|
||||||
labels:
|
labels:
|
||||||
app: open-feature-demo
|
app: open-feature-demo
|
||||||
spec:
|
spec:
|
||||||
|
@ -122,23 +107,7 @@ spec:
|
||||||
selector:
|
selector:
|
||||||
app: open-feature-demo
|
app: open-feature-demo
|
||||||
ports:
|
ports:
|
||||||
|
# By default and for convenience, the `targetPort` is set to the same value as the `port` field.
|
||||||
- port: 30000
|
- port: 30000
|
||||||
targetPort: 30000
|
targetPort: 30000
|
||||||
nodePort: 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
|
|
||||||
|
|
|
@ -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
|
|
|
@ -1,7 +1,7 @@
|
||||||
version: '3.8'
|
version: '3.8'
|
||||||
services:
|
services:
|
||||||
demo:
|
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:
|
# build:
|
||||||
# dockerfile: ./packages/app/Dockerfile
|
# dockerfile: ./packages/app/Dockerfile
|
||||||
# context: .
|
# context: .
|
||||||
|
@ -21,10 +21,7 @@ services:
|
||||||
- OTEL_EXPORTER_JAEGER_AGENT_HOST=jaeger
|
- OTEL_EXPORTER_JAEGER_AGENT_HOST=jaeger
|
||||||
- OTEL_EXPORTER_JAEGER_AGENT_PORT=6832
|
- OTEL_EXPORTER_JAEGER_AGENT_PORT=6832
|
||||||
- GO_FEATURE_FLAG_URL=http://go-feature-flag:1031
|
- GO_FEATURE_FLAG_URL=http://go-feature-flag:1031
|
||||||
- GO_FEATURE_FLAG_WEB_URL=http://localhost:1031
|
|
||||||
- FIB_SERVICE_URL=http://fib-service:30001
|
- FIB_SERVICE_URL=http://fib-service:30001
|
||||||
- FLIPT_URL=http://flipt:8080
|
|
||||||
- FLIPT_WEB_URL=http://localhost:8080
|
|
||||||
- FIB_SERVICE_USER
|
- FIB_SERVICE_USER
|
||||||
- FIB_SERVICE_PASS
|
- FIB_SERVICE_PASS
|
||||||
# Provider values come from the .env
|
# Provider values come from the .env
|
||||||
|
@ -38,7 +35,6 @@ services:
|
||||||
- LD_KEY
|
- LD_KEY
|
||||||
- FLAGSMITH_ENV_KEY
|
- FLAGSMITH_ENV_KEY
|
||||||
- CLOUDBEES_APP_KEY
|
- CLOUDBEES_APP_KEY
|
||||||
- CONFIGCAT_SDK_KEY
|
|
||||||
## Web
|
## Web
|
||||||
- HARNESS_KEY_WEB
|
- HARNESS_KEY_WEB
|
||||||
- SPLIT_KEY_WEB
|
- SPLIT_KEY_WEB
|
||||||
|
@ -47,11 +43,10 @@ services:
|
||||||
- CLOUDBEES_APP_KEY_WEB
|
- CLOUDBEES_APP_KEY_WEB
|
||||||
- FLAGD_HOST_WEB
|
- FLAGD_HOST_WEB
|
||||||
- FLAGD_PORT_WEB
|
- FLAGD_PORT_WEB
|
||||||
- FLAGD_TLS_WEB
|
- FLAGD_TLS_WEB
|
||||||
- CONFIGCAT_SDK_KEY_WEB
|
|
||||||
|
|
||||||
fib-service:
|
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:
|
# build:
|
||||||
# dockerfile: ./packages/fibonacci-service/Dockerfile
|
# dockerfile: ./packages/fibonacci-service/Dockerfile
|
||||||
# context: .
|
# context: .
|
||||||
|
@ -62,8 +57,6 @@ services:
|
||||||
- OTEL_EXPORTER_JAEGER_AGENT_HOST=jaeger
|
- OTEL_EXPORTER_JAEGER_AGENT_HOST=jaeger
|
||||||
- OTEL_EXPORTER_JAEGER_AGENT_PORT=6832
|
- OTEL_EXPORTER_JAEGER_AGENT_PORT=6832
|
||||||
- OTEL_SERVICE_NAME=fibonacci-service
|
- OTEL_SERVICE_NAME=fibonacci-service
|
||||||
- GO_FEATURE_FLAG_URL=http://go-feature-flag:1031
|
|
||||||
- FLIPT_URL=http://flipt:8080
|
|
||||||
- FIB_SERVICE_USER
|
- FIB_SERVICE_USER
|
||||||
- FIB_SERVICE_PASS
|
- FIB_SERVICE_PASS
|
||||||
# Provider values come from the .env
|
# Provider values come from the .env
|
||||||
|
@ -76,10 +69,9 @@ services:
|
||||||
- LD_KEY
|
- LD_KEY
|
||||||
- FLAGSMITH_ENV_KEY
|
- FLAGSMITH_ENV_KEY
|
||||||
- CLOUDBEES_APP_KEY
|
- CLOUDBEES_APP_KEY
|
||||||
- CONFIGCAT_SDK_KEY
|
|
||||||
|
|
||||||
jaeger:
|
jaeger:
|
||||||
image: jaegertracing/all-in-one:1.60
|
image: jaegertracing/all-in-one:1.49.0
|
||||||
expose:
|
expose:
|
||||||
- '6832/udp'
|
- '6832/udp'
|
||||||
- '4317'
|
- '4317'
|
||||||
|
@ -87,7 +79,7 @@ services:
|
||||||
- '16686:16686'
|
- '16686:16686'
|
||||||
|
|
||||||
otel-collector:
|
otel-collector:
|
||||||
image: otel/opentelemetry-collector-contrib:0.105.0
|
image: otel/opentelemetry-collector-contrib:0.85.0
|
||||||
restart: always
|
restart: always
|
||||||
command: [ "--config=/etc/otel-collector-config.yaml" ]
|
command: [ "--config=/etc/otel-collector-config.yaml" ]
|
||||||
volumes:
|
volumes:
|
||||||
|
@ -103,7 +95,7 @@ services:
|
||||||
|
|
||||||
prometheus:
|
prometheus:
|
||||||
container_name: prometheus
|
container_name: prometheus
|
||||||
image: prom/prometheus:v2.55.1
|
image: prom/prometheus:v2.47.2
|
||||||
restart: always
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
- ./config/prometheus/prometheus.yaml:/etc/prometheus/prometheus.yml
|
- ./config/prometheus/prometheus.yaml:/etc/prometheus/prometheus.yml
|
||||||
|
@ -111,7 +103,7 @@ services:
|
||||||
- "9090:9090"
|
- "9090:9090"
|
||||||
|
|
||||||
flagd:
|
flagd:
|
||||||
image: ghcr.io/open-feature/flagd:v0.11.5
|
image: ghcr.io/open-feature/flagd:v0.6.8
|
||||||
command:
|
command:
|
||||||
- start
|
- start
|
||||||
- --cors-origin
|
- --cors-origin
|
||||||
|
@ -126,43 +118,13 @@ services:
|
||||||
- ./config/flagd/flags.json:/etc/flagd/flags.json
|
- ./config/flagd/flags.json:/etc/flagd/flags.json
|
||||||
ports:
|
ports:
|
||||||
- '8013:8013'
|
- '8013:8013'
|
||||||
- '8016:8016'
|
|
||||||
|
|
||||||
go-feature-flag:
|
go-feature-flag:
|
||||||
image: thomaspoignant/go-feature-flag:v1.40.0
|
image: thomaspoignant/go-feature-flag-relay-proxy:v1.12.1
|
||||||
volumes:
|
volumes:
|
||||||
- ./config/go-feature-flag:/goff/
|
- ./config/go-feature-flag:/goff/
|
||||||
ports:
|
expose:
|
||||||
- "1031: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'
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
flagd-flags:
|
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 |
|
@ -2,18 +2,87 @@
|
||||||
"migrations": [
|
"migrations": [
|
||||||
{
|
{
|
||||||
"cli": "nx",
|
"cli": "nx",
|
||||||
"version": "17.2.1-beta.0",
|
"version": "16.7.0-beta.2",
|
||||||
"description": "Add webpack.config.js file when webpackConfig is not defined",
|
"description": "Add @babel/core to package.json if @babel/preset-react is present",
|
||||||
"implementation": "./src/migrations/update-17-2-1/webpack-config-setup",
|
"implementation": "./src/migrations/update-16-7-0/add-babel-core",
|
||||||
"package": "@nx/webpack",
|
"package": "@nx/react",
|
||||||
"name": "update-17-2-1-webpack-config-setup"
|
"name": "add-babel-core"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"version": "17.2.0-beta.0",
|
"cli": "nx",
|
||||||
"description": "Simplify eslintFilePatterns",
|
"version": "16.7.0-beta.2",
|
||||||
"implementation": "./src/migrations/update-17-2-0/simplify-eslint-patterns",
|
"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",
|
"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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
210
package.json
210
package.json
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "openfeature",
|
"name": "openfeature",
|
||||||
"version": "0.16.0",
|
"version": "0.13.1",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"ui": "nx run ui:serve",
|
"ui": "nx run ui:serve",
|
||||||
"app": "nx run app:serve",
|
"app": "nx run app:serve",
|
||||||
"fib-service": "nx run fibonacci-service: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:app": "nx build app && nx build ui",
|
||||||
"build:fib-service": "nx build fibonacci-service",
|
"build:fib-service": "nx build fibonacci-service",
|
||||||
"lint": "nx run-many --all --target=lint",
|
"lint": "nx run-many --all --target=lint",
|
||||||
|
@ -16,137 +16,119 @@
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@harnessio/ff-javascript-client-sdk": "^1.21.0",
|
"@harnessio/ff-javascript-client-sdk": "^1.10.0",
|
||||||
"@harnessio/ff-nodejs-server-sdk": "^1.4.0",
|
"@harnessio/ff-nodejs-server-sdk": "^1.2.8",
|
||||||
"@nestjs/axios": "^3.0.2",
|
"@nestjs/axios": "^2.0.0",
|
||||||
"@nestjs/common": "10.4.15",
|
"@nestjs/common": "9.4.3",
|
||||||
"@nestjs/core": "10.4.15",
|
"@nestjs/core": "9.4.3",
|
||||||
"@nestjs/platform-express": "10.4.15",
|
"@nestjs/platform-express": "9.4.3",
|
||||||
"@nestjs/serve-static": "^4.0.2",
|
"@nestjs/serve-static": "^3.0.0",
|
||||||
"@openfeature/config-cat-web-provider": "^0.1.3",
|
"@openfeature/env-var-provider": "^0.1.1",
|
||||||
"@openfeature/config-cat-provider": "^0.7.2",
|
"@openfeature/flagd-provider": "^0.8.2",
|
||||||
"@openfeature/env-var-provider": "^0.3.0",
|
"@openfeature/flagd-web-provider": "^0.4.0",
|
||||||
"@openfeature/flagd-provider": "^0.13.0",
|
"@openfeature/go-feature-flag-provider": "^0.5.14",
|
||||||
"@openfeature/flagd-web-provider": "^0.7.0",
|
"@openfeature/js-sdk": "^1.4.1",
|
||||||
"@openfeature/flipt-provider": "^0.1.0",
|
"@openfeature/open-telemetry-hooks": "^0.2.3",
|
||||||
"@openfeature/flipt-web-provider": "^0.1.0",
|
"@openfeature/web-sdk": "0.4.0",
|
||||||
"@openfeature/go-feature-flag-provider": "^0.7.0",
|
"@opentelemetry/api": "~1.6.0",
|
||||||
"@openfeature/go-feature-flag-web-provider": "^0.2.0",
|
"@opentelemetry/auto-instrumentations-node": "^0.39.2",
|
||||||
"@openfeature/nestjs-sdk": "^0.1.3-experimental",
|
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.43.0",
|
||||||
"@openfeature/ofrep-provider": "^0.1.3",
|
"@opentelemetry/exporter-trace-otlp-grpc": "^0.43.0",
|
||||||
"@openfeature/ofrep-web-provider": "^0.1.3",
|
"@opentelemetry/sdk-metrics": "^1.15.1",
|
||||||
"@openfeature/open-telemetry-hooks": "^0.4.0",
|
"@opentelemetry/sdk-node": "^0.43.0",
|
||||||
"@openfeature/web-sdk": "1.0.3",
|
"@splitsoftware/openfeature-js-split-provider": "^1.0.5",
|
||||||
"@opentelemetry/api": "^1.8.0",
|
"@splitsoftware/splitio": "^10.22.3",
|
||||||
"@opentelemetry/auto-instrumentations-node": "^0.44.0",
|
"@splitsoftware/splitio-browserjs": "^0.10.0",
|
||||||
"@opentelemetry/core": "^1.23.0",
|
"@types/rox-browser": "^5.0.2",
|
||||||
"@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",
|
|
||||||
"change-case": "^4.1.2",
|
"change-case": "^4.1.2",
|
||||||
"class-validator": "^0.14.1",
|
"class-validator": "^0.14.0",
|
||||||
"cloudbees-openfeature-provider-node": "^1.0.0",
|
"cloudbees-openfeature-provider-node": "^1.0.0",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
"eventemitter3": "^5.0.1",
|
"eventemitter3": "^5.0.1",
|
||||||
"events": "^3.3.0",
|
"events": "^3.3.0",
|
||||||
"express": "4.21.2",
|
"express": "4.18.2",
|
||||||
"express-validator": "^7.0.1",
|
"express-validator": "^7.0.0",
|
||||||
"flagsmith": "^3.21.0",
|
"flagsmith": "^3.14.2",
|
||||||
"flagsmith-nodejs": "^3.2.0",
|
"flagsmith-nodejs": "^2.5.0",
|
||||||
"launchdarkly-js-client-sdk": "^3.1.4",
|
"launchdarkly-js-client-sdk": "^3.0.0",
|
||||||
"launchdarkly-node-server-sdk": "^7.0.3",
|
"launchdarkly-node-server-sdk": "^7.0.0",
|
||||||
"nestjs-pino": "^4.0.0",
|
"nestjs-pino": "^3.1.2",
|
||||||
"pino-http": "^9.0.0",
|
"pino-http": "^8.3.1",
|
||||||
"pino-pretty": "^11.0.0",
|
"pino-pretty": "^10.0.0",
|
||||||
"react-router-dom": "^6.21.1",
|
"react-router-dom": "^6.11.2",
|
||||||
"reflect-metadata": "^0.2.0",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rox-browser": "^5.4.9",
|
"rox-browser": "^5.4.2",
|
||||||
"rox-node": "^5.4.9",
|
"rox-node": "^5.4.2",
|
||||||
"rxjs": "^7.8.0"
|
"rxjs": "^7.8.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/preset-react": "^7.23.3",
|
"@babel/preset-react": "^7.18.6",
|
||||||
"@emotion/react": "11.14.0",
|
"@emotion/react": "11.11.1",
|
||||||
"@emotion/styled": "11.14.0",
|
"@emotion/styled": "11.11.0",
|
||||||
"@mui/material": "^5.15.2",
|
"@mui/material": "^5.11.3",
|
||||||
"@nestjs/schematics": "10.2.3",
|
"@nestjs/schematics": "9.2.0",
|
||||||
"@nestjs/testing": "10.4.15",
|
"@nestjs/testing": "9.4.3",
|
||||||
"@nrwl/tao": "17.3.2",
|
"@nrwl/tao": "17.1.3",
|
||||||
"@nx/devkit": "17.3.2",
|
"@nx/devkit": "17.1.3",
|
||||||
"@nx/eslint-plugin": "17.3.2",
|
"@nx/eslint-plugin": "17.1.3",
|
||||||
"@nx/express": "17.3.2",
|
"@nx/express": "17.1.3",
|
||||||
"@nx/jest": "17.3.2",
|
"@nx/jest": "17.1.3",
|
||||||
"@nx/js": "17.3.2",
|
"@nx/js": "17.1.3",
|
||||||
"@nx/linter": "17.3.2",
|
"@nx/linter": "17.1.3",
|
||||||
"@nx/nest": "17.3.2",
|
"@nx/nest": "17.1.3",
|
||||||
"@nx/node": "17.3.2",
|
"@nx/node": "17.1.3",
|
||||||
"@nx/react": "17.3.2",
|
"@nx/react": "17.1.3",
|
||||||
"@nx/web": "17.3.2",
|
"@nx/web": "17.1.3",
|
||||||
"@nx/webpack": "17.3.2",
|
"@nx/webpack": "17.1.3",
|
||||||
"@nx/workspace": "17.3.2",
|
"@nx/workspace": "17.1.3",
|
||||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.11",
|
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
|
||||||
"@reactour/tour": "^3.6.1",
|
"@reactour/tour": "^3.1.8",
|
||||||
"@svgr/webpack": "^8.1.0",
|
"@svgr/webpack": "^8.0.0",
|
||||||
"@testing-library/react": "^12.1.5",
|
"@testing-library/react": "^12.1.5",
|
||||||
"@types/events": "^3.0.3",
|
"@types/events": "^3.0.0",
|
||||||
"@types/express": "4.17.21",
|
"@types/express": "4.17.21",
|
||||||
"@types/jest": "^29.5.11",
|
"@types/jest": "^29.2.5",
|
||||||
"@types/node": "18.19.68",
|
"@types/node": "18.18.9",
|
||||||
"@types/react": "18.3.18",
|
"@types/react": "18.2.24",
|
||||||
"@types/react-dom": "18.3.5",
|
"@types/react-dom": "18.2.9",
|
||||||
"@types/react-json-editor-ajrm": "^2.5.6",
|
"@types/react-json-editor-ajrm": "^2.5.3",
|
||||||
"@types/react-modal": "^3.16.3",
|
"@types/react-modal": "^3.13.1",
|
||||||
"@types/rox-node": "^5.0.5",
|
"@types/rox-node": "^5.0.1",
|
||||||
"@typescript-eslint/eslint-plugin": "6.21.0",
|
"@typescript-eslint/eslint-plugin": "6.13.1",
|
||||||
"@typescript-eslint/parser": "6.21.0",
|
"@typescript-eslint/parser": "6.13.1",
|
||||||
"ajv": "^8.12.0",
|
"ajv": "^8.12.0",
|
||||||
"babel-jest": "^29.7.0",
|
"babel-jest": "^29.3.1",
|
||||||
"core-js": "^3.35.0",
|
"core-js": "^3.27.1",
|
||||||
"css-loader": "^6.8.1",
|
"css-loader": "^6.7.3",
|
||||||
"eslint": "8.57.1",
|
"eslint": "8.54.0",
|
||||||
"eslint-config-prettier": "9.1.0",
|
"eslint-config-prettier": "9.0.0",
|
||||||
"eslint-plugin-import": "2.31.0",
|
"eslint-plugin-import": "2.29.0",
|
||||||
"eslint-plugin-jsx-a11y": "6.10.2",
|
"eslint-plugin-jsx-a11y": "6.8.0",
|
||||||
"eslint-plugin-react": "7.37.2",
|
"eslint-plugin-react": "7.33.2",
|
||||||
"eslint-plugin-react-hooks": "4.6.2",
|
"eslint-plugin-react-hooks": "4.6.0",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.3.1",
|
||||||
"jest-environment-jsdom": "^29.7.0",
|
"jest-environment-jsdom": "^29.3.1",
|
||||||
"json-schema-to-typescript": "^11.0.5",
|
"json-schema-to-typescript": "^11.0.2",
|
||||||
"jsoneditor-react": "^3.1.2",
|
"jsoneditor-react": "^3.1.2",
|
||||||
"markdown-toc": "^1.2.0",
|
"markdown-toc": "^1.2.0",
|
||||||
"prettier": "2.8.8",
|
"prettier": "2.8.8",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^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-json-view": "^1.21.3",
|
||||||
"react-modal": "^3.16.1",
|
"react-modal": "^3.16.1",
|
||||||
"react-refresh": "^0.16.0",
|
"react-refresh": "^0.14.0",
|
||||||
"regenerator-runtime": "^0.14.0",
|
"regenerator-runtime": "^0.13.11",
|
||||||
"style-loader": "^3.3.3",
|
"style-loader": "^3.3.1",
|
||||||
"styled-components": "5.3.11",
|
"styled-components": "5.3.11",
|
||||||
"stylus": "^0.64.0",
|
"stylus": "^0.59.0",
|
||||||
"stylus-loader": "^7.1.3",
|
"stylus-loader": "^7.1.0",
|
||||||
"ts-jest": "29.2.5",
|
"ts-jest": "29.1.1",
|
||||||
"ts-node": "10.9.2",
|
"ts-node": "10.9.1",
|
||||||
"tslib": "^2.6.2",
|
"tslib": "^2.4.1",
|
||||||
"typescript": "5.7.2",
|
"typescript": "5.3.2",
|
||||||
"url-loader": "^4.1.1",
|
"url-loader": "^4.1.1",
|
||||||
"webpack": "5.97.1",
|
"webpack": "5.89.0",
|
||||||
"webpack-merge": "^5.10.0"
|
"webpack-merge": "^5.8.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"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM node:20.18-bullseye AS builder
|
FROM node:20.3-bullseye AS builder
|
||||||
WORKDIR /tmp/playground/
|
WORKDIR /tmp/playground/
|
||||||
COPY package*.json tsconfig*.json nx.json babel.config.json ./
|
COPY package*.json tsconfig*.json nx.json babel.config.json ./
|
||||||
COPY schemas/ ./schemas/
|
COPY schemas/ ./schemas/
|
||||||
|
|
|
@ -13,8 +13,7 @@
|
||||||
"tsConfig": "packages/app/tsconfig.app.json",
|
"tsConfig": "packages/app/tsconfig.app.json",
|
||||||
"assets": ["packages/app/src/assets"],
|
"assets": ["packages/app/src/assets"],
|
||||||
"target": "node",
|
"target": "node",
|
||||||
"compiler": "tsc",
|
"compiler": "tsc"
|
||||||
"webpackConfig": "packages/app/webpack.config.js"
|
|
||||||
},
|
},
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"production": {
|
"production": {
|
||||||
|
|
|
@ -1,18 +1,27 @@
|
||||||
import { HttpModule } from '@nestjs/axios';
|
import {HttpModule} from '@nestjs/axios';
|
||||||
import { ExecutionContext, Module } from '@nestjs/common';
|
import {MiddlewareConsumer, Module, NestModule, Scope} from '@nestjs/common';
|
||||||
import { ServeStaticModule } from '@nestjs/serve-static';
|
import {REQUEST} from '@nestjs/core';
|
||||||
import { LoggingHook, OpenFeatureLogger } from '@openfeature/extra';
|
import {ServeStaticModule} from '@nestjs/serve-static';
|
||||||
import { MetricsHook, TracingHook as SpanEventBasedTracingHook } from '@openfeature/open-telemetry-hooks';
|
import {AsyncLocalStorageTransactionContext, LoggingHook, OpenFeatureLogger} from '@openfeature/extra';
|
||||||
import { ProviderService } from '@openfeature/provider';
|
import {FlagMetadata, OpenFeature} from '@openfeature/js-sdk';
|
||||||
import { Request } from 'express';
|
import {MetricsHook, TracingHook as SpanEventBasedTracingHook} from '@openfeature/open-telemetry-hooks';
|
||||||
import { Agent } from 'http';
|
import {ProviderService} from '@openfeature/provider';
|
||||||
import { LoggerModule } from 'nestjs-pino';
|
import {Request} from 'express';
|
||||||
import { join } from 'path';
|
import {Agent} from 'http';
|
||||||
import { FibonacciAsAServiceController } from './fibonacci-as-a-service.controller';
|
import {LoggerModule} from 'nestjs-pino';
|
||||||
import { FibonacciService } from './fibonacci/fibonacci.service';
|
import {join} from 'path';
|
||||||
import { ProvidersController } from './providers.controller';
|
import {OPENFEATURE_CLIENT, REQUEST_DATA} from './constants';
|
||||||
import { UtilsController } from './utils.controller';
|
import {FibonacciAsAServiceController} from './fibonacci-as-a-service.controller';
|
||||||
import { EvaluationContext, FlagMetadata, OpenFeatureModule } from '@openfeature/nestjs-sdk';
|
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) {
|
function attributeMapper(flagMetadata: FlagMetadata) {
|
||||||
return {
|
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({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
LoggerModule.forRoot({
|
LoggerModule.forRoot({
|
||||||
|
@ -48,22 +73,24 @@ function attributeMapper(flagMetadata: FlagMetadata) {
|
||||||
HttpModule.register({
|
HttpModule.register({
|
||||||
httpAgent: new Agent({ keepAlive: true }),
|
httpAgent: new Agent({ keepAlive: true }),
|
||||||
}),
|
}),
|
||||||
OpenFeatureModule.forRoot({
|
],
|
||||||
// Set a global logger for OpenFeature. This is logger will available in hooks.
|
controllers: [FibonacciAsAServiceController, UtilsController, ProvidersController],
|
||||||
logger: new OpenFeatureLogger('OpenFeature'),
|
providers: [
|
||||||
//Adding hooks to at the global level will ensure they always run as part of a flag evaluation lifecycle.
|
FibonacciService,
|
||||||
hooks: [
|
ProviderService,
|
||||||
new LoggingHook(),
|
{
|
||||||
new SpanEventBasedTracingHook({ attributeMapper }),
|
provide: OPENFEATURE_CLIENT,
|
||||||
new MetricsHook({ attributeMapper }),
|
useFactory: () => {
|
||||||
],
|
const client = OpenFeature.getClient('app');
|
||||||
// This context will be used for all flag evaluations in the callstack
|
return client;
|
||||||
contextFactory: async (context: ExecutionContext): Promise<EvaluationContext> => {
|
},
|
||||||
const req = await context.switchToHttp().getRequest<Request>();
|
},
|
||||||
|
{
|
||||||
|
provide: REQUEST_DATA,
|
||||||
|
useFactory: (req: Request): RequestData => {
|
||||||
const authHeaderValue = req.header('Authorization') || 'anonymous';
|
const authHeaderValue = req.header('Authorization') || 'anonymous';
|
||||||
const userAgent = req.header('user-agent');
|
const userAgent = req.header('user-agent');
|
||||||
return {
|
return {
|
||||||
ts: new Date().getTime(),
|
|
||||||
ip: (req.headers['x-forwarded-for'] as string) || (req.socket.remoteAddress as string),
|
ip: (req.headers['x-forwarded-for'] as string) || (req.socket.remoteAddress as string),
|
||||||
email: authHeaderValue,
|
email: authHeaderValue,
|
||||||
method: req.method,
|
method: req.method,
|
||||||
|
@ -72,9 +99,13 @@ function attributeMapper(flagMetadata: FlagMetadata) {
|
||||||
targetingKey: authHeaderValue,
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
export const OPENFEATURE_CLIENT = Symbol.for('OPENFEATURE_CLIENT');
|
||||||
|
export const REQUEST_DATA = Symbol.for('REQUEST_DATA');
|
|
@ -1,15 +1,15 @@
|
||||||
import {HttpService} from '@nestjs/axios';
|
import { HttpService } from '@nestjs/axios';
|
||||||
import {Injectable} from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import {fibonacci} from '@openfeature/fibonacci';
|
import { fibonacci } from '@openfeature/fibonacci';
|
||||||
import {lastValueFrom, map} from 'rxjs';
|
import { Client } from '@openfeature/js-sdk';
|
||||||
import {Client, FeatureClient} from "@openfeature/nestjs-sdk";
|
import { OPENFEATURE_CLIENT } from '../constants';
|
||||||
|
import { lastValueFrom, map } from 'rxjs';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FibonacciService {
|
export class FibonacciService {
|
||||||
private readonly FIB_SERVICE_URL = process.env.FIB_SERVICE_URL || 'http://localhost:30001';
|
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 }> {
|
async calculateFibonacci(num: number): Promise<{ result: number }> {
|
||||||
const useRemoteFibService = await this.client.getBooleanValue('use-remote-fib-service', false);
|
const useRemoteFibService = await this.client.getBooleanValue('use-remote-fib-service', false);
|
||||||
|
@ -18,7 +18,7 @@ export class FibonacciService {
|
||||||
return lastValueFrom(
|
return lastValueFrom(
|
||||||
this.httpService
|
this.httpService
|
||||||
.get<{ result: number }>(`${this.FIB_SERVICE_URL}/calculate`, {
|
.get<{ result: number }>(`${this.FIB_SERVICE_URL}/calculate`, {
|
||||||
params: {num},
|
params: { num },
|
||||||
auth: {
|
auth: {
|
||||||
username: process.env.FIB_SERVICE_USER || '',
|
username: process.env.FIB_SERVICE_USER || '',
|
||||||
password: process.env.FIB_SERVICE_PASS || '',
|
password: process.env.FIB_SERVICE_PASS || '',
|
||||||
|
|
|
@ -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();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
};
|
|
@ -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;
|
|
||||||
});
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM node:20.18-bullseye-slim AS builder
|
FROM node:20.3-bullseye-slim AS builder
|
||||||
WORKDIR /tmp/playground/
|
WORKDIR /tmp/playground/
|
||||||
COPY package*.json tsconfig*.json nx.json babel.config.json ./
|
COPY package*.json tsconfig*.json nx.json babel.config.json ./
|
||||||
RUN npm ci
|
RUN npm ci
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
"compiler": "tsc",
|
"compiler": "tsc",
|
||||||
"outputPath": "dist/packages/fibonacci-service",
|
"outputPath": "dist/packages/fibonacci-service",
|
||||||
"main": "packages/fibonacci-service/src/main.ts",
|
"main": "packages/fibonacci-service/src/main.ts",
|
||||||
"tsConfig": "packages/fibonacci-service/tsconfig.app.json",
|
"tsConfig": "packages/fibonacci-service/tsconfig.app.json"
|
||||||
"webpackConfig": "packages/fibonacci-service/webpack.config.js"
|
|
||||||
},
|
},
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"production": {
|
"production": {
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
import { Module } from '@nestjs/common';
|
import {MiddlewareConsumer, Module, NestModule} from '@nestjs/common';
|
||||||
import { AppController } from './app.controller';
|
import {AppController} from './app.controller';
|
||||||
import { LoggerModule } from 'nestjs-pino';
|
import {LoggerModule} from 'nestjs-pino';
|
||||||
import { LoggingHook, OpenFeatureLogger } from '@openfeature/extra';
|
import {FlagMetadata, OpenFeature} from '@openfeature/js-sdk';
|
||||||
import { MetricsHook, TracingHook as SpanEventBasedTracingHook } from '@openfeature/open-telemetry-hooks';
|
import {AsyncLocalStorageTransactionContext, LoggingHook, OpenFeatureLogger} from '@openfeature/extra';
|
||||||
import { ProviderService } from '@openfeature/provider';
|
import {MetricsHook, TracingHook as SpanEventBasedTracingHook} from '@openfeature/open-telemetry-hooks';
|
||||||
import { ProvidersController } from './providers.controller';
|
import {TransactionContextMiddleware} from './transaction-context.middleware';
|
||||||
import { OpenFeatureModule, FlagMetadata } from '@openfeature/nestjs-sdk';
|
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) {
|
function attributeMapper(flagMetadata: FlagMetadata) {
|
||||||
return {
|
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({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
LoggerModule.forRoot({
|
LoggerModule.forRoot({
|
||||||
|
@ -35,18 +57,12 @@ function attributeMapper(flagMetadata: FlagMetadata) {
|
||||||
: undefined,
|
: 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],
|
controllers: [AppController, ProvidersController],
|
||||||
providers: [ProviderService],
|
providers: [ProviderService],
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule implements NestModule {
|
||||||
|
configure(consumer: MiddlewareConsumer) {
|
||||||
|
consumer.apply(TransactionContextMiddleware).forRoutes(AppController);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
|
||||||
});
|
|
|
@ -11,8 +11,7 @@
|
||||||
"main": "packages/fibonacci/src/index.ts",
|
"main": "packages/fibonacci/src/index.ts",
|
||||||
"tsConfig": "packages/fibonacci/tsconfig.lib.json",
|
"tsConfig": "packages/fibonacci/tsconfig.lib.json",
|
||||||
"target": "node",
|
"target": "node",
|
||||||
"compiler": "tsc",
|
"compiler": "tsc"
|
||||||
"webpackConfig": "packages/fibonacci/webpack.config.js"
|
|
||||||
},
|
},
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"production": {
|
"production": {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { OpenFeature } from '@openfeature/nestjs-sdk';
|
import { OpenFeature } from '@openfeature/js-sdk';
|
||||||
|
|
||||||
const oFeatClient = OpenFeature.getClient('fibonacci');
|
const oFeatClient = OpenFeature.getClient('fibonacci');
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
});
|
|
|
@ -12,8 +12,7 @@
|
||||||
"main": "packages/js-flagsmith-provider/src/index.ts",
|
"main": "packages/js-flagsmith-provider/src/index.ts",
|
||||||
"tsConfig": "packages/js-flagsmith-provider/tsconfig.lib.json",
|
"tsConfig": "packages/js-flagsmith-provider/tsconfig.lib.json",
|
||||||
"target": "node",
|
"target": "node",
|
||||||
"compiler": "tsc",
|
"compiler": "tsc"
|
||||||
"webpackConfig": "packages/js-flagsmith-provider/webpack.config.js"
|
|
||||||
},
|
},
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"production": {
|
"production": {
|
||||||
|
|
|
@ -1,14 +1,4 @@
|
||||||
import {
|
import { EvaluationContext, EvaluationContextValue, FlagNotFoundError, JsonValue, Logger, ParseError, Provider, ResolutionDetails, TypeMismatchError } from '@openfeature/js-sdk';
|
||||||
EvaluationContext,
|
|
||||||
EvaluationContextValue,
|
|
||||||
FlagNotFoundError,
|
|
||||||
JsonValue,
|
|
||||||
Logger,
|
|
||||||
ParseError,
|
|
||||||
Provider,
|
|
||||||
ResolutionDetails,
|
|
||||||
TypeMismatchError,
|
|
||||||
} from '@openfeature/server-sdk';
|
|
||||||
import { parseValidJsonObject } from '@openfeature/utils';
|
import { parseValidJsonObject } from '@openfeature/utils';
|
||||||
import Flagsmith from 'flagsmith-nodejs';
|
import Flagsmith from 'flagsmith-nodejs';
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
});
|
|
|
@ -11,8 +11,7 @@
|
||||||
"main": "packages/js-harness-provider/src/index.ts",
|
"main": "packages/js-harness-provider/src/index.ts",
|
||||||
"tsConfig": "packages/js-harness-provider/tsconfig.lib.json",
|
"tsConfig": "packages/js-harness-provider/tsconfig.lib.json",
|
||||||
"target": "node",
|
"target": "node",
|
||||||
"compiler": "tsc",
|
"compiler": "tsc"
|
||||||
"webpackConfig": "packages/js-harness-provider/webpack.config.js"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lint": {
|
"lint": {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Client, Target } from '@harnessio/ff-nodejs-server-sdk';
|
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
|
* NOTE: This is an unofficial provider that was created for demonstration
|
||||||
|
|
|
@ -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;
|
|
||||||
});
|
|
|
@ -11,8 +11,7 @@
|
||||||
"main": "packages/js-launchdarkly-provider/src/index.ts",
|
"main": "packages/js-launchdarkly-provider/src/index.ts",
|
||||||
"tsConfig": "packages/js-launchdarkly-provider/tsconfig.lib.json",
|
"tsConfig": "packages/js-launchdarkly-provider/tsconfig.lib.json",
|
||||||
"target": "node",
|
"target": "node",
|
||||||
"compiler": "tsc",
|
"compiler": "tsc"
|
||||||
"webpackConfig": "packages/js-launchdarkly-provider/webpack.config.js"
|
|
||||||
},
|
},
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"production": {
|
"production": {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { FlagValue, JsonValue, ParseError, TypeMismatchError } from '@openfeature/server-sdk';
|
import { FlagValue, JsonValue, ParseError, TypeMismatchError } from '@openfeature/js-sdk';
|
||||||
import { EvaluationContext, Provider, ResolutionDetails, Logger } from '@openfeature/server-sdk';
|
import { EvaluationContext, Provider, ResolutionDetails, Logger } from '@openfeature/js-sdk';
|
||||||
import { init, LDClient, LDUser } from 'launchdarkly-node-server-sdk';
|
import { init, LDClient, LDUser } from 'launchdarkly-node-server-sdk';
|
||||||
|
|
||||||
export interface LaunchDarklyProviderOptions {
|
export interface LaunchDarklyProviderOptions {
|
||||||
|
|
|
@ -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;
|
|
||||||
});
|
|
|
@ -11,8 +11,7 @@
|
||||||
"main": "packages/js-split-provider/src/index.ts",
|
"main": "packages/js-split-provider/src/index.ts",
|
||||||
"tsConfig": "packages/js-split-provider/tsconfig.lib.json",
|
"tsConfig": "packages/js-split-provider/tsconfig.lib.json",
|
||||||
"target": "node",
|
"target": "node",
|
||||||
"compiler": "tsc",
|
"compiler": "tsc"
|
||||||
"webpackConfig": "packages/js-split-provider/webpack.config.js"
|
|
||||||
},
|
},
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"production": {
|
"production": {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { JsonValue, TypeMismatchError } from '@openfeature/server-sdk';
|
import { JsonValue, TypeMismatchError } from '@openfeature/js-sdk';
|
||||||
import { EvaluationContext, Provider, ResolutionDetails, Logger } from '@openfeature/server-sdk';
|
import { EvaluationContext, Provider, ResolutionDetails, Logger } from '@openfeature/js-sdk';
|
||||||
import type { Attributes, IClient } from '@splitsoftware/splitio/types/splitio';
|
import type { Attributes, IClient } from '@splitsoftware/splitio/types/splitio';
|
||||||
import { parseValidNumber, parseValidJsonObject } from '@openfeature/utils';
|
import { parseValidNumber, parseValidJsonObject } from '@openfeature/utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* NOTE: This is an unofficial provider that was created for demonstration
|
* NOTE: This is an unofficial provider that was created for demonstration
|
||||||
* purposes only. The playground environment will be updated to use official
|
* purposes only. The playground environment will be updated to use official
|
||||||
* providers once they're available.
|
* providers once they're available.
|
||||||
|
|
|
@ -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;
|
|
||||||
});
|
|
|
@ -11,8 +11,7 @@
|
||||||
"main": "packages/openfeature-extra/src/index.ts",
|
"main": "packages/openfeature-extra/src/index.ts",
|
||||||
"tsConfig": "packages/openfeature-extra/tsconfig.lib.json",
|
"tsConfig": "packages/openfeature-extra/tsconfig.lib.json",
|
||||||
"target": "node",
|
"target": "node",
|
||||||
"compiler": "tsc",
|
"compiler": "tsc"
|
||||||
"webpackConfig": "packages/openfeature-extra/webpack.config.js"
|
|
||||||
},
|
},
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"production": {
|
"production": {
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
export * from './lib/hooks';
|
export * from './lib/hooks';
|
||||||
|
export * from './lib/transaction-context';
|
||||||
export * from './lib/logger';
|
export * from './lib/logger';
|
||||||
|
|
|
@ -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';
|
import { validateSync } from 'class-validator';
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
|
@ -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.
|
* A hook that simply logs at every life-cycle stage.
|
||||||
|
|
|
@ -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';
|
import { Logger } from '@nestjs/common';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './async-local-storage';
|
|
@ -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;
|
|
||||||
});
|
|
|
@ -7,7 +7,7 @@ import {
|
||||||
BaggageEntry,
|
BaggageEntry,
|
||||||
} from '@opentelemetry/api';
|
} from '@opentelemetry/api';
|
||||||
import { isTracingSuppressed } from '@opentelemetry/core';
|
import { isTracingSuppressed } from '@opentelemetry/core';
|
||||||
import { OpenFeature, EvaluationContext } from '@openfeature/nestjs-sdk';
|
import { OpenFeature, EvaluationContext } from '@openfeature/js-sdk';
|
||||||
|
|
||||||
const KEY_PAIR_SEPARATOR = '=';
|
const KEY_PAIR_SEPARATOR = '=';
|
||||||
const PROPERTIES_SEPARATOR = ';';
|
const PROPERTIES_SEPARATOR = ';';
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { GoFeatureFlagProvider } from '@openfeature/go-feature-flag-provider';
|
||||||
import { EnvVarProvider } from '@openfeature/env-var-provider';
|
import { EnvVarProvider } from '@openfeature/env-var-provider';
|
||||||
import { FlagsmithProvider } from '@openfeature/js-flagsmith-provider';
|
import { FlagsmithProvider } from '@openfeature/js-flagsmith-provider';
|
||||||
import { OpenFeatureLaunchDarklyProvider } from '@openfeature/js-launchdarkly-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 { OpenFeatureSplitProvider } from '@openfeature/js-split-provider';
|
||||||
import { SplitFactory } from '@splitsoftware/splitio';
|
import { SplitFactory } from '@splitsoftware/splitio';
|
||||||
import { CloudbeesProvider } from 'cloudbees-openfeature-provider-node';
|
import { CloudbeesProvider } from 'cloudbees-openfeature-provider-node';
|
||||||
|
@ -15,22 +15,14 @@ import { OpenFeatureLogger } from '@openfeature/extra';
|
||||||
import {
|
import {
|
||||||
AvailableProvider,
|
AvailableProvider,
|
||||||
CB_PROVIDER_ID,
|
CB_PROVIDER_ID,
|
||||||
CONFIGCAT_PROVIDER_ID,
|
|
||||||
ENV_PROVIDER_ID,
|
ENV_PROVIDER_ID,
|
||||||
FLAGD_OFREP_PROVIDER_ID,
|
|
||||||
FLAGD_PROVIDER_ID,
|
FLAGD_PROVIDER_ID,
|
||||||
FLAGSMITH_PROVIDER_ID,
|
FLAGSMITH_PROVIDER_ID,
|
||||||
FLIPT_PROVIDER_ID,
|
|
||||||
GO_OFREP_PROVIDER_ID,
|
|
||||||
GO_PROVIDER_ID,
|
GO_PROVIDER_ID,
|
||||||
HARNESS_PROVIDER_ID,
|
HARNESS_PROVIDER_ID,
|
||||||
ProviderId,
|
ProviderId,
|
||||||
SPLIT_PROVIDER_ID,
|
SPLIT_PROVIDER_ID,
|
||||||
} from '@openfeature/utils';
|
} 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<
|
type ProviderMap = Record<
|
||||||
ProviderId,
|
ProviderId,
|
||||||
|
@ -53,18 +45,6 @@ export class ProviderService {
|
||||||
port: Number.parseInt(process.env.FLAGD_PORT_WEB || '8013') || 8013,
|
port: Number.parseInt(process.env.FLAGD_PORT_WEB || '8013') || 8013,
|
||||||
tls: process.env.FLAGD_TLS_WEB === 'true',
|
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: {
|
launchdarkly: {
|
||||||
factory: () => {
|
factory: () => {
|
||||||
const sdkKey = process.env.LD_KEY;
|
const sdkKey = process.env.LD_KEY;
|
||||||
|
@ -119,14 +99,6 @@ export class ProviderService {
|
||||||
endpoint: process.env.GO_FEATURE_FLAG_URL as string,
|
endpoint: process.env.GO_FEATURE_FLAG_URL as string,
|
||||||
}),
|
}),
|
||||||
available: () => !!process.env.GO_FEATURE_FLAG_URL,
|
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]: {
|
[FLAGSMITH_PROVIDER_ID]: {
|
||||||
factory: () => {
|
factory: () => {
|
||||||
|
@ -167,25 +139,6 @@ export class ProviderService {
|
||||||
available: () => !!process.env.HARNESS_KEY && !!process.env.HARNESS_KEY_WEB,
|
available: () => !!process.env.HARNESS_KEY && !!process.env.HARNESS_KEY_WEB,
|
||||||
webCredential: 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() {
|
constructor() {
|
||||||
|
@ -230,7 +183,6 @@ export class ProviderService {
|
||||||
host: p[1].host,
|
host: p[1].host,
|
||||||
port: p[1].port,
|
port: p[1].port,
|
||||||
tls: p[1].tls,
|
tls: p[1].tls,
|
||||||
url: p[1].url,
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,8 @@ import { FlagdWebProvider } from '@openfeature/flagd-web-provider';
|
||||||
import {
|
import {
|
||||||
AvailableProvider,
|
AvailableProvider,
|
||||||
CB_PROVIDER_ID,
|
CB_PROVIDER_ID,
|
||||||
CONFIGCAT_PROVIDER_ID,
|
|
||||||
FLAGD_OFREP_PROVIDER_ID,
|
|
||||||
FLAGD_PROVIDER_ID,
|
FLAGD_PROVIDER_ID,
|
||||||
FLAGSMITH_PROVIDER_ID,
|
FLAGSMITH_PROVIDER_ID,
|
||||||
FLIPT_PROVIDER_ID,
|
|
||||||
GO_OFREP_PROVIDER_ID,
|
|
||||||
GO_PROVIDER_ID,
|
|
||||||
HARNESS_PROVIDER_ID,
|
HARNESS_PROVIDER_ID,
|
||||||
LD_PROVIDER_ID,
|
LD_PROVIDER_ID,
|
||||||
ProviderId,
|
ProviderId,
|
||||||
|
@ -21,7 +16,6 @@ import { HarnessWebProvider } from '@openfeature/web-harness-provider';
|
||||||
import { LaunchDarklyProvider } from '@openfeature/web-launchdarkly-provider';
|
import { LaunchDarklyProvider } from '@openfeature/web-launchdarkly-provider';
|
||||||
import { NOOP_PROVIDER, OpenFeature, Provider } from '@openfeature/web-sdk';
|
import { NOOP_PROVIDER, OpenFeature, Provider } from '@openfeature/web-sdk';
|
||||||
import { SplitWebProvider } from '@openfeature/web-split-provider';
|
import { SplitWebProvider } from '@openfeature/web-split-provider';
|
||||||
import { OFREPWebProvider } from '@openfeature/ofrep-web-provider';
|
|
||||||
import { TourProvider } from '@reactour/tour';
|
import { TourProvider } from '@reactour/tour';
|
||||||
import Ajv, { AnySchema, ErrorObject, ValidateFunction } from 'ajv';
|
import Ajv, { AnySchema, ErrorObject, ValidateFunction } from 'ajv';
|
||||||
import EventEmitter from 'eventemitter3';
|
import EventEmitter from 'eventemitter3';
|
||||||
|
@ -34,9 +28,6 @@ import { JsonEditor, JsonOutput } from './json-editor';
|
||||||
import { styledFib3rSteps } from './demos/fib3r/tour';
|
import { styledFib3rSteps } from './demos/fib3r/tour';
|
||||||
import { JSON_UPDATED } from './types';
|
import { JSON_UPDATED } from './types';
|
||||||
import { getData } from './utils';
|
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<
|
type ProviderMap = Record<
|
||||||
string,
|
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]: {
|
[HARNESS_PROVIDER_ID]: {
|
||||||
factory: () => {
|
factory: () => {
|
||||||
return new HarnessWebProvider(this.getProviderCredential(HARNESS_PROVIDER_ID), console);
|
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));
|
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);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
json: {},
|
json: {},
|
||||||
|
|
|
@ -30,5 +30,5 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tags": ["shared"]
|
"tags": []
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
export * from './lib/parse-valid-boolean';
|
export * from './lib/parse-valid-boolean';
|
||||||
export * from './lib/parse-valid-json-object';
|
export * from './lib/parse-valid-json-object';
|
||||||
export * from './lib/parse-valid-number';
|
export * from './lib/parse-valid-number';
|
||||||
|
export * from './lib/errors';
|
||||||
export * from './lib/types';
|
export * from './lib/types';
|
|
@ -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',
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { ErrorCode } from './codes';
|
||||||
|
|
||||||
|
export abstract class OpenFeatureError extends Error {
|
||||||
|
abstract code: ErrorCode;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
export * from './codes';
|
||||||
|
export * from './flag-not-found';
|
||||||
|
export * from './general';
|
||||||
|
export * from './parse';
|
||||||
|
export * from './type-mismatch';
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import { TypeMismatchError } from '@openfeature/core';
|
import { TypeMismatchError } from '@openfeature/js-sdk';
|
||||||
|
|
||||||
export const parseValidBoolean = (stringValue: string | undefined) => {
|
export const parseValidBoolean = (stringValue: string | undefined) => {
|
||||||
const asUnknown = stringValue as unknown;
|
const asUnknown = stringValue as unknown;
|
||||||
|
|
|
@ -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 => {
|
export const parseValidJsonObject = <T extends JsonValue>(stringValue: string): T => {
|
||||||
if (stringValue === undefined) {
|
if (stringValue === undefined) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ParseError, TypeMismatchError } from '@openfeature/core';
|
import { ParseError, TypeMismatchError } from '@openfeature/js-sdk';
|
||||||
|
|
||||||
export const parseValidNumber = (stringValue: string | undefined) => {
|
export const parseValidNumber = (stringValue: string | undefined) => {
|
||||||
if (stringValue === undefined) {
|
if (stringValue === undefined) {
|
||||||
|
|
|
@ -1,34 +1,25 @@
|
||||||
export const ENV_PROVIDER_ID = 'env';
|
export const ENV_PROVIDER_ID = 'env';
|
||||||
export const FLAGD_OFREP_PROVIDER_ID = 'flagd-ofrep';
|
|
||||||
export const FLAGD_PROVIDER_ID = 'flagd';
|
export const FLAGD_PROVIDER_ID = 'flagd';
|
||||||
export const GO_PROVIDER_ID = 'go-feature-flag';
|
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 LD_PROVIDER_ID = 'launchdarkly';
|
||||||
export const SPLIT_PROVIDER_ID = 'split';
|
export const SPLIT_PROVIDER_ID = 'split';
|
||||||
export const CB_PROVIDER_ID = 'cloudbees';
|
export const CB_PROVIDER_ID = 'cloudbees';
|
||||||
export const FLAGSMITH_PROVIDER_ID = 'flagsmith';
|
export const FLAGSMITH_PROVIDER_ID = 'flagsmith';
|
||||||
export const HARNESS_PROVIDER_ID = 'harness';
|
export const HARNESS_PROVIDER_ID = 'harness';
|
||||||
export const FLIPT_PROVIDER_ID = 'flipt';
|
|
||||||
export const CONFIGCAT_PROVIDER_ID = 'configcat';
|
|
||||||
|
|
||||||
export type ProviderId =
|
export type ProviderId =
|
||||||
| typeof ENV_PROVIDER_ID
|
| typeof ENV_PROVIDER_ID
|
||||||
| typeof FLAGD_PROVIDER_ID
|
| typeof FLAGD_PROVIDER_ID
|
||||||
| typeof FLAGD_OFREP_PROVIDER_ID
|
|
||||||
| typeof GO_PROVIDER_ID
|
| typeof GO_PROVIDER_ID
|
||||||
| typeof GO_OFREP_PROVIDER_ID
|
|
||||||
| typeof LD_PROVIDER_ID
|
| typeof LD_PROVIDER_ID
|
||||||
| typeof SPLIT_PROVIDER_ID
|
| typeof SPLIT_PROVIDER_ID
|
||||||
| typeof CB_PROVIDER_ID
|
| typeof CB_PROVIDER_ID
|
||||||
| typeof FLAGSMITH_PROVIDER_ID
|
| typeof FLAGSMITH_PROVIDER_ID
|
||||||
| typeof HARNESS_PROVIDER_ID
|
| typeof HARNESS_PROVIDER_ID;
|
||||||
| typeof FLIPT_PROVIDER_ID
|
|
||||||
| typeof CONFIGCAT_PROVIDER_ID;
|
|
||||||
|
|
||||||
export interface AvailableProvider {
|
export interface AvailableProvider {
|
||||||
id: ProviderId;
|
id: ProviderId;
|
||||||
webCredential?: string;
|
webCredential?: string;
|
||||||
url?: string;
|
|
||||||
host?: string;
|
host?: string;
|
||||||
tls?: boolean;
|
tls?: boolean;
|
||||||
port?: number;
|
port?: number;
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
import {parseValidJsonObject, parseValidNumber} from '@openfeature/utils';
|
import { parseValidJsonObject, parseValidNumber } from '@openfeature/utils';
|
||||||
import {
|
import {
|
||||||
EvaluationContext,
|
EvaluationContext,
|
||||||
|
OpenFeatureEventEmitter,
|
||||||
|
FlagValue,
|
||||||
Hook,
|
Hook,
|
||||||
JsonValue,
|
JsonValue,
|
||||||
Logger,
|
Logger,
|
||||||
OpenFeatureEventEmitter,
|
|
||||||
Provider,
|
Provider,
|
||||||
ProviderEvents,
|
ProviderEvents,
|
||||||
ProviderMetadata,
|
ProviderMetadata,
|
||||||
ProviderStatus,
|
|
||||||
ResolutionDetails,
|
ResolutionDetails,
|
||||||
TypeMismatchError,
|
TypeMismatchError,
|
||||||
|
ProviderStatus,
|
||||||
} from '@openfeature/web-sdk';
|
} from '@openfeature/web-sdk';
|
||||||
import {SplitFactory} from '@splitsoftware/splitio-browserjs';
|
import { SplitFactory } from '@splitsoftware/splitio-browserjs';
|
||||||
|
|
||||||
const ANONYMOUS = 'anonymous';
|
const ANONYMOUS = 'anonymous';
|
||||||
|
|
||||||
|
@ -57,7 +58,7 @@ export class SplitWebProvider implements Provider {
|
||||||
name: 'Split web provider',
|
name: 'Split web provider',
|
||||||
};
|
};
|
||||||
|
|
||||||
hooks?: Hook[] | undefined;
|
hooks?: Hook<FlagValue>[] | undefined;
|
||||||
|
|
||||||
async onContextChange?(oldContext: EvaluationContext, newContext: EvaluationContext): Promise<void> {
|
async onContextChange?(oldContext: EvaluationContext, newContext: EvaluationContext): Promise<void> {
|
||||||
if (oldContext.targetingKey !== newContext.targetingKey) {
|
if (oldContext.targetingKey !== newContext.targetingKey) {
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
"description": "Default preset for use with OpenFeature's repos",
|
"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,
|
"dependencyDashboard": true,
|
||||||
|
"prCreation": "not-pending",
|
||||||
|
"rebaseWhen": "behind-base-branch",
|
||||||
|
"platformAutomerge": true,
|
||||||
|
"platformCommit": true,
|
||||||
"npm": {
|
"npm": {
|
||||||
"packageRules": [
|
"packageRules": [
|
||||||
{
|
{
|
||||||
|
@ -13,10 +20,6 @@
|
||||||
"matchPackagePatterns": ["@opentelemtry/"],
|
"matchPackagePatterns": ["@opentelemtry/"],
|
||||||
"groupName": "OpenTelemetry"
|
"groupName": "OpenTelemetry"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"matchPackagePatterns": ["@openfeature/"],
|
|
||||||
"groupName": "OpenFeature"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"matchPackagePatterns": ["@typescript-eslint", "eslint"],
|
"matchPackagePatterns": ["@typescript-eslint", "eslint"],
|
||||||
"groupName": "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
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue