Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions libs/providers/go-feature-flag/src/lib/controller/goff-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,32 @@ export class GoffApiController {
* @param defaultValue
* @param evaluationContext
* @param expectedType
* @param exporterMetadata
*/
async evaluate<T>(
flagKey: string,
defaultValue: T,
evaluationContext: EvaluationContext,
expectedType: string,
exporterMetadata: Record<string, ExporterMetadataValue> = {},
): Promise<{ resolutionDetails: ResolutionDetails<T>; isCacheable: boolean }> {
const goffEvaluationContext = transformContext(evaluationContext);

// build URL to access to the endpoint
const endpointURL = new URL(this.endpoint);
endpointURL.pathname = `v1/feature/${flagKey}/eval`;

if (goffEvaluationContext.custom === undefined) {
goffEvaluationContext.custom = {};
}
goffEvaluationContext.custom['gofeatureflag'] = {
exporterMetadata: {
openfeature: true,
provider: 'js',
...exporterMetadata,
},
};

const request: GoFeatureFlagProxyRequest<T> = {
evaluationContext: goffEvaluationContext,
defaultValue,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,39 @@ describe('GoFeatureFlagProvider', () => {
it('provider should be ready after after setting the provider to Open Feature', async () => {
expect(cli.providerStatus).toEqual(ServerProviderStatus.READY);
});

it('should send exporter metadata to the evaluation API', async () => {
const flagName = 'random-flag';
const targetingKey = 'user-key';
const dns = `${endpoint}v1/feature/${flagName}/eval`;
axiosMock.onPost(dns).reply(200, {
value: true,
variationType: 'trueVariation',
reason: StandardResolutionReasons.TARGETING_MATCH,
failed: false,
trackEvents: true,
version: '1.0.0',
} as GoFeatureFlagProxyResponse<boolean>);

const provider = new GoFeatureFlagProvider({
endpoint,
exporterMetadata: { key1: 'value', key2: 123, key3: 123.45 },
});
await OpenFeature.setProviderAndWait('test-exporter-metadata', provider);
const cli = OpenFeature.getClient('test-exporter-metadata');

await cli.getBooleanDetails(flagName, false, { targetingKey });
const request = axiosMock.history.post[0];
const want = {
openfeature: true,
provider: 'js',
key1: 'value',
key2: 123,
key3: 123.45,
};
const got = JSON.parse(request.data).evaluationContext.custom.gofeatureflag.exporterMetadata;
expect(got).toEqual(want);
});
});
describe('resolveBooleanEvaluation', () => {
it('should throw an error if we expect a boolean and got another type', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
ServerProviderEvents,
StandardResolutionReasons,
} from '@openfeature/server-sdk';
import { ConfigurationChange, GoFeatureFlagProviderOptions } from './model';
import { ConfigurationChange, ExporterMetadataValue, GoFeatureFlagProviderOptions } from './model';
import { GoFeatureFlagDataCollectorHook } from './data-collector-hook';
import { GoffApiController } from './controller/goff-api';
import { CacheController } from './controller/cache';
Expand All @@ -34,6 +34,7 @@ export class GoFeatureFlagProvider implements Provider {
private readonly _cacheController?: CacheController;
private _pollingIntervalId?: number;
private _pollingInterval: number;
private _exporterMetadata?: Record<string, ExporterMetadataValue>;

constructor(options: GoFeatureFlagProviderOptions, logger?: Logger) {
this._goffApiController = new GoffApiController(options);
Expand All @@ -46,6 +47,7 @@ export class GoFeatureFlagProvider implements Provider {
this._goffApiController,
logger,
);
this._exporterMetadata = options.exporterMetadata;
this._disableDataCollection = options.disableDataCollection || false;
this._cacheController = new CacheController(options, logger);
this._pollingInterval = options.pollInterval ?? this.DEFAULT_POLL_INTERVAL;
Expand Down Expand Up @@ -188,6 +190,7 @@ export class GoFeatureFlagProvider implements Provider {
defaultValue,
evaluationContext,
expectedType,
this._exporterMetadata ?? {},
);

this._cacheController?.set(flagKey, evaluationContext, evaluationResponse);
Expand Down