From a0147850014171afe46ca597fdb40ec982f5fe3f Mon Sep 17 00:00:00 2001 From: Luiz Carvalho Date: Thu, 5 Sep 2024 15:18:36 -0300 Subject: [PATCH 01/12] #201 (feat): added envId to the storage key and added property to cacheOptions to customize the key --- flagsmith-core.ts | 20 ++++++++++++------- test/cache.test.ts | 36 ++++++++++++++++++++++++----------- test/default-flags.test.ts | 4 ++-- test/react.test.tsx | 39 ++++++++++++++++++++++++++++++++++++-- test/test-constants.ts | 2 +- types.d.ts | 1 + 6 files changed, 79 insertions(+), 23 deletions(-) diff --git a/flagsmith-core.ts b/flagsmith-core.ts index 5b93816..17fe8ef 100644 --- a/flagsmith-core.ts +++ b/flagsmith-core.ts @@ -37,8 +37,10 @@ type RequestOptions = { } let AsyncStorage: AsyncStorageType = null; -const FLAGSMITH_KEY = "BULLET_TRAIN_DB"; -const FLAGSMITH_EVENT = "BULLET_TRAIN_EVENT"; +const DEFAULT_FLAGSMITH_KEY = "BULLET_TRAIN_DB"; +const DEFAULT_FLAGSMITH_EVENT = "BULLET_TRAIN_EVENT"; +let FlagsmithKey = DEFAULT_FLAGSMITH_KEY; +let FlagsmithEvent = DEFAULT_FLAGSMITH_EVENT; const defaultAPI = 'https://edge.api.flagsmith.com/api/v1/'; let eventSource: typeof EventSource; const initError = function(caller: string) { @@ -320,6 +322,10 @@ const Flagsmith = class { this.ticks = 10000; this.timer = this.enableLogs ? new Date().valueOf() : null; this.cacheFlags = typeof AsyncStorage !== 'undefined' && !!cacheFlags; + + FlagsmithKey = cacheOptions?.storageKey || DEFAULT_FLAGSMITH_KEY + "_" + environmentID; + FlagsmithEvent = DEFAULT_FLAGSMITH_EVENT + "_" + environmentID; + if (_AsyncStorage) { AsyncStorage = _AsyncStorage; } @@ -360,7 +366,7 @@ const Flagsmith = class { } if (AsyncStorage && this.canUseStorage) { - AsyncStorage.getItem(FLAGSMITH_EVENT) + AsyncStorage.getItem(FlagsmithEvent) .then((res)=>{ try { this.evaluationEvent = JSON.parse(res!) || {} @@ -377,7 +383,7 @@ const Flagsmith = class { } if (AsyncStorage && this.canUseStorage) { - AsyncStorage.getItem(FLAGSMITH_EVENT, (err, res) => { + AsyncStorage.getItem(FlagsmithEvent, (err, res) => { if (res) { const json = JSON.parse(res); if (json[this.environmentID]) { @@ -469,7 +475,7 @@ const Flagsmith = class { } }; try { - const res = AsyncStorage.getItemSync? AsyncStorage.getItemSync(FLAGSMITH_KEY) : await AsyncStorage.getItem(FLAGSMITH_KEY); + const res = AsyncStorage.getItemSync? AsyncStorage.getItemSync(FlagsmithKey) : await AsyncStorage.getItem(FlagsmithKey); await onRetrievedStorage(null, res) } catch (e) {} } @@ -685,7 +691,7 @@ const Flagsmith = class { this.ts = new Date().valueOf(); const state = JSON.stringify(this.getState()); this.log('Setting storage', state); - AsyncStorage!.setItem(FLAGSMITH_KEY, state); + AsyncStorage!.setItem(FlagsmithKey, state); } } @@ -749,7 +755,7 @@ const Flagsmith = class { private updateEventStorage() { if (this.enableAnalytics) { const events = JSON.stringify(this.getState().evaluationEvent); - AsyncStorage!.setItem(FLAGSMITH_EVENT, events); + AsyncStorage!.setItem(FlagsmithEvent, events); } } diff --git a/test/cache.test.ts b/test/cache.test.ts index 2acdcb7..f50daaf 100644 --- a/test/cache.test.ts +++ b/test/cache.test.ts @@ -1,7 +1,7 @@ // Sample test import { defaultState, - defaultStateAlt, + defaultStateAlt, FLAGSMITH_KEY, getFlagsmith, getStateToCheck, identityState, @@ -32,7 +32,21 @@ describe('Cache', () => { onChange, }); await flagsmith.init(initConfig); - const cache = await AsyncStorage.getItem('BULLET_TRAIN_DB'); + const cache = await AsyncStorage.getItem(FLAGSMITH_KEY); + expect(getStateToCheck(JSON.parse(`${cache}`))).toEqual(defaultState); + }); + test('should set cache after init with custom key', async () => { + const onChange = jest.fn(); + const customKey = 'custom_key'; + const { flagsmith, initConfig, AsyncStorage, mockFetch } = getFlagsmith({ + cacheFlags: true, + cacheOptions: { + storageKey: customKey, + }, + onChange, + }); + await flagsmith.init(initConfig); + const cache = await AsyncStorage.getItem(customKey); expect(getStateToCheck(JSON.parse(`${cache}`))).toEqual(defaultState); }); test('should call onChange with cache then eventually with an API response', async () => { @@ -52,7 +66,7 @@ describe('Cache', () => { cacheFlags: true, onChange, }); - await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify(defaultStateAlt)); + await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify(defaultStateAlt)); await flagsmith.init(initConfig); // Flags retrieved from cache @@ -85,7 +99,7 @@ describe('Cache', () => { identity: testIdentity, onChange, }); - await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({ + await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({ ...defaultStateAlt, identity: 'bad_identity', })); @@ -101,7 +115,7 @@ describe('Cache', () => { onChange, cacheOptions: { ttl: 1 }, }); - await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({ + await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({ ...defaultStateAlt, ts: new Date().valueOf() - 100, })); @@ -119,7 +133,7 @@ describe('Cache', () => { onChange, cacheOptions: { ttl: 1000 }, }); - await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({ + await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({ ...defaultStateAlt, ts: new Date().valueOf(), })); @@ -136,7 +150,7 @@ describe('Cache', () => { cacheFlags: false, onChange, }); - await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({ + await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({ ...defaultStateAlt, ts: new Date().valueOf(), })); @@ -154,7 +168,7 @@ describe('Cache', () => { onChange, cacheOptions: { ttl: 1000, skipAPI: true }, }); - await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({ + await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({ ...defaultStateAlt, ts: new Date().valueOf(), })); @@ -172,7 +186,7 @@ describe('Cache', () => { cacheFlags: true, preventFetch: true, }); - await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({ + await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({ ...defaultState, })); await flagsmith.init(initConfig); @@ -218,7 +232,7 @@ describe('Cache', () => { preventFetch: true, defaultFlags: defaultState.flags, }); - await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({ + await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({ ...defaultState, })); await flagsmith.init(initConfig); @@ -264,7 +278,7 @@ describe('Cache', () => { preventFetch: true, }); const storage = new SyncStorageMock(); - await storage.setItem('BULLET_TRAIN_DB', JSON.stringify({ + await storage.setItem(FLAGSMITH_KEY, JSON.stringify({ ...defaultState, })); flagsmith.init({ diff --git a/test/default-flags.test.ts b/test/default-flags.test.ts index 7c21407..a95548e 100644 --- a/test/default-flags.test.ts +++ b/test/default-flags.test.ts @@ -1,5 +1,5 @@ // Sample test -import { defaultState, defaultStateAlt, getFlagsmith, getStateToCheck } from './test-constants'; +import { defaultState, defaultStateAlt, FLAGSMITH_KEY, getFlagsmith, getStateToCheck } from './test-constants'; import { IFlags } from '../types'; describe('Default Flags', () => { @@ -51,7 +51,7 @@ describe('Default Flags', () => { cacheFlags: true, defaultFlags: {...defaultFlags, ...itemsToRemove}, }); - await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({ + await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({ ...defaultState, flags: { ...defaultFlags, diff --git a/test/react.test.tsx b/test/react.test.tsx index 3d7eba9..1139758 100644 --- a/test/react.test.tsx +++ b/test/react.test.tsx @@ -1,7 +1,13 @@ import React, { FC } from 'react'; import { render, screen, waitFor } from '@testing-library/react'; import { FlagsmithProvider, useFlags, useFlagsmithLoading } from '../lib/flagsmith/react'; -import { defaultState, environmentID, getFlagsmith, identityState, testIdentity } from './test-constants'; +import { + defaultState, + FLAGSMITH_KEY, + getFlagsmith, + identityState, + testIdentity, +} from './test-constants'; import removeIds from './test-utils/remove-ids'; const FlagsmithPage: FC = () => { const flags = useFlags(Object.keys(defaultState.flags)) @@ -18,6 +24,7 @@ const FlagsmithPage: FC = () => { ); }; + export default FlagsmithPage; describe('FlagsmithProvider', () => { it('renders without crashing', () => { @@ -84,7 +91,34 @@ describe('FlagsmithProvider', () => { preventFetch: true, defaultFlags: defaultState.flags }); - await AsyncStorage.setItem("BULLET_TRAIN_DB", JSON.stringify({ + await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({ + ...defaultState + }) ) + render( + + + + ); + + await waitFor(() => { + expect(JSON.parse(screen.getByTestId("loading-state").innerHTML)).toEqual({"isLoading":false,"isFetching":false,"error":null,"source":"CACHE"}); + expect(JSON.parse(screen.getByTestId("flags").innerHTML)).toEqual(removeIds(defaultState.flags)); + }); + }); + + it('renders cached flags by custom key', async () => { + const customKey = 'custom_key'; + const onChange = jest.fn(); + const { flagsmith, initConfig, AsyncStorage } = getFlagsmith({ + onChange, + cacheFlags: true, + preventFetch: true, + defaultFlags: defaultState.flags, + cacheOptions: { + storageKey: customKey, + }, + }); + await AsyncStorage.setItem(customKey, JSON.stringify({ ...defaultState }) ) render( @@ -98,6 +132,7 @@ describe('FlagsmithProvider', () => { expect(JSON.parse(screen.getByTestId("flags").innerHTML)).toEqual(removeIds(defaultState.flags)); }); }); + it('renders default flags', async () => { const onChange = jest.fn(); diff --git a/test/test-constants.ts b/test/test-constants.ts index 7ca936d..631996c 100644 --- a/test/test-constants.ts +++ b/test/test-constants.ts @@ -3,7 +3,7 @@ import MockAsyncStorage from './mocks/async-storage-mock'; import { createFlagsmithInstance } from '../lib/flagsmith'; import fetch from 'isomorphic-unfetch'; export const environmentID = 'QjgYur4LQTwe5HpvbvhpzK'; // Flagsmith Demo Projects - +export const FLAGSMITH_KEY = 'BULLET_TRAIN_DB' + "_" + environmentID; export const defaultState = { api: 'https://edge.api.flagsmith.com/api/v1/', environmentID, diff --git a/types.d.ts b/types.d.ts index 4b21f32..a71f44b 100644 --- a/types.d.ts +++ b/types.d.ts @@ -46,6 +46,7 @@ export interface IState { declare type ICacheOptions = { ttl?: number; skipAPI?: boolean; + storageKey?: string; }; export declare type IDatadogRum = { From 2082e52c5c0da7907dfc3c39a4cd1b41aa179e99 Mon Sep 17 00:00:00 2001 From: Luiz Carvalho Date: Mon, 9 Sep 2024 09:39:52 -0300 Subject: [PATCH 02/12] #201 (chore): rename BULLET_TRAIN to FLAGSMITH --- flagsmith-core.ts | 25 +++++++++++++++++++++++-- test/test-constants.ts | 2 +- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/flagsmith-core.ts b/flagsmith-core.ts index 17fe8ef..c4d7c79 100644 --- a/flagsmith-core.ts +++ b/flagsmith-core.ts @@ -37,8 +37,8 @@ type RequestOptions = { } let AsyncStorage: AsyncStorageType = null; -const DEFAULT_FLAGSMITH_KEY = "BULLET_TRAIN_DB"; -const DEFAULT_FLAGSMITH_EVENT = "BULLET_TRAIN_EVENT"; +const DEFAULT_FLAGSMITH_KEY = "FLAGSMITH_DB"; +const DEFAULT_FLAGSMITH_EVENT = "FLAGSMITH_EVENT"; let FlagsmithKey = DEFAULT_FLAGSMITH_KEY; let FlagsmithEvent = DEFAULT_FLAGSMITH_EVENT; const defaultAPI = 'https://edge.api.flagsmith.com/api/v1/'; @@ -399,6 +399,27 @@ const Flagsmith = class { } } + const migrateAsyncStorageCache = async () => { + try { + // Check if data exists under the old key using getItemSync or getItem + const oldData = AsyncStorage?.getItemSync ? + AsyncStorage.getItemSync(oldKey) : + await AsyncStorage?.getItem(oldKey); + + if (oldData) { + // Migrate the data to the new key + await AsyncStorage?.setItem(newKey, oldData); + + // Optionally, you can remove the old key after migration + await AsyncStorage?.removeItem(oldKey); + + console.log(`Cache migrated from '${oldKey}' to '${newKey}'.`); + } + } catch (error) { + console.error(`Failed to migrate cache from '${oldKey}' to '${newKey}':`, error); + } + } + //If the user specified default flags emit a changed event immediately if (cacheFlags) { if (AsyncStorage && this.canUseStorage) { diff --git a/test/test-constants.ts b/test/test-constants.ts index 631996c..1b19357 100644 --- a/test/test-constants.ts +++ b/test/test-constants.ts @@ -3,7 +3,7 @@ import MockAsyncStorage from './mocks/async-storage-mock'; import { createFlagsmithInstance } from '../lib/flagsmith'; import fetch from 'isomorphic-unfetch'; export const environmentID = 'QjgYur4LQTwe5HpvbvhpzK'; // Flagsmith Demo Projects -export const FLAGSMITH_KEY = 'BULLET_TRAIN_DB' + "_" + environmentID; +export const FLAGSMITH_KEY = 'FLAGSMITH_DB' + "_" + environmentID; export const defaultState = { api: 'https://edge.api.flagsmith.com/api/v1/', environmentID, From 2254f7cc05106dd9bcb7a58b4584885301db0368 Mon Sep 17 00:00:00 2001 From: Luiz Carvalho Date: Tue, 10 Sep 2024 12:32:55 -0300 Subject: [PATCH 03/12] #201 (chore): removed unused code --- flagsmith-core.ts | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/flagsmith-core.ts b/flagsmith-core.ts index c4d7c79..2e99e33 100644 --- a/flagsmith-core.ts +++ b/flagsmith-core.ts @@ -399,27 +399,6 @@ const Flagsmith = class { } } - const migrateAsyncStorageCache = async () => { - try { - // Check if data exists under the old key using getItemSync or getItem - const oldData = AsyncStorage?.getItemSync ? - AsyncStorage.getItemSync(oldKey) : - await AsyncStorage?.getItem(oldKey); - - if (oldData) { - // Migrate the data to the new key - await AsyncStorage?.setItem(newKey, oldData); - - // Optionally, you can remove the old key after migration - await AsyncStorage?.removeItem(oldKey); - - console.log(`Cache migrated from '${oldKey}' to '${newKey}'.`); - } - } catch (error) { - console.error(`Failed to migrate cache from '${oldKey}' to '${newKey}':`, error); - } - } - //If the user specified default flags emit a changed event immediately if (cacheFlags) { if (AsyncStorage && this.canUseStorage) { From e1582c76def8d7fbedd0446be3fe6700f4e51cca Mon Sep 17 00:00:00 2001 From: Luiz Carvalho Date: Thu, 12 Sep 2024 18:26:54 -0300 Subject: [PATCH 04/12] #201 (fix): new tests --- test/cache.test.ts | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/test/cache.test.ts b/test/cache.test.ts index 98b4030..b4e3fa2 100644 --- a/test/cache.test.ts +++ b/test/cache.test.ts @@ -1,7 +1,8 @@ // Sample test import { defaultState, - defaultStateAlt, FLAGSMITH_KEY, + defaultStateAlt, + FLAGSMITH_KEY, getFlagsmith, getStateToCheck, identityState, @@ -179,24 +180,7 @@ describe('Cache', () => { ...defaultStateAlt, }); }); - test('should not get flags from API when skipAPI is set', async () => { - const onChange = jest.fn(); - const { flagsmith, initConfig, AsyncStorage, mockFetch } = getFlagsmith({ - cacheFlags: true, - onChange, - cacheOptions: { ttl: 1000, skipAPI: true }, - }); - await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({ - ...defaultStateAlt, - ts: new Date().valueOf(), - })); - await flagsmith.init(initConfig); - expect(onChange).toHaveBeenCalledTimes(1); - expect(mockFetch).toHaveBeenCalledTimes(0); - expect(getStateToCheck(flagsmith.getState())).toEqual({ - ...defaultStateAlt, - }); - }); + test('should validate flags are unchanged when fetched', async () => { const onChange = jest.fn(); const { flagsmith, initConfig, AsyncStorage, mockFetch } = getFlagsmith({ @@ -322,7 +306,7 @@ describe('Cache', () => { preventFetch: true, }); const storage = new SyncStorageMock(); - await storage.setItem('BULLET_TRAIN_DB', JSON.stringify({ + await storage.setItem(FLAGSMITH_KEY, JSON.stringify({ ...identityState, })); const ts = Date.now(); @@ -333,7 +317,7 @@ describe('Cache', () => { }); expect(flagsmith.getAllTraits()).toEqual({ ...identityState.traits, - ts - }) + ts, + }); }); }); From 560b5351e16ccdc63dd9fbb7d052eb441fb9ebd9 Mon Sep 17 00:00:00 2001 From: kyle-ssg Date: Tue, 17 Sep 2024 17:10:37 +0100 Subject: [PATCH 05/12] Bump version --- lib/flagsmith-es/package.json | 2 +- lib/flagsmith/package.json | 2 +- lib/react-native-flagsmith/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/flagsmith-es/package.json b/lib/flagsmith-es/package.json index f266326..fc00c89 100644 --- a/lib/flagsmith-es/package.json +++ b/lib/flagsmith-es/package.json @@ -1,6 +1,6 @@ { "name": "flagsmith-es", - "version": "4.1.2", + "version": "5.0.0", "description": "Feature flagging to support continuous development. This is an esm equivalent of the standard flagsmith npm module.", "main": "./index.js", "type": "module", diff --git a/lib/flagsmith/package.json b/lib/flagsmith/package.json index f198d95..68988d6 100644 --- a/lib/flagsmith/package.json +++ b/lib/flagsmith/package.json @@ -1,6 +1,6 @@ { "name": "flagsmith", - "version": "4.1.2", + "version": "5.0.0", "description": "Feature flagging to support continuous development", "main": "./index.js", "repository": { diff --git a/lib/react-native-flagsmith/package.json b/lib/react-native-flagsmith/package.json index 2e31925..bcbde83 100644 --- a/lib/react-native-flagsmith/package.json +++ b/lib/react-native-flagsmith/package.json @@ -1,6 +1,6 @@ { "name": "react-native-flagsmith", - "version": "4.1.2", + "version": "5.0.0", "description": "Feature flagging to support continuous development", "main": "./index.js", "repository": { From 328bae9125dc9a5126e2d1e47dd70044174045bc Mon Sep 17 00:00:00 2001 From: kyle-ssg Date: Tue, 17 Sep 2024 17:54:55 +0100 Subject: [PATCH 06/12] Fix test --- test/cache.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cache.test.ts b/test/cache.test.ts index d97bc81..c075c5c 100644 --- a/test/cache.test.ts +++ b/test/cache.test.ts @@ -134,7 +134,7 @@ describe('Cache', () => { onChange, cacheOptions: { ttl: 1, loadStale: true }, }); - await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({ + await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({ ...defaultStateAlt, ts: new Date().valueOf() - 100, })); From 79f7e5670ce21b02a9ac7d91252e862c9bc1787b Mon Sep 17 00:00:00 2001 From: kyle-ssg Date: Tue, 24 Sep 2024 10:06:26 +0100 Subject: [PATCH 07/12] Fix test --- test/cache.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cache.test.ts b/test/cache.test.ts index 1e74085..c5d65b2 100644 --- a/test/cache.test.ts +++ b/test/cache.test.ts @@ -205,7 +205,7 @@ describe('Cache', () => { onChange, cacheOptions: { ttl: 1, skipAPI: true, loadStale: true }, }); - await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({ + await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({ ...defaultStateAlt, ts: new Date().valueOf() - 100, })); From d4c88cb2b01024b5b99ec5f1d51458cc1d7ad472 Mon Sep 17 00:00:00 2001 From: kyle-ssg Date: Wed, 9 Oct 2024 10:04:45 +0100 Subject: [PATCH 08/12] Fix tests --- flagsmith-core.ts | 4 ++-- test/cache.test.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/flagsmith-core.ts b/flagsmith-core.ts index e58adcc..fe5ec01 100644 --- a/flagsmith-core.ts +++ b/flagsmith-core.ts @@ -348,8 +348,8 @@ const Flagsmith = class { this.timer = this.enableLogs ? new Date().valueOf() : null; this.cacheFlags = typeof AsyncStorage !== 'undefined' && !!cacheFlags; - FlagsmithKey = cacheOptions?.storageKey || DEFAULT_FLAGSMITH_KEY + "_" + environmentID; - FlagsmithEvent = DEFAULT_FLAGSMITH_EVENT + "_" + environmentID; + FlagsmithKey = cacheOptions?.storageKey || DEFAULT_FLAGSMITH_KEY + "_" + evaluationContext.environment.apiKey; + FlagsmithEvent = DEFAULT_FLAGSMITH_EVENT + "_" + evaluationContext.environment.apiKey; if (_AsyncStorage) { AsyncStorage = _AsyncStorage; diff --git a/test/cache.test.ts b/test/cache.test.ts index 0c2fb48..4bef6a7 100644 --- a/test/cache.test.ts +++ b/test/cache.test.ts @@ -206,7 +206,7 @@ describe('Cache', () => { onChange, cacheOptions: { ttl: 1, skipAPI: true, loadStale: true }, }); - await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({ + await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({ ...defaultStateAlt, ts: new Date().valueOf() - 100, })); From 2c72ff4f904f8167d91fd5971fafab1a15c2b7d1 Mon Sep 17 00:00:00 2001 From: kyle-ssg Date: Wed, 9 Oct 2024 10:08:28 +0100 Subject: [PATCH 09/12] Fix tests --- test/cache.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/test/cache.test.ts b/test/cache.test.ts index 4bef6a7..cb70e15 100644 --- a/test/cache.test.ts +++ b/test/cache.test.ts @@ -1,4 +1,3 @@ -// Sample test import { defaultState, defaultStateAlt, From 731053ac2c0c08672d6c7b8e735084637dfb32ca Mon Sep 17 00:00:00 2001 From: kyle-ssg Date: Wed, 9 Oct 2024 10:24:21 +0100 Subject: [PATCH 10/12] bump versions --- lib/flagsmith-es/package.json | 2 +- lib/flagsmith/package.json | 2 +- lib/react-native-flagsmith/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/flagsmith-es/package.json b/lib/flagsmith-es/package.json index fc00c89..d295b30 100644 --- a/lib/flagsmith-es/package.json +++ b/lib/flagsmith-es/package.json @@ -1,6 +1,6 @@ { "name": "flagsmith-es", - "version": "5.0.0", + "version": "6.0.0", "description": "Feature flagging to support continuous development. This is an esm equivalent of the standard flagsmith npm module.", "main": "./index.js", "type": "module", diff --git a/lib/flagsmith/package.json b/lib/flagsmith/package.json index 68988d6..972d4f5 100644 --- a/lib/flagsmith/package.json +++ b/lib/flagsmith/package.json @@ -1,6 +1,6 @@ { "name": "flagsmith", - "version": "5.0.0", + "version": "6.0.0", "description": "Feature flagging to support continuous development", "main": "./index.js", "repository": { diff --git a/lib/react-native-flagsmith/package.json b/lib/react-native-flagsmith/package.json index bcbde83..06416c3 100644 --- a/lib/react-native-flagsmith/package.json +++ b/lib/react-native-flagsmith/package.json @@ -1,6 +1,6 @@ { "name": "react-native-flagsmith", - "version": "5.0.0", + "version": "6.0.0", "description": "Feature flagging to support continuous development", "main": "./index.js", "repository": { From 1b3f13c8c91c663cedd7f0b5f32c906156a1a3c0 Mon Sep 17 00:00:00 2001 From: kyle-ssg Date: Wed, 9 Oct 2024 10:28:42 +0100 Subject: [PATCH 11/12] neaten --- flagsmith-core.ts | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/flagsmith-core.ts b/flagsmith-core.ts index fe5ec01..25eefbd 100644 --- a/flagsmith-core.ts +++ b/flagsmith-core.ts @@ -43,7 +43,6 @@ type RequestOptions = { let AsyncStorage: AsyncStorageType = null; const DEFAULT_FLAGSMITH_KEY = "FLAGSMITH_DB"; const DEFAULT_FLAGSMITH_EVENT = "FLAGSMITH_EVENT"; -let FlagsmithKey = DEFAULT_FLAGSMITH_KEY; let FlagsmithEvent = DEFAULT_FLAGSMITH_EVENT; const defaultAPI = 'https://edge.api.flagsmith.com/api/v1/'; let eventSource: typeof EventSource; @@ -82,7 +81,7 @@ const Flagsmith = class { } getFlags = () => { - let { api, evaluationContext } = this; + const { api, evaluationContext } = this; this.log("Get Flags") this.isLoading = true; @@ -273,7 +272,7 @@ const Flagsmith = class { timer: number|null= null dtrum= null withTraits?: ITraits|null= null - cacheOptions = {ttl:0, skipAPI: false, loadStale: false} + cacheOptions = {ttl:0, skipAPI: false, loadStale: false, storageKey: undefined as string|undefined} async init(config: IInitConfig) { const evaluationContext = toEvaluationContext(config.evaluationContext || {}); try { @@ -292,7 +291,7 @@ const Flagsmith = class { enableDynatrace, enableAnalytics, realtime, - eventSourceUrl= "https://realtime.flagsmith.com/", + eventSourceUrl= "https://realtime.flagsmith.com/", AsyncStorage: _AsyncStorage, identity, traits, @@ -333,7 +332,7 @@ const Flagsmith = class { onError?.(message); }; this.enableLogs = enableLogs || false; - this.cacheOptions = cacheOptions ? { skipAPI: !!cacheOptions.skipAPI, ttl: cacheOptions.ttl || 0, loadStale: !!cacheOptions.loadStale } : this.cacheOptions; + this.cacheOptions = cacheOptions ? { skipAPI: !!cacheOptions.skipAPI, ttl: cacheOptions.ttl || 0, storageKey:cacheOptions.storageKey, loadStale: !!cacheOptions.loadStale } : this.cacheOptions; if (!this.cacheOptions.ttl && this.cacheOptions.skipAPI) { console.warn("Flagsmith: you have set a cache ttl of 0 and are skipping API calls, this means the API will not be hit unless you clear local storage.") } @@ -348,7 +347,6 @@ const Flagsmith = class { this.timer = this.enableLogs ? new Date().valueOf() : null; this.cacheFlags = typeof AsyncStorage !== 'undefined' && !!cacheFlags; - FlagsmithKey = cacheOptions?.storageKey || DEFAULT_FLAGSMITH_KEY + "_" + evaluationContext.environment.apiKey; FlagsmithEvent = DEFAULT_FLAGSMITH_EVENT + "_" + evaluationContext.environment.apiKey; if (_AsyncStorage) { @@ -408,8 +406,8 @@ const Flagsmith = class { if (res && this.evaluationContext.environment) { const json = JSON.parse(res); if (json[this.evaluationContext.environment.apiKey]) { - const state = this.getState(); - this.log("Retrieved events from cache", res); + const state = this.getState(); + this.log("Retrieved events from cache", res); this.setState({ ...state, evaluationEvent: json[this.evaluationContext.environment.apiKey], @@ -459,7 +457,7 @@ const Flagsmith = class { ...json, evaluationContext: toEvaluationContext({ ...json.evaluationContext, - identity: !!json.evaluationContext?.identity ? { + identity: json.evaluationContext?.identity ? { ...json.evaluationContext?.identity, traits: { ...json.evaluationContext?.identity?.traits || {}, @@ -516,7 +514,7 @@ const Flagsmith = class { } }; try { - const res = AsyncStorage.getItemSync? AsyncStorage.getItemSync(FlagsmithKey) : await AsyncStorage.getItem(FlagsmithKey); + const res = AsyncStorage.getItemSync? AsyncStorage.getItemSync(this.getStorageKey()) : await AsyncStorage.getItem(this.getStorageKey()); await onRetrievedStorage(null, res) } catch (e) {} } @@ -544,15 +542,6 @@ const Flagsmith = class { } } - private _loadedState(error: any = null, source: FlagSource, isFetching = false) { - return { - error, - isFetching, - isLoading: false, - source - } - } - getAllFlags() { return this.flags; } @@ -596,7 +585,7 @@ const Flagsmith = class { this.api = state.api || this.api || defaultAPI; this.flags = state.flags || this.flags; this.evaluationContext = state.evaluationContext || this.evaluationContext, - this.evaluationEvent = state.evaluationEvent || this.evaluationEvent; + this.evaluationEvent = state.evaluationEvent || this.evaluationEvent; this.log("setState called", this) } } @@ -666,7 +655,7 @@ const Flagsmith = class { } setContext = (clientEvaluationContext: ClientEvaluationContext) => { - let evaluationContext = toEvaluationContext(clientEvaluationContext); + const evaluationContext = toEvaluationContext(clientEvaluationContext); this.evaluationContext = { ...evaluationContext, environment: evaluationContext.environment || this.evaluationContext.environment, @@ -751,6 +740,19 @@ const Flagsmith = class { return res; }; + private _loadedState(error: any = null, source: FlagSource, isFetching = false) { + return { + error, + isFetching, + isLoading: false, + source + } + } + + private getStorageKey = ()=> { + return this.cacheOptions?.storageKey || DEFAULT_FLAGSMITH_KEY + "_" + this.evaluationContext.environment?.apiKey + } + private log(...args: (unknown)[]) { if (this.enableLogs) { console.log.apply(this, ['FLAGSMITH:', new Date().valueOf() - (this.timer || 0), 'ms', ...args]); @@ -762,7 +764,7 @@ const Flagsmith = class { this.ts = new Date().valueOf(); const state = JSON.stringify(this.getState()); this.log('Setting storage', state); - AsyncStorage!.setItem(FlagsmithKey, state); + AsyncStorage!.setItem(this.getStorageKey(), state); } } From f4eaca3507843cc743cb26d3071c651da42b67fc Mon Sep 17 00:00:00 2001 From: kyle-ssg Date: Wed, 9 Oct 2024 13:33:25 +0100 Subject: [PATCH 12/12] formatting fix --- flagsmith-core.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flagsmith-core.ts b/flagsmith-core.ts index 25eefbd..f1381c6 100644 --- a/flagsmith-core.ts +++ b/flagsmith-core.ts @@ -585,7 +585,7 @@ const Flagsmith = class { this.api = state.api || this.api || defaultAPI; this.flags = state.flags || this.flags; this.evaluationContext = state.evaluationContext || this.evaluationContext, - this.evaluationEvent = state.evaluationEvent || this.evaluationEvent; + this.evaluationEvent = state.evaluationEvent || this.evaluationEvent; this.log("setState called", this) } }