Skip to content

Commit

Permalink
feat: add named provider metadata accessor (#715)
Browse files Browse the repository at this point in the history
## This PR

- adds an accessor for named provider metadata

### Related Issues

Fixes #714 

### Notes

The default metadata is returned if the name doesn't match a registered
provider.

This is another example where provider namespace would work well. It
doesn't make sense to call this "named client" since we are only
interested in the client.

---------

Signed-off-by: Michael Beemer <[email protected]>
Co-authored-by: Todd Baert <[email protected]>
  • Loading branch information
beeme1mr and toddbaert committed Jan 11, 2024
1 parent 5c0b1ef commit 2bce515
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 8 deletions.
22 changes: 19 additions & 3 deletions packages/client/test/open-feature.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ describe('OpenFeature', () => {
describe('Requirement 1.1.2.1', () => {
it('should throw because the provider is not intended for the client', () => {
const provider = mockProvider({ runsOn: 'server' });
expect(() => OpenFeature.setProvider(provider)).toThrowError(
"Provider 'mock-events-success' is intended for use on the server."
expect(() => OpenFeature.setProvider(provider)).toThrow(
"Provider 'mock-events-success' is intended for use on the server.",
);
});
it('should succeed because the provider is intended for the client', () => {
const provider = mockProvider({ runsOn: 'client' });
expect(() => OpenFeature.setProvider(provider)).not.toThrowError();
expect(() => OpenFeature.setProvider(provider)).not.toThrow();
});
});

Expand Down Expand Up @@ -132,6 +132,22 @@ describe('OpenFeature', () => {
OpenFeature.setProvider('client2', { ...provider1 });
expect(provider1.onClose).toHaveBeenCalledTimes(1);
});

it('should return the default provider metadata when passing an unregistered client name', async () => {
const mockProvider = { metadata: { name: 'test' } } as unknown as Provider;
OpenFeature.setProvider(mockProvider);
const metadata = OpenFeature.getProviderMetadata('unused');
expect(metadata.name === mockProvider.metadata.name).toBeTruthy();
});

it('should return the named provider metadata when passing a registered client name', async () => {
const mockProvider = { metadata: { name: 'mock' } } as unknown as Provider;
const mockNamedProvider = { metadata: { name: 'named-mock' } } as unknown as Provider;
OpenFeature.setProvider(mockProvider);
OpenFeature.setProvider('mocked', mockNamedProvider);
const metadata = OpenFeature.getProviderMetadata('mocked');
expect(metadata.name === mockNamedProvider.metadata.name).toBeTruthy();
});
});

describe('Requirement 1.1.4', () => {
Expand Down
22 changes: 19 additions & 3 deletions packages/server/test/open-feature.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ describe('OpenFeature', () => {
describe('Requirement 1.1.2.1', () => {
it('should throw because the provider is not intended for the server', () => {
const provider = mockProvider({ runsOn: 'client' });
expect(() => OpenFeature.setProvider(provider)).toThrowError(
"Provider 'mock-events-success' is intended for use on the client."
expect(() => OpenFeature.setProvider(provider)).toThrow(
"Provider 'mock-events-success' is intended for use on the client.",
);
});
it('should succeed because the provider is intended for the server', () => {
const provider = mockProvider({ runsOn: 'server' });
expect(() => OpenFeature.setProvider(provider)).not.toThrowError();
expect(() => OpenFeature.setProvider(provider)).not.toThrow();
});
});

Expand Down Expand Up @@ -132,6 +132,22 @@ describe('OpenFeature', () => {
OpenFeature.setProvider('client2', { ...provider1 });
expect(provider1.onClose).toHaveBeenCalledTimes(1);
});

it('should return the default provider metadata when passing an unregistered client name', async () => {
const mockProvider = { metadata: { name: 'test' } } as unknown as Provider;
OpenFeature.setProvider(mockProvider);
const metadata = OpenFeature.getProviderMetadata('unused');
expect(metadata.name === mockProvider.metadata.name).toBeTruthy();
});

it('should return the named provider metadata when passing a registered client name', async () => {
const mockProvider = { metadata: { name: 'mock' } } as unknown as Provider;
const mockNamedProvider = { metadata: { name: 'named-mock' } } as unknown as Provider;
OpenFeature.setProvider(mockProvider);
OpenFeature.setProvider('mocked', mockNamedProvider);
const metadata = OpenFeature.getProviderMetadata('mocked');
expect(metadata.name === mockNamedProvider.metadata.name).toBeTruthy();
});
});

describe('Requirement 1.1.4', () => {
Expand Down
14 changes: 12 additions & 2 deletions packages/shared/src/open-feature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,21 @@ export abstract class OpenFeatureCommonAPI<P extends CommonProvider = CommonProv
}

/**
* Get metadata about registered provider.
* Get metadata about the default provider.
* @returns {ProviderMetadata} Provider Metadata
*/
get providerMetadata(): ProviderMetadata {
return this._defaultProvider.metadata;
return this.getProviderMetadata();
}

/**
* Get metadata about a registered provider using the client name.
* An unbound or empty client name will return metadata from the default provider.
* @param {string} [clientName] The name to identify the client
* @returns {ProviderMetadata} Provider Metadata
*/
getProviderMetadata(clientName?: string): ProviderMetadata {
return this.getProviderForClient(clientName).metadata;
}

/**
Expand Down

0 comments on commit 2bce515

Please sign in to comment.