Skip to content

Commit 4dc7e01

Browse files
authored
Merge branch 'main' into update-flipt-web-underlying-sdk
2 parents 51da370 + 4180281 commit 4dc7e01

File tree

12 files changed

+158
-81
lines changed

12 files changed

+158
-81
lines changed

.release-please-manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"libs/providers/flagd": "0.13.3",
55
"libs/providers/flagd-web": "0.7.3",
66
"libs/providers/env-var": "0.3.1",
7-
"libs/providers/config-cat": "0.7.4",
7+
"libs/providers/config-cat": "0.7.5",
88
"libs/providers/launchdarkly-client": "0.3.2",
99
"libs/providers/go-feature-flag-web": "0.2.5",
1010
"libs/shared/flagd-core": "1.0.0",
@@ -17,7 +17,7 @@
1717
"libs/providers/multi-provider": "0.1.2",
1818
"libs/providers/multi-provider-web": "0.0.3",
1919
"libs/providers/growthbook-client": "0.1.2",
20-
"libs/providers/config-cat-web": "0.1.5",
20+
"libs/providers/config-cat-web": "0.1.6",
2121
"libs/shared/config-cat-core": "0.1.1",
2222
"libs/providers/unleash-web": "0.1.1",
2323
"libs/providers/growthbook": "0.1.2",

CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
#
44
# Managed by Peribolos: https://github.com/open-feature/community/blob/main/config/open-feature/sdk-javascript/workgroup.yaml
55
#
6-
* @open-feature/sdk-javascript-maintainers
6+
* @open-feature/sdk-javascript-maintainers @open-feature/maintainers

libs/providers/config-cat-web/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## [0.1.6](https://github.com/open-feature/js-sdk-contrib/compare/config-cat-web-provider-v0.1.5...config-cat-web-provider-v0.1.6) (2025-04-09)
4+
5+
6+
### 🐛 Bug Fixes
7+
8+
* **config-cat:** Rework error reporting ([#1242](https://github.com/open-feature/js-sdk-contrib/issues/1242)) ([0425619](https://github.com/open-feature/js-sdk-contrib/commit/04256197bf6e7da70afd4ac1c31bdaf55ce4b789))
9+
310
## [0.1.5](https://github.com/open-feature/js-sdk-contrib/compare/config-cat-web-provider-v0.1.4...config-cat-web-provider-v0.1.5) (2025-03-14)
411

512

libs/providers/config-cat-web/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libs/providers/config-cat-web/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@openfeature/config-cat-web-provider",
3-
"version": "0.1.5",
3+
"version": "0.1.6",
44
"license": "Apache-2.0",
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-web/src/lib/config-cat-web-provider.spec.ts

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
createConsoleLogger,
44
createFlagOverridesFromMap,
55
HookEvents,
6+
IConfigCatCache,
67
ISettingUnion,
78
LogLevel,
89
OverrideBehaviour,
@@ -81,30 +82,47 @@ describe('ConfigCatWebProvider', () => {
8182
});
8283
});
8384

84-
it('should emit PROVIDER_ERROR event', () => {
85-
const handler = jest.fn();
86-
const eventData: [string, unknown] = ['error', { error: 'error' }];
85+
it("should emit PROVIDER_READY event when underlying client is initialized after provider's initialize", async () => {
86+
const cacheValue = '253370761200000\nW/"12345678-90a"\n{"f":{"booleanTrue":{"t":0,"v":{"b":true}}}}';
87+
88+
const fakeSharedCache = new (class implements IConfigCatCache {
89+
private _value?: string;
90+
get(key: string) {
91+
return this._value;
92+
}
93+
set(key: string, value: string) {
94+
this._value = value;
95+
}
96+
})();
97+
98+
const provider = ConfigCatWebProvider.create('configcat-sdk-1/1234567890123456789012/1234567890123456789012', {
99+
cache: fakeSharedCache,
100+
logger: createConsoleLogger(LogLevel.Off),
101+
offline: true,
102+
maxInitWaitTimeSeconds: 1,
103+
});
87104

88-
provider.events.addHandler(ProviderEvents.Error, handler);
89-
configCatEmitter.emit('clientError', ...eventData);
105+
const readyHandler = jest.fn();
106+
provider.events.addHandler(ProviderEvents.Ready, readyHandler);
90107

91-
expect(handler).toHaveBeenCalledWith({
92-
message: eventData[0],
93-
metadata: eventData[1],
94-
});
95-
});
108+
try {
109+
await provider.initialize();
110+
} catch (err) {
111+
expect((err as Error).message).toContain('underlying ConfigCat client could not initialize');
112+
}
96113

97-
it('should emit PROVIDER_READY event after successful evaluation during ERROR condition', async () => {
98-
const errorHandler = jest.fn();
99-
provider.events.addHandler(ProviderEvents.Error, errorHandler);
114+
expect(readyHandler).toHaveBeenCalledTimes(0);
100115

101-
configCatEmitter.emit('clientError', 'error', { error: 'error' });
102-
expect(errorHandler).toHaveBeenCalled();
116+
fakeSharedCache.set('', cacheValue);
103117

104-
const readyHandler = jest.fn();
105-
provider.events.addHandler(ProviderEvents.Ready, readyHandler);
118+
// Make sure that the internal cache is refreshed.
119+
await provider.configCatClient?.forceRefreshAsync();
120+
121+
provider.resolveBooleanEvaluation('booleanTrue', false, { targetingKey });
122+
123+
// Wait a little while for the Ready event to be emitted.
124+
await new Promise((resolve) => setTimeout(resolve, 100));
106125

107-
await provider.resolveBooleanEvaluation('booleanTrue', false, { targetingKey });
108126
expect(readyHandler).toHaveBeenCalled();
109127
});
110128
});

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

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
transformContext,
2020
} from '@openfeature/config-cat-core';
2121
import {
22+
ClientCacheState,
2223
getClient,
2324
IConfig,
2425
IConfigCatClient,
@@ -30,7 +31,7 @@ import {
3031
export class ConfigCatWebProvider implements Provider {
3132
public readonly events = new OpenFeatureEventEmitter();
3233
private readonly _clientFactory: (provider: ConfigCatWebProvider) => IConfigCatClient;
33-
private _hasError = false;
34+
private _isProviderReady = false;
3435
private _client?: IConfigCatClient;
3536

3637
public runsOn: Paradigm = 'client';
@@ -53,19 +54,11 @@ export class ConfigCatWebProvider implements Provider {
5354
options.setupHooks = (hooks) => {
5455
oldSetupHooks?.(hooks);
5556

56-
hooks.on('configChanged', (projectConfig: IConfig | undefined) =>
57+
hooks.on('configChanged', (config: IConfig) =>
5758
provider.events.emit(ProviderEvents.ConfigurationChanged, {
58-
flagsChanged: projectConfig ? Object.keys(projectConfig.settings) : undefined,
59+
flagsChanged: Object.keys(config.settings),
5960
}),
6061
);
61-
62-
hooks.on('clientError', (message: string, error) => {
63-
provider._hasError = true;
64-
provider.events.emit(ProviderEvents.Error, {
65-
message: message,
66-
metadata: error,
67-
});
68-
});
6962
};
7063

7164
return getClient(sdkKey, PollingMode.AutoPoll, options);
@@ -74,8 +67,19 @@ export class ConfigCatWebProvider implements Provider {
7467

7568
public async initialize(): Promise<void> {
7669
const client = this._clientFactory(this);
77-
await client.waitForReady();
70+
const clientCacheState = await client.waitForReady();
7871
this._client = client;
72+
73+
if (clientCacheState !== ClientCacheState.NoFlagData) {
74+
this._isProviderReady = true;
75+
} else {
76+
// OpenFeature provider defines ready state like this: "The provider is ready to resolve flags."
77+
// However, ConfigCat client's behavior is different: in some cases ready state may be reached
78+
// even if the client's internal, in-memory cache hasn't been populated yet, that is,
79+
// the client is not able to evaluate feature flags yet. In such cases we throw an error to
80+
// prevent the provider from being set ready right away, and check for the ready state later.
81+
throw Error('The underlying ConfigCat client could not initialize within maxInitWaitTimeSeconds.');
82+
}
7983
}
8084

8185
public get configCatClient() {
@@ -137,13 +141,22 @@ export class ConfigCatWebProvider implements Provider {
137141

138142
const configCatDefaultValue = flagType !== 'object' ? (defaultValue as SettingValue) : JSON.stringify(defaultValue);
139143

140-
const { value, ...evaluationData } = this._client
141-
.snapshot()
142-
.getValueDetails(flagKey, configCatDefaultValue, transformContext(context));
144+
const snapshot = this._client.snapshot();
145+
146+
const { value, ...evaluationData } = snapshot.getValueDetails(
147+
flagKey,
148+
configCatDefaultValue,
149+
transformContext(context),
150+
);
151+
152+
if (!this._isProviderReady && snapshot.cacheState !== ClientCacheState.NoFlagData) {
153+
// Ideally, we would check ConfigCat client's initialization state in its "background" polling loop.
154+
// This is not possible at the moment, so as a workaround, we do the check on feature flag evaluation.
155+
// There are plans to improve this situation, so let's revise this
156+
// as soon as ConfigCat SDK implements the necessary event.
143157

144-
if (this._hasError && !evaluationData.errorMessage && !evaluationData.errorException) {
145-
this._hasError = false;
146-
this.events.emit(ProviderEvents.Ready);
158+
this._isProviderReady = true;
159+
setTimeout(() => this.events.emit(ProviderEvents.Ready), 0);
147160
}
148161

149162
if (evaluationData.isDefaultValue) {

libs/providers/config-cat/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## [0.7.5](https://github.com/open-feature/js-sdk-contrib/compare/config-cat-provider-v0.7.4...config-cat-provider-v0.7.5) (2025-04-09)
4+
5+
6+
### 🐛 Bug Fixes
7+
8+
* **config-cat:** Rework error reporting ([#1242](https://github.com/open-feature/js-sdk-contrib/issues/1242)) ([0425619](https://github.com/open-feature/js-sdk-contrib/commit/04256197bf6e7da70afd4ac1c31bdaf55ce4b789))
9+
310
## [0.7.4](https://github.com/open-feature/js-sdk-contrib/compare/config-cat-provider-v0.7.3...config-cat-provider-v0.7.4) (2025-03-14)
411

512

libs/providers/config-cat/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libs/providers/config-cat/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@openfeature/config-cat-provider",
3-
"version": "0.7.4",
3+
"version": "0.7.5",
44
"license": "Apache-2.0",
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",

0 commit comments

Comments
 (0)