diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 9e75dbfab0..4115cafc02 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: registry-url: 'https://registry.npmjs.org' node-version: 16 diff --git a/.github/workflows/dco-merge-group.yml b/.github/workflows/dco-merge-group.yml new file mode 100644 index 0000000000..dbfaab9344 --- /dev/null +++ b/.github/workflows/dco-merge-group.yml @@ -0,0 +1,12 @@ +name: DCO +on: + merge_group: + +# Workaround because the DCO app doesn't run on a merge_group trigger +# https://github.com/dcoapp/app/pull/200 +jobs: + DCO: + runs-on: ubuntu-latest + if: ${{ github.actor != 'renovate[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" \ No newline at end of file diff --git a/.github/workflows/pr-checks.yaml b/.github/workflows/pr-checks.yaml index 4c4be1faf3..b46960a9ec 100644 --- a/.github/workflows/pr-checks.yaml +++ b/.github/workflows/pr-checks.yaml @@ -8,6 +8,7 @@ on: - reopened branches: - main + merge_group: jobs: build-test-lint: @@ -22,7 +23,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: 'npm' @@ -44,7 +45,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 16 cache: 'npm' @@ -69,7 +70,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: # we need 'fetch' for this test, which is only in 18 node-version: 18 diff --git a/.github/workflows/publish-experimental.yml b/.github/workflows/publish-experimental.yml index 57604caf53..7567c5d511 100644 --- a/.github/workflows/publish-experimental.yml +++ b/.github/workflows/publish-experimental.yml @@ -14,7 +14,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: registry-url: 'https://registry.npmjs.org' diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index e9ad5044bc..e17274b456 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -19,7 +19,7 @@ jobs: release_created: ${{ steps.release.outputs.releases_created }} npm-release: - needs: Release-please + needs: release-please runs-on: ubuntu-latest if: ${{ needs.release-please.outputs.release_created }} steps: @@ -27,7 +27,7 @@ jobs: - name: Checkout Repository uses: actions/checkout@v4 - name: Setup Node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 16 registry-url: "https://registry.npmjs.org" diff --git a/package-lock.json b/package-lock.json index e82730d778..c11fcd8c43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "packages/react" ], "devDependencies": { - "@openfeature/flagd-provider": "^0.8.1", + "@openfeature/flagd-provider": "^0.9.0", "@openfeature/flagd-web-provider": "^0.4.0", "@rollup/plugin-alias": "^5.0.0", "@rollup/plugin-typescript": "^11.0.0", @@ -27,7 +27,7 @@ "@typescript-eslint/parser": "^5.23.0", "esbuild": "^0.17.0", "eslint": "^8.14.0", - "eslint-config-prettier": "^8.5.0", + "eslint-config-prettier": "^9.0.0", "eslint-import-resolver-alias": "^1.1.2", "eslint-plugin-check-file": "^2.0.0", "eslint-plugin-import": "^2.26.0", @@ -1338,23 +1338,24 @@ } }, "node_modules/@openfeature/flagd-provider": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/@openfeature/flagd-provider/-/flagd-provider-0.8.3.tgz", - "integrity": "sha512-PWZO6QpybjoegYHE2EkeXXEvmCvmvD4LMwxsv0DW3YjU/mmQXVsfQxqr/KF5FnZ81/1zFutSy/QNNJ90u9+BDA==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@openfeature/flagd-provider/-/flagd-provider-0.9.0.tgz", + "integrity": "sha512-7x9Xkax6uo16GEFvK4OEzbgcavSrZqYzqTnIKysEs78XgRE6PROW1CIRZGjumwaY4E36A3ZEs5OeD9QBL6GAGg==", "dev": true, "dependencies": { "@protobuf-ts/runtime-rpc": "2.9.0", - "lru-cache": "10.0.0" + "lru-cache": "10.0.1", + "util": "0.12.5" }, "peerDependencies": { "@grpc/grpc-js": "^1.6.0", - "@openfeature/js-sdk": ">=1.3.0" + "@openfeature/server-sdk": ">=1.6.0" } }, "node_modules/@openfeature/flagd-provider/node_modules/lru-cache": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.0.tgz", - "integrity": "sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", + "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", "dev": true, "engines": { "node": "14 || >=16.14" @@ -1374,10 +1375,6 @@ "@openfeature/web-sdk": "^0.4.0" } }, - "node_modules/@openfeature/js-sdk": { - "resolved": "packages/server", - "link": true - }, "node_modules/@openfeature/react-sdk": { "resolved": "packages/react", "link": true @@ -1464,9 +1461,9 @@ "license": "BSD-3-Clause" }, "node_modules/@rollup/plugin-alias": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-alias/-/plugin-alias-5.0.0.tgz", - "integrity": "sha512-l9hY5chSCjuFRPsnRm16twWBiSApl2uYFLsepQYwtBuAxNMQ/1dJqADld40P0Jkqm65GRTLy/AC6hnpVebtLsA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-alias/-/plugin-alias-5.0.1.tgz", + "integrity": "sha512-JObvbWdOHoMy9W7SU0lvGhDtWq9PllP5mjpAy+TUslZG/WzOId9u80Hsqq1vCUn9pFJ0cxpdcnAv+QzU2zFH3Q==", "dev": true, "dependencies": { "slash": "^4.0.0" @@ -1475,7 +1472,7 @@ "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0" + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { @@ -1648,9 +1645,9 @@ "dev": true }, "node_modules/@types/events": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.1.tgz", - "integrity": "sha512-QfUFdKjGSc+iCf8OFZhqJKfDuqB6lP57kSMkPw8ba3yNDANicUwCdaPt5ytZ4nDXXVFxQkvT8v73I4stSVrCxA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.2.tgz", + "integrity": "sha512-v4Mr60wJuF069iZZCdY5DKhfj0l6eXNJtbSM/oMDNdRLoBEUsktmKnswkz0X3OAic5W8Qy/YU6owKE4A66Y46A==", "dev": true }, "node_modules/@types/glob": { @@ -1692,9 +1689,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.4", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.4.tgz", - "integrity": "sha512-PhglGmhWeD46FYOVLt3X7TiWjzwuVGW9wG/4qocPevXMjCmrIc5b6db9WjeGE4QYVpUAWMDv3v0IiBwObY289A==", + "version": "29.5.6", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.6.tgz", + "integrity": "sha512-/t9NnzkOpXb4Nfvg17ieHE6EeSjDS2SGSpNYfoLbUAeL/EOueU/RSdOWFpfQTXBEM7BguYW1XQ0EbM+6RlIh6w==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -1755,9 +1752,9 @@ "dev": true }, "node_modules/@types/react": { - "version": "18.2.21", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.21.tgz", - "integrity": "sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA==", + "version": "18.2.31", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.31.tgz", + "integrity": "sha512-c2UnPv548q+5DFh03y8lEDeMfDwBn9G3dRwfkrxQMo/dOtRHUUO57k6pHvBIfH/VF4Nh+98mZ5aaSe+2echD5g==", "dev": true, "dependencies": { "@types/prop-types": "*", @@ -3482,9 +3479,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", - "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", + "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" @@ -4797,6 +4794,22 @@ "node": ">=0.10.0" } }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-array-buffer": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", @@ -4993,6 +5006,21 @@ "node": ">=6" } }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "dev": true, @@ -12434,6 +12462,19 @@ "node": ">=0.10.0" } }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", diff --git a/package.json b/package.json index ab5b195089..289a0938cb 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "node": ">=16" }, "devDependencies": { - "@openfeature/flagd-provider": "^0.8.1", + "@openfeature/flagd-provider": "^0.9.0", "@openfeature/flagd-web-provider": "^0.4.0", "@rollup/plugin-alias": "^5.0.0", "@rollup/plugin-typescript": "^11.0.0", @@ -46,7 +46,7 @@ "@typescript-eslint/parser": "^5.23.0", "esbuild": "^0.17.0", "eslint": "^8.14.0", - "eslint-config-prettier": "^8.5.0", + "eslint-config-prettier": "^9.0.0", "eslint-import-resolver-alias": "^1.1.2", "eslint-plugin-check-file": "^2.0.0", "eslint-plugin-import": "^2.26.0", diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts index a45964d600..116336b6f7 100644 --- a/packages/server/src/index.ts +++ b/packages/server/src/index.ts @@ -2,4 +2,5 @@ export * from './client'; export * from './provider'; export * from './evaluation'; export * from './open-feature'; +export * from './transaction-context'; export * from '@openfeature/shared'; diff --git a/packages/server/src/open-feature.ts b/packages/server/src/open-feature.ts index fb6d88aa17..962bb20d17 100644 --- a/packages/server/src/open-feature.ts +++ b/packages/server/src/open-feature.ts @@ -6,6 +6,12 @@ import { objectOrUndefined, stringOrUndefined, } from '@openfeature/shared'; +import { + ManageTransactionContextPropagator, + NOOP_TRANSACTION_CONTEXT_PROPAGATOR, + TransactionContext, + TransactionContextPropagator, +} from './transaction-context'; import { Client, OpenFeatureClient } from './client'; // use a symbol as a key for the global singleton @@ -16,7 +22,11 @@ type OpenFeatureGlobal = { }; const _globalThis = globalThis as OpenFeatureGlobal; -export class OpenFeatureAPI extends OpenFeatureCommonAPI implements ManageContext { +export class OpenFeatureAPI + extends OpenFeatureCommonAPI + implements ManageContext, ManageTransactionContextPropagator> +{ + private _transactionContextPropagator: TransactionContextPropagator = NOOP_TRANSACTION_CONTEXT_PROPAGATOR; protected _defaultProvider: Provider = NOOP_PROVIDER; private constructor() { @@ -111,6 +121,39 @@ export class OpenFeatureAPI extends OpenFeatureCommonAPI implements Ma clearProviders(): Promise { return super.clearProvidersAndSetDefault(NOOP_PROVIDER); } + + setTransactionContextPropagator( + transactionContextPropagator: TransactionContextPropagator + ): OpenFeatureCommonAPI { + const baseMessage = 'Invalid TransactionContextPropagator, will not be set: '; + if (typeof transactionContextPropagator?.getTransactionContext !== 'function') { + this._logger.error(`${baseMessage}: getTransactionContext is not a function.`); + } else if (typeof transactionContextPropagator?.setTransactionContext !== 'function') { + this._logger.error(`${baseMessage}: setTransactionContext is not a function.`); + } else { + this._transactionContextPropagator = transactionContextPropagator; + } + return this; + } + + setTransactionContext( + transactionContext: TransactionContext, + callback: (...args: unknown[]) => R, + ...args: unknown[] + ): void { + this._transactionContextPropagator.setTransactionContext(transactionContext, callback, ...args); + } + + getTransactionContext(): TransactionContext { + try { + return this._transactionContextPropagator.getTransactionContext(); + } catch (err: unknown) { + const error = err as Error | undefined; + this._logger.error(`Error getting transaction context: ${error?.message}, returning empty context.`); + this._logger.error(error?.stack); + return {}; + } + } } /** diff --git a/packages/shared/src/transaction-context/index.ts b/packages/server/src/transaction-context/index.ts similarity index 100% rename from packages/shared/src/transaction-context/index.ts rename to packages/server/src/transaction-context/index.ts diff --git a/packages/shared/src/transaction-context/no-op-transaction-context-propagator.ts b/packages/server/src/transaction-context/no-op-transaction-context-propagator.ts similarity index 87% rename from packages/shared/src/transaction-context/no-op-transaction-context-propagator.ts rename to packages/server/src/transaction-context/no-op-transaction-context-propagator.ts index 13ee4ce9a1..0dbeaaa5bc 100644 --- a/packages/shared/src/transaction-context/no-op-transaction-context-propagator.ts +++ b/packages/server/src/transaction-context/no-op-transaction-context-propagator.ts @@ -1,4 +1,4 @@ -import { EvaluationContext } from '../evaluation'; +import { EvaluationContext } from '@openfeature/shared'; import { TransactionContextPropagator } from './transaction-context'; class NoopTransactionContextPropagator implements TransactionContextPropagator { diff --git a/packages/shared/src/transaction-context/transaction-context.ts b/packages/server/src/transaction-context/transaction-context.ts similarity index 97% rename from packages/shared/src/transaction-context/transaction-context.ts rename to packages/server/src/transaction-context/transaction-context.ts index 92c86800a1..d69c5f86ad 100644 --- a/packages/shared/src/transaction-context/transaction-context.ts +++ b/packages/server/src/transaction-context/transaction-context.ts @@ -1,4 +1,4 @@ -import { EvaluationContext } from '../evaluation'; +import { EvaluationContext } from '@openfeature/shared'; /** * Transaction context is a mechanism for adding transaction specific context that diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index a009632f7d..8a85f41420 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -6,6 +6,5 @@ export * from './events'; export * from './logger'; export * from './provider'; export * from './evaluation'; -export * from './transaction-context'; export * from './type-guards'; export * from './open-feature'; diff --git a/packages/shared/src/open-feature.ts b/packages/shared/src/open-feature.ts index ca3373216e..1f6f23eef4 100644 --- a/packages/shared/src/open-feature.ts +++ b/packages/shared/src/open-feature.ts @@ -6,24 +6,13 @@ import { isDefined } from './filter'; import { EvaluationLifeCycle, Hook } from './hooks'; import { DefaultLogger, Logger, ManageLogger, SafeLogger } from './logger'; import { CommonProvider, ProviderMetadata, ProviderStatus } from './provider'; -import { - ManageTransactionContextPropagator, - NOOP_TRANSACTION_CONTEXT_PROPAGATOR, - TransactionContext, - TransactionContextPropagator, -} from './transaction-context'; import { objectOrUndefined, stringOrUndefined } from './type-guards'; import { Paradigm } from './types'; export abstract class OpenFeatureCommonAPI

- implements - Eventing, - EvaluationLifeCycle>, - ManageLogger>, - ManageTransactionContextPropagator> + implements Eventing, EvaluationLifeCycle>, ManageLogger> { protected _hooks: Hook[] = []; - protected _transactionContextPropagator: TransactionContextPropagator = NOOP_TRANSACTION_CONTEXT_PROPAGATOR; protected _context: EvaluationContext = {}; protected _logger: Logger = new DefaultLogger(); @@ -350,35 +339,4 @@ export abstract class OpenFeatureCommonAPI

{ - const baseMessage = 'Invalid TransactionContextPropagator, will not be set: '; - if (typeof transactionContextPropagator?.getTransactionContext !== 'function') { - this._logger.error(`${baseMessage}: getTransactionContext is not a function.`); - } else if (typeof transactionContextPropagator?.setTransactionContext !== 'function') { - this._logger.error(`${baseMessage}: setTransactionContext is not a function.`); - } else { - this._transactionContextPropagator = transactionContextPropagator; - } - return this; - } - - setTransactionContext( - transactionContext: TransactionContext, - callback: (...args: unknown[]) => R, - ...args: unknown[] - ): void { - this._transactionContextPropagator.setTransactionContext(transactionContext, callback, ...args); - } - - getTransactionContext(): TransactionContext { - try { - return this._transactionContextPropagator.getTransactionContext(); - } catch (err: unknown) { - const error = err as Error | undefined; - this._logger.error(`Error getting transaction context: ${error?.message}, returning empty context.`); - this._logger.error(error?.stack); - return {}; - } - } } diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json index 04772c62ab..624fa2800e 100644 --- a/packages/shared/tsconfig.json +++ b/packages/shared/tsconfig.json @@ -103,4 +103,4 @@ "node_modules", "**/*.test.js" ] -} \ No newline at end of file +}