Skip to content

Commit dd57675

Browse files
authored
Merge branch 'main' into release-please--branches--main--components--flagd-web-provider
Signed-off-by: Todd Baert <[email protected]>
2 parents 02b39de + 80990b3 commit dd57675

17 files changed

+170
-69
lines changed

.release-please-manifest.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"libs/hooks/open-telemetry": "0.2.2",
3-
"libs/providers/go-feature-flag": "0.5.12",
4-
"libs/providers/flagd": "0.7.7",
3+
"libs/providers/go-feature-flag": "0.5.13",
4+
"libs/providers/flagd": "0.8.1",
55
"libs/providers/flagd-web": "0.3.5",
66
"libs/providers/env-var": "0.1.1",
77
"libs/providers/in-memory": "0.2.0",
8-
"libs/providers/config-cat": "0.2.0",
8+
"libs/providers/config-cat": "0.3.0",
99
"libs/providers/launchdarkly-client": "0.1.2"
1010
}

libs/providers/config-cat/CHANGELOG.md

+12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# Changelog
22

3+
## [0.3.0](https://github.com/open-feature/js-sdk-contrib/compare/config-cat-provider-v0.2.0...config-cat-provider-v0.3.0) (2023-07-27)
4+
5+
6+
### ⚠ BREAKING CHANGES
7+
8+
* remove configcat 7 peer dependency ([#435](https://github.com/open-feature/js-sdk-contrib/issues/435))
9+
10+
### 🐛 Bug Fixes
11+
12+
* **config-cat:** add status flag to provider ([#491](https://github.com/open-feature/js-sdk-contrib/issues/491)) ([f599c31](https://github.com/open-feature/js-sdk-contrib/commit/f599c3145881b81107c9a65b2c4cfe2a8b4111f1))
13+
* remove configcat 7 peer dependency ([#435](https://github.com/open-feature/js-sdk-contrib/issues/435)) ([da5d212](https://github.com/open-feature/js-sdk-contrib/commit/da5d21208e8929f7cdfc805e256cb892968bcd95))
14+
315
## [0.2.0](https://github.com/open-feature/js-sdk-contrib/compare/config-cat-provider-v0.1.1...config-cat-provider-v0.2.0) (2023-06-27)
416

517

libs/providers/config-cat/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@openfeature/config-cat-provider",
3-
"version": "0.2.0",
3+
"version": "0.3.0",
44
"type": "commonjs",
55
"scripts": {
66
"publish-if-not-exists": "cp $NPM_CONFIG_USERCONFIG .npmrc && if [ \"$(npm show $npm_package_name@$npm_package_version version)\" = \"$(npm run current-version -s)\" ]; then echo 'already published, skipping'; else npm publish --access public; fi",

libs/providers/config-cat/src/lib/config-cat-provider.spec.ts

+28-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ConfigCatProvider } from './config-cat-provider';
2-
import { ParseError, ProviderEvents, TypeMismatchError } from '@openfeature/js-sdk';
2+
import { ParseError, ProviderEvents, ProviderStatus, TypeMismatchError } from '@openfeature/js-sdk';
33
import {
44
createConsoleLogger,
55
createFlagOverridesFromMap,
@@ -42,8 +42,8 @@ describe('ConfigCatProvider', () => {
4242
configCatEmitter = (provider.configCatClient as any).options.hooks;
4343
});
4444

45-
afterAll(() => {
46-
provider.onClose();
45+
afterAll(async () => {
46+
await provider.onClose();
4747
});
4848

4949
it('should be an instance of ConfigCatProvider', () => {
@@ -69,6 +69,31 @@ describe('ConfigCatProvider', () => {
6969
expect(clientDisposeSpy).toHaveBeenCalled();
7070
});
7171

72+
describe('status', () => {
73+
it('should be NOT_READY before initialization and READY after successful initialization', async () => {
74+
const newProvider = ConfigCatProvider.create('key', PollingMode.ManualPoll, {
75+
logger: createConsoleLogger(LogLevel.Off),
76+
offline: true,
77+
});
78+
79+
expect(newProvider.status).toEqual(ProviderStatus.NOT_READY);
80+
await newProvider.initialize();
81+
expect(newProvider.status).toEqual(ProviderStatus.READY);
82+
});
83+
84+
it('should set status to ERROR if an error occurs', async () => {
85+
configCatEmitter.emit('clientError', 'Error');
86+
expect(provider.status).toEqual(ProviderStatus.ERROR);
87+
});
88+
89+
it('should set status back to READY if client switches back to ready after an error occured', async () => {
90+
configCatEmitter.emit('clientError', 'Error');
91+
expect(provider.status).toEqual(ProviderStatus.ERROR);
92+
configCatEmitter.emit('clientReady');
93+
expect(provider.status).toEqual(ProviderStatus.READY);
94+
});
95+
});
96+
7297
describe('events', () => {
7398
it('should emit PROVIDER_READY event', () => {
7499
const handler = jest.fn();

libs/providers/config-cat/src/lib/config-cat-provider.ts

+35-23
Original file line numberDiff line numberDiff line change
@@ -6,34 +6,40 @@ import {
66
ParseError,
77
Provider,
88
ProviderEvents,
9+
ProviderStatus,
910
ResolutionDetails,
1011
ResolutionReason,
1112
StandardResolutionReasons,
1213
TypeMismatchError,
1314
} from '@openfeature/js-sdk';
14-
import { getClient, IConfigCatClient, IEvaluationDetails, SettingValue } from 'configcat-js';
15+
import { getClient, IConfig, IConfigCatClient, IEvaluationDetails, SettingValue } from 'configcat-js';
1516
import { transformContext } from './context-transformer';
1617

1718
export class ConfigCatProvider implements Provider {
18-
private readonly clientParameters: Parameters<typeof getClient>;
1919
public readonly events = new OpenFeatureEventEmitter();
20-
private client?: IConfigCatClient;
20+
private _status: ProviderStatus = ProviderStatus.NOT_READY;
21+
private readonly _clientParameters: Parameters<typeof getClient>;
22+
private _client?: IConfigCatClient;
2123

2224
public metadata = {
2325
name: ConfigCatProvider.name,
2426
};
2527

2628
constructor(...params: Parameters<typeof getClient>) {
27-
this.clientParameters = params;
29+
this._clientParameters = params;
2830
}
2931

3032
public static create(...params: Parameters<typeof getClient>) {
3133
return new ConfigCatProvider(...params);
3234
}
3335

36+
get status() {
37+
return this._status;
38+
}
39+
3440
public async initialize(): Promise<void> {
3541
return new Promise((resolve) => {
36-
const originalParameters = this.clientParameters;
42+
const originalParameters = this._clientParameters;
3743
originalParameters[2] ??= {};
3844

3945
const options = originalParameters[2];
@@ -43,48 +49,54 @@ export class ConfigCatProvider implements Provider {
4349
oldSetupHooks?.(hooks);
4450

4551
// After resolving, once, we can simply emit events the next time
46-
hooks.once('clientReady', () => {
47-
hooks.on('clientReady', () => this.events.emit(ProviderEvents.Ready));
52+
const onProviderReady = () => {
4853
this.events.emit(ProviderEvents.Ready);
54+
this._status = ProviderStatus.READY;
55+
};
56+
57+
hooks.once('clientReady', () => {
58+
hooks.on('clientReady', onProviderReady);
59+
onProviderReady();
4960
resolve();
5061
});
5162

52-
hooks.on('configChanged', (projectConfig) =>
63+
hooks.on('configChanged', (projectConfig: IConfig | undefined) =>
5364
this.events.emit(ProviderEvents.ConfigurationChanged, {
54-
flagsChanged: Object.keys(projectConfig.settings),
65+
flagsChanged: projectConfig ? Object.keys(projectConfig.settings) : undefined,
5566
})
5667
);
5768

58-
hooks.on('clientError', (message: string, error) =>
69+
hooks.on('clientError', (message: string, error) => {
70+
this._status = ProviderStatus.ERROR;
5971
this.events.emit(ProviderEvents.Error, {
6072
message: message,
6173
metadata: error,
62-
})
63-
);
74+
});
75+
});
6476
};
6577

66-
this.client = getClient(...originalParameters);
78+
this._client = getClient(...originalParameters);
6779
});
6880
}
6981

7082
public get configCatClient() {
71-
return this.client;
83+
return this._client;
7284
}
7385

7486
public async onClose(): Promise<void> {
75-
await this.client?.dispose();
87+
await this._client?.dispose();
7688
}
7789

7890
async resolveBooleanEvaluation(
7991
flagKey: string,
8092
defaultValue: boolean,
8193
context: EvaluationContext
8294
): Promise<ResolutionDetails<boolean>> {
83-
if (!this.client) {
95+
if (!this._client) {
8496
throw new GeneralError('Provider is not initialized');
8597
}
8698

87-
const { value, ...evaluationData } = await this.client.getValueDetailsAsync<SettingValue>(
99+
const { value, ...evaluationData } = await this._client.getValueDetailsAsync<SettingValue>(
88100
flagKey,
89101
undefined,
90102
transformContext(context)
@@ -102,11 +114,11 @@ export class ConfigCatProvider implements Provider {
102114
defaultValue: string,
103115
context: EvaluationContext
104116
): Promise<ResolutionDetails<string>> {
105-
if (!this.client) {
117+
if (!this._client) {
106118
throw new GeneralError('Provider is not initialized');
107119
}
108120

109-
const { value, ...evaluationData } = await this.client.getValueDetailsAsync<SettingValue>(
121+
const { value, ...evaluationData } = await this._client.getValueDetailsAsync<SettingValue>(
110122
flagKey,
111123
undefined,
112124
transformContext(context)
@@ -124,11 +136,11 @@ export class ConfigCatProvider implements Provider {
124136
defaultValue: number,
125137
context: EvaluationContext
126138
): Promise<ResolutionDetails<number>> {
127-
if (!this.client) {
139+
if (!this._client) {
128140
throw new GeneralError('Provider is not initialized');
129141
}
130142

131-
const { value, ...evaluationData } = await this.client.getValueDetailsAsync<SettingValue>(
143+
const { value, ...evaluationData } = await this._client.getValueDetailsAsync<SettingValue>(
132144
flagKey,
133145
undefined,
134146
transformContext(context)
@@ -146,11 +158,11 @@ export class ConfigCatProvider implements Provider {
146158
defaultValue: U,
147159
context: EvaluationContext
148160
): Promise<ResolutionDetails<U>> {
149-
if (!this.client) {
161+
if (!this._client) {
150162
throw new GeneralError('Provider is not initialized');
151163
}
152164

153-
const { value, ...evaluationData } = await this.client.getValueDetailsAsync(
165+
const { value, ...evaluationData } = await this._client.getValueDetailsAsync(
154166
flagKey,
155167
undefined,
156168
transformContext(context)

libs/providers/flagd/CHANGELOG.md

+25
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,30 @@
11
# Changelog
22

3+
## [0.8.1](https://github.com/open-feature/js-sdk-contrib/compare/flagd-provider-v0.8.0...flagd-provider-v0.8.1) (2023-07-27)
4+
5+
6+
### 🐛 Bug Fixes
7+
8+
* issue with flagd not disconnecting ([#495](https://github.com/open-feature/js-sdk-contrib/issues/495)) ([ff61206](https://github.com/open-feature/js-sdk-contrib/commit/ff61206f7f51fd5ec30fc85ea2742c0933384330))
9+
10+
## [0.8.0](https://github.com/open-feature/js-sdk-contrib/compare/flagd-provider-v0.7.7...flagd-provider-v0.8.0) (2023-07-27)
11+
12+
13+
### ⚠ BREAKING CHANGES
14+
15+
* events, init, shutdown ([#484](https://github.com/open-feature/js-sdk-contrib/issues/484))
16+
* constructor arg order changed
17+
* 1.3.0 minimum js-sdk version
18+
19+
### ✨ New Features
20+
21+
* events, init, shutdown ([#484](https://github.com/open-feature/js-sdk-contrib/issues/484)) ([a73fc76](https://github.com/open-feature/js-sdk-contrib/commit/a73fc7670c66b2108cef8132a94433d75dea3622))
22+
23+
24+
### 🧹 Chore
25+
26+
* migrate buf ([#456](https://github.com/open-feature/js-sdk-contrib/issues/456)) ([8568af1](https://github.com/open-feature/js-sdk-contrib/commit/8568af1e26f92f4d0e9a942b9fc3e001d919ef03))
27+
328
## [0.7.7](https://github.com/open-feature/js-sdk-contrib/compare/flagd-provider-v0.7.6...flagd-provider-v0.7.7) (2023-07-03)
429

530

libs/providers/flagd/package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libs/providers/flagd/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@openfeature/flagd-provider",
3-
"version": "0.7.7",
3+
"version": "0.8.1",
44
"scripts": {
55
"publish-if-not-exists": "cp $NPM_CONFIG_USERCONFIG .npmrc && if [ \"$(npm show $npm_package_name@$npm_package_version version)\" = \"$(npm run current-version -s)\" ]; then echo 'already published, skipping'; else npm publish --access public; fi",
66
"current-version": "echo $npm_package_version"

libs/providers/flagd/src/lib/flagd-provider.spec.ts

+12-6
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,10 @@ describe(FlagdProvider.name, () => {
7171
callback({ type: EVENT_PROVIDER_READY });
7272
}
7373
}),
74-
destroy: jest.fn(),
74+
cancel: jest.fn(),
7575
};
7676
}),
77+
close: jest.fn(),
7778
resolveBoolean: jest.fn((request: ResolveBooleanRequest, callback: (error: ServiceError | null, response: ResolveBooleanResponse) => void) => {
7879
callback(null, {
7980
value: BOOLEAN_VALUE,
@@ -198,9 +199,10 @@ describe(FlagdProvider.name, () => {
198199
callback({ type: EVENT_PROVIDER_READY });
199200
}
200201
}),
201-
destroy: jest.fn(),
202+
cancel: jest.fn(),
202203
};
203204
}),
205+
close: jest.fn(),
204206
resolveBoolean: jest.fn((request: ResolveBooleanRequest, callback: (error: ServiceError | null, response: ResolveBooleanResponse) => void) => {
205207
callback(null, {
206208
variant: BOOLEAN_VARIANT,
@@ -312,14 +314,15 @@ describe(FlagdProvider.name, () => {
312314
registeredOnErrorCallback = callback;
313315
}
314316
}),
315-
destroy: jest.fn(),
317+
cancel: jest.fn(),
316318
};
317319

318320
// mock ServiceClient to inject
319321
const streamingServiceClientMock = {
320322
eventStream: jest.fn(() => {
321323
return streamMock;
322324
}),
325+
close: jest.fn(),
323326
resolveBoolean: jest.fn((req: ResolveBooleanRequest, callback: (error: ServiceError | null, response: ResolveBooleanResponse) => void) => {
324327
const response = {
325328
variant: BOOLEAN_VARIANT,
@@ -608,9 +611,10 @@ describe(FlagdProvider.name, () => {
608611
callback({ type: EVENT_PROVIDER_READY });
609612
}
610613
}),
611-
destroy: jest.fn(),
614+
cancel: jest.fn(),
612615
};
613616
}),
617+
close: jest.fn(),
614618
resolveBoolean: jest.fn((request: ResolveBooleanRequest, callback: (error: ServiceError | null, response: ResolveBooleanResponse) => void) => {
615619
callback({ code: status.DATA_LOSS, details } as ServiceError, {} as ResolveBooleanResponse);
616620
}),
@@ -692,6 +696,7 @@ describe(FlagdProvider.name, () => {
692696
});
693697

694698
describe('shutdown', () => {
699+
const cancelMock = jest.fn();
695700
const closeMock = jest.fn();
696701

697702
// mock ServiceClient to inject
@@ -703,10 +708,10 @@ describe(FlagdProvider.name, () => {
703708
callback({ type: EVENT_PROVIDER_READY });
704709
}
705710
}),
706-
destroy: closeMock,
711+
cancel: cancelMock,
707712
};
708713
}),
709-
714+
close: closeMock,
710715
} as unknown as ServiceClient;
711716

712717
beforeEach(() => {
@@ -718,6 +723,7 @@ describe(FlagdProvider.name, () => {
718723
describe(FlagdProvider.prototype.onClose.name, () => {
719724
it('should call service disconnect', async () => {
720725
await OpenFeature.close();
726+
expect(cancelMock).toHaveBeenCalled();
721727
expect(closeMock).toHaveBeenCalled();
722728
});
723729
});

libs/providers/flagd/src/lib/flagd-provider.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class FlagdProvider implements Provider {
3838
*/
3939
constructor(
4040
options?: FlagdProviderOptions,
41-
private logger?: Logger,
41+
private readonly logger?: Logger,
4242
service?: Service,
4343
) {
4444
this._service = service ? service : new GRPCService(getConfig(options), undefined, logger);

0 commit comments

Comments
 (0)