@metamask-previews/remote-feature-flag-controller 1.9.1-preview-9fa15fd0 → 2.0.0-preview-46d2c977
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/remote-feature-flag-controller-types.cjs.map +1 -1
- package/dist/remote-feature-flag-controller-types.d.cts +0 -13
- package/dist/remote-feature-flag-controller-types.d.cts.map +1 -1
- package/dist/remote-feature-flag-controller-types.d.mts +0 -13
- package/dist/remote-feature-flag-controller-types.d.mts.map +1 -1
- package/dist/remote-feature-flag-controller-types.mjs.map +1 -1
- package/dist/remote-feature-flag-controller.cjs +5 -5
- package/dist/remote-feature-flag-controller.cjs.map +1 -1
- package/dist/remote-feature-flag-controller.d.cts +5 -6
- package/dist/remote-feature-flag-controller.d.cts.map +1 -1
- package/dist/remote-feature-flag-controller.d.mts +5 -6
- package/dist/remote-feature-flag-controller.d.mts.map +1 -1
- package/dist/remote-feature-flag-controller.mjs +3 -3
- package/dist/remote-feature-flag-controller.mjs.map +1 -1
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.0.0]
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6502](https://github.com/MetaMask/core/pull/6502))
|
|
15
|
+
- Previously, `RemoteFeatureFlagController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`.
|
|
16
|
+
- **BREAKING:** Metadata property `anonymous` renamed to `includeInDebugSnapshot` ([#6502](https://github.com/MetaMask/core/pull/6502))
|
|
17
|
+
- Bump `@metamask/base-controller` from `^8.4.2` to `^9.0.0` ([#6962](https://github.com/MetaMask/core/pull/6962))
|
|
18
|
+
|
|
10
19
|
## [1.9.1]
|
|
11
20
|
|
|
12
21
|
### Changed
|
|
@@ -117,7 +126,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
117
126
|
- Initial release of the RemoteFeatureFlagController. ([#4931](https://github.com/MetaMask/core/pull/4931))
|
|
118
127
|
- This controller manages the retrieval and caching of remote feature flags. It fetches feature flags from a remote API, caches them, and provides methods to access and manage these flags. The controller ensures that feature flags are refreshed based on a specified interval and handles cases where the controller is disabled or the network is unavailable.
|
|
119
128
|
|
|
120
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/remote-feature-flag-controller@
|
|
129
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/remote-feature-flag-controller@2.0.0...HEAD
|
|
130
|
+
[2.0.0]: https://github.com/MetaMask/core/compare/@metamask/remote-feature-flag-controller@1.9.1...@metamask/remote-feature-flag-controller@2.0.0
|
|
121
131
|
[1.9.1]: https://github.com/MetaMask/core/compare/@metamask/remote-feature-flag-controller@1.9.0...@metamask/remote-feature-flag-controller@1.9.1
|
|
122
132
|
[1.9.0]: https://github.com/MetaMask/core/compare/@metamask/remote-feature-flag-controller@1.8.0...@metamask/remote-feature-flag-controller@1.9.0
|
|
123
133
|
[1.8.0]: https://github.com/MetaMask/core/compare/@metamask/remote-feature-flag-controller@1.7.0...@metamask/remote-feature-flag-controller@1.8.0
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,uFAA+E;AAAtE,6IAAA,2BAA2B,OAAA;
|
|
1
|
+
{"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,uFAA+E;AAAtE,6IAAA,2BAA2B,OAAA;AAUpC,mGAIgD;AAH9C,kIAAA,UAAU,OAAA;AACV,wIAAA,gBAAgB,OAAA;AAChB,uIAAA,eAAe,OAAA;AAIjB,uGAA+F;AAAtF,mIAAA,sBAAsB,OAAA;AAC/B,+EAAoF;AAA3E,4IAAA,iCAAiC,OAAA","sourcesContent":["export { RemoteFeatureFlagController } from './remote-feature-flag-controller';\nexport type {\n RemoteFeatureFlagControllerState,\n RemoteFeatureFlagControllerMessenger,\n RemoteFeatureFlagControllerActions,\n RemoteFeatureFlagControllerGetStateAction,\n RemoteFeatureFlagControllerUpdateRemoteFeatureFlagsAction,\n RemoteFeatureFlagControllerEvents,\n RemoteFeatureFlagControllerStateChangeEvent,\n} from './remote-feature-flag-controller';\nexport {\n ClientType,\n DistributionType,\n EnvironmentType,\n} from './remote-feature-flag-controller-types';\n\nexport type { FeatureFlags } from './remote-feature-flag-controller-types';\nexport { ClientConfigApiService } from './client-config-api-service/client-config-api-service';\nexport { generateDeterministicRandomNumber } from './utils/user-segmentation-utils';\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { RemoteFeatureFlagController } from "./remote-feature-flag-controller.cjs";
|
|
2
|
-
export type { RemoteFeatureFlagControllerMessenger, RemoteFeatureFlagControllerActions, RemoteFeatureFlagControllerGetStateAction, RemoteFeatureFlagControllerUpdateRemoteFeatureFlagsAction, RemoteFeatureFlagControllerEvents, RemoteFeatureFlagControllerStateChangeEvent, } from "./remote-feature-flag-controller.cjs";
|
|
2
|
+
export type { RemoteFeatureFlagControllerState, RemoteFeatureFlagControllerMessenger, RemoteFeatureFlagControllerActions, RemoteFeatureFlagControllerGetStateAction, RemoteFeatureFlagControllerUpdateRemoteFeatureFlagsAction, RemoteFeatureFlagControllerEvents, RemoteFeatureFlagControllerStateChangeEvent, } from "./remote-feature-flag-controller.cjs";
|
|
3
3
|
export { ClientType, DistributionType, EnvironmentType, } from "./remote-feature-flag-controller-types.cjs";
|
|
4
|
-
export type {
|
|
4
|
+
export type { FeatureFlags } from "./remote-feature-flag-controller-types.cjs";
|
|
5
5
|
export { ClientConfigApiService } from "./client-config-api-service/client-config-api-service.cjs";
|
|
6
6
|
export { generateDeterministicRandomNumber } from "./utils/user-segmentation-utils.cjs";
|
|
7
7
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,6CAAyC;AAC/E,YAAY,EACV,oCAAoC,EACpC,kCAAkC,EAClC,yCAAyC,EACzC,yDAAyD,EACzD,iCAAiC,EACjC,2CAA2C,GAC5C,6CAAyC;AAC1C,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,eAAe,GAChB,mDAA+C;AAEhD,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,6CAAyC;AAC/E,YAAY,EACV,gCAAgC,EAChC,oCAAoC,EACpC,kCAAkC,EAClC,yCAAyC,EACzC,yDAAyD,EACzD,iCAAiC,EACjC,2CAA2C,GAC5C,6CAAyC;AAC1C,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,eAAe,GAChB,mDAA+C;AAEhD,YAAY,EAAE,YAAY,EAAE,mDAA+C;AAC3E,OAAO,EAAE,sBAAsB,EAAE,kEAA8D;AAC/F,OAAO,EAAE,iCAAiC,EAAE,4CAAwC"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { RemoteFeatureFlagController } from "./remote-feature-flag-controller.mjs";
|
|
2
|
-
export type { RemoteFeatureFlagControllerMessenger, RemoteFeatureFlagControllerActions, RemoteFeatureFlagControllerGetStateAction, RemoteFeatureFlagControllerUpdateRemoteFeatureFlagsAction, RemoteFeatureFlagControllerEvents, RemoteFeatureFlagControllerStateChangeEvent, } from "./remote-feature-flag-controller.mjs";
|
|
2
|
+
export type { RemoteFeatureFlagControllerState, RemoteFeatureFlagControllerMessenger, RemoteFeatureFlagControllerActions, RemoteFeatureFlagControllerGetStateAction, RemoteFeatureFlagControllerUpdateRemoteFeatureFlagsAction, RemoteFeatureFlagControllerEvents, RemoteFeatureFlagControllerStateChangeEvent, } from "./remote-feature-flag-controller.mjs";
|
|
3
3
|
export { ClientType, DistributionType, EnvironmentType, } from "./remote-feature-flag-controller-types.mjs";
|
|
4
|
-
export type {
|
|
4
|
+
export type { FeatureFlags } from "./remote-feature-flag-controller-types.mjs";
|
|
5
5
|
export { ClientConfigApiService } from "./client-config-api-service/client-config-api-service.mjs";
|
|
6
6
|
export { generateDeterministicRandomNumber } from "./utils/user-segmentation-utils.mjs";
|
|
7
7
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,6CAAyC;AAC/E,YAAY,EACV,oCAAoC,EACpC,kCAAkC,EAClC,yCAAyC,EACzC,yDAAyD,EACzD,iCAAiC,EACjC,2CAA2C,GAC5C,6CAAyC;AAC1C,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,eAAe,GAChB,mDAA+C;AAEhD,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,6CAAyC;AAC/E,YAAY,EACV,gCAAgC,EAChC,oCAAoC,EACpC,kCAAkC,EAClC,yCAAyC,EACzC,yDAAyD,EACzD,iCAAiC,EACjC,2CAA2C,GAC5C,6CAAyC;AAC1C,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,eAAe,GAChB,mDAA+C;AAEhD,YAAY,EAAE,YAAY,EAAE,mDAA+C;AAC3E,OAAO,EAAE,sBAAsB,EAAE,kEAA8D;AAC/F,OAAO,EAAE,iCAAiC,EAAE,4CAAwC"}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,6CAAyC;
|
|
1
|
+
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,6CAAyC;AAU/E,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,eAAe,EAChB,mDAA+C;AAGhD,OAAO,EAAE,sBAAsB,EAAE,kEAA8D;AAC/F,OAAO,EAAE,iCAAiC,EAAE,4CAAwC","sourcesContent":["export { RemoteFeatureFlagController } from './remote-feature-flag-controller';\nexport type {\n RemoteFeatureFlagControllerState,\n RemoteFeatureFlagControllerMessenger,\n RemoteFeatureFlagControllerActions,\n RemoteFeatureFlagControllerGetStateAction,\n RemoteFeatureFlagControllerUpdateRemoteFeatureFlagsAction,\n RemoteFeatureFlagControllerEvents,\n RemoteFeatureFlagControllerStateChangeEvent,\n} from './remote-feature-flag-controller';\nexport {\n ClientType,\n DistributionType,\n EnvironmentType,\n} from './remote-feature-flag-controller-types';\n\nexport type { FeatureFlags } from './remote-feature-flag-controller-types';\nexport { ClientConfigApiService } from './client-config-api-service/client-config-api-service';\nexport { generateDeterministicRandomNumber } from './utils/user-segmentation-utils';\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-feature-flag-controller-types.cjs","sourceRoot":"","sources":["../src/remote-feature-flag-controller-types.ts"],"names":[],"mappings":";;;AAEA,mEAAmE;AACnE,IAAY,UAGX;AAHD,WAAY,UAAU;IACpB,qCAAuB,CAAA;IACvB,+BAAiB,CAAA;AACnB,CAAC,EAHW,UAAU,0BAAV,UAAU,QAGrB;AAED,IAAY,gBAOX;AAPD,WAAY,gBAAgB;IAC1B,iCAAa,CAAA;IACb,mCAAe,CAAA;IACf;;OAEG;IACH,iCAAa,CAAA;AACf,CAAC,EAPW,gBAAgB,gCAAhB,gBAAgB,QAO3B;AAED,IAAY,eAOX;AAPD,WAAY,eAAe;IACzB,sCAAmB,CAAA;IACnB,0CAAuB,CAAA;IACvB,sCAAmB,CAAA;IACnB,gCAAa,CAAA;IACb,gCAAa,CAAA;IACb,8BAAW,CAAA;AACb,CAAC,EAPW,eAAe,+BAAf,eAAe,QAO1B","sourcesContent":["import type { Json } from '@metamask/utils';\n\n// Define accepted values for client, distribution, and environment\nexport enum ClientType {\n Extension = 'extension',\n Mobile = 'mobile',\n}\n\nexport enum DistributionType {\n Main = 'main',\n Flask = 'flask',\n /**\n * @deprecated Use DistributionType Main with EnvironmentType Beta instead\n */\n Beta = 'beta',\n}\n\nexport enum EnvironmentType {\n Production = 'prod',\n ReleaseCandidate = 'rc',\n Development = 'dev',\n Beta = 'beta',\n Test = 'test',\n Exp = 'exp',\n}\n\n/** Type representing the feature flags collection */\nexport type FeatureFlags = {\n [key: string]: Json;\n};\n\nexport type FeatureFlagScope = {\n type: string;\n value: number;\n};\n\nexport type FeatureFlagScopeValue = {\n name: string;\n scope: FeatureFlagScope;\n value: Json;\n};\n\nexport type ApiDataResponse = FeatureFlags[];\n\nexport type ServiceResponse = {\n remoteFeatureFlags: FeatureFlags;\n cacheTimestamp: number | null;\n};\n
|
|
1
|
+
{"version":3,"file":"remote-feature-flag-controller-types.cjs","sourceRoot":"","sources":["../src/remote-feature-flag-controller-types.ts"],"names":[],"mappings":";;;AAEA,mEAAmE;AACnE,IAAY,UAGX;AAHD,WAAY,UAAU;IACpB,qCAAuB,CAAA;IACvB,+BAAiB,CAAA;AACnB,CAAC,EAHW,UAAU,0BAAV,UAAU,QAGrB;AAED,IAAY,gBAOX;AAPD,WAAY,gBAAgB;IAC1B,iCAAa,CAAA;IACb,mCAAe,CAAA;IACf;;OAEG;IACH,iCAAa,CAAA;AACf,CAAC,EAPW,gBAAgB,gCAAhB,gBAAgB,QAO3B;AAED,IAAY,eAOX;AAPD,WAAY,eAAe;IACzB,sCAAmB,CAAA;IACnB,0CAAuB,CAAA;IACvB,sCAAmB,CAAA;IACnB,gCAAa,CAAA;IACb,gCAAa,CAAA;IACb,8BAAW,CAAA;AACb,CAAC,EAPW,eAAe,+BAAf,eAAe,QAO1B","sourcesContent":["import type { Json } from '@metamask/utils';\n\n// Define accepted values for client, distribution, and environment\nexport enum ClientType {\n Extension = 'extension',\n Mobile = 'mobile',\n}\n\nexport enum DistributionType {\n Main = 'main',\n Flask = 'flask',\n /**\n * @deprecated Use DistributionType Main with EnvironmentType Beta instead\n */\n Beta = 'beta',\n}\n\nexport enum EnvironmentType {\n Production = 'prod',\n ReleaseCandidate = 'rc',\n Development = 'dev',\n Beta = 'beta',\n Test = 'test',\n Exp = 'exp',\n}\n\n/** Type representing the feature flags collection */\nexport type FeatureFlags = {\n [key: string]: Json;\n};\n\nexport type FeatureFlagScope = {\n type: string;\n value: number;\n};\n\nexport type FeatureFlagScopeValue = {\n name: string;\n scope: FeatureFlagScope;\n value: Json;\n};\n\nexport type ApiDataResponse = FeatureFlags[];\n\nexport type ServiceResponse = {\n remoteFeatureFlags: FeatureFlags;\n cacheTimestamp: number | null;\n};\n"]}
|
|
@@ -37,17 +37,4 @@ export type ServiceResponse = {
|
|
|
37
37
|
remoteFeatureFlags: FeatureFlags;
|
|
38
38
|
cacheTimestamp: number | null;
|
|
39
39
|
};
|
|
40
|
-
/**
|
|
41
|
-
* Describes the shape of the state object for the {@link RemoteFeatureFlagController}.
|
|
42
|
-
*/
|
|
43
|
-
export type RemoteFeatureFlagControllerState = {
|
|
44
|
-
/**
|
|
45
|
-
* The collection of feature flags and their respective values, which can be objects.
|
|
46
|
-
*/
|
|
47
|
-
remoteFeatureFlags: FeatureFlags;
|
|
48
|
-
/**
|
|
49
|
-
* The timestamp of the last successful feature flag cache.
|
|
50
|
-
*/
|
|
51
|
-
cacheTimestamp: number;
|
|
52
|
-
};
|
|
53
40
|
//# sourceMappingURL=remote-feature-flag-controller-types.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-feature-flag-controller-types.d.cts","sourceRoot":"","sources":["../src/remote-feature-flag-controller-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAG5C,oBAAY,UAAU;IACpB,SAAS,cAAc;IACvB,MAAM,WAAW;CAClB;AAED,oBAAY,gBAAgB;IAC1B,IAAI,SAAS;IACb,KAAK,UAAU;IACf;;OAEG;IACH,IAAI,SAAS;CACd;AAED,oBAAY,eAAe;IACzB,UAAU,SAAS;IACnB,gBAAgB,OAAO;IACvB,WAAW,QAAQ;IACnB,IAAI,SAAS;IACb,IAAI,SAAS;IACb,GAAG,QAAQ;CACZ;AAED,qDAAqD;AACrD,MAAM,MAAM,YAAY,GAAG;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,gBAAgB,CAAC;IACxB,KAAK,EAAE,IAAI,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,YAAY,EAAE,CAAC;AAE7C,MAAM,MAAM,eAAe,GAAG;IAC5B,kBAAkB,EAAE,YAAY,CAAC;IACjC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC
|
|
1
|
+
{"version":3,"file":"remote-feature-flag-controller-types.d.cts","sourceRoot":"","sources":["../src/remote-feature-flag-controller-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAG5C,oBAAY,UAAU;IACpB,SAAS,cAAc;IACvB,MAAM,WAAW;CAClB;AAED,oBAAY,gBAAgB;IAC1B,IAAI,SAAS;IACb,KAAK,UAAU;IACf;;OAEG;IACH,IAAI,SAAS;CACd;AAED,oBAAY,eAAe;IACzB,UAAU,SAAS;IACnB,gBAAgB,OAAO;IACvB,WAAW,QAAQ;IACnB,IAAI,SAAS;IACb,IAAI,SAAS;IACb,GAAG,QAAQ;CACZ;AAED,qDAAqD;AACrD,MAAM,MAAM,YAAY,GAAG;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,gBAAgB,CAAC;IACxB,KAAK,EAAE,IAAI,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,YAAY,EAAE,CAAC;AAE7C,MAAM,MAAM,eAAe,GAAG;IAC5B,kBAAkB,EAAE,YAAY,CAAC;IACjC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC"}
|
|
@@ -37,17 +37,4 @@ export type ServiceResponse = {
|
|
|
37
37
|
remoteFeatureFlags: FeatureFlags;
|
|
38
38
|
cacheTimestamp: number | null;
|
|
39
39
|
};
|
|
40
|
-
/**
|
|
41
|
-
* Describes the shape of the state object for the {@link RemoteFeatureFlagController}.
|
|
42
|
-
*/
|
|
43
|
-
export type RemoteFeatureFlagControllerState = {
|
|
44
|
-
/**
|
|
45
|
-
* The collection of feature flags and their respective values, which can be objects.
|
|
46
|
-
*/
|
|
47
|
-
remoteFeatureFlags: FeatureFlags;
|
|
48
|
-
/**
|
|
49
|
-
* The timestamp of the last successful feature flag cache.
|
|
50
|
-
*/
|
|
51
|
-
cacheTimestamp: number;
|
|
52
|
-
};
|
|
53
40
|
//# sourceMappingURL=remote-feature-flag-controller-types.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-feature-flag-controller-types.d.mts","sourceRoot":"","sources":["../src/remote-feature-flag-controller-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAG5C,oBAAY,UAAU;IACpB,SAAS,cAAc;IACvB,MAAM,WAAW;CAClB;AAED,oBAAY,gBAAgB;IAC1B,IAAI,SAAS;IACb,KAAK,UAAU;IACf;;OAEG;IACH,IAAI,SAAS;CACd;AAED,oBAAY,eAAe;IACzB,UAAU,SAAS;IACnB,gBAAgB,OAAO;IACvB,WAAW,QAAQ;IACnB,IAAI,SAAS;IACb,IAAI,SAAS;IACb,GAAG,QAAQ;CACZ;AAED,qDAAqD;AACrD,MAAM,MAAM,YAAY,GAAG;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,gBAAgB,CAAC;IACxB,KAAK,EAAE,IAAI,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,YAAY,EAAE,CAAC;AAE7C,MAAM,MAAM,eAAe,GAAG;IAC5B,kBAAkB,EAAE,YAAY,CAAC;IACjC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC
|
|
1
|
+
{"version":3,"file":"remote-feature-flag-controller-types.d.mts","sourceRoot":"","sources":["../src/remote-feature-flag-controller-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAG5C,oBAAY,UAAU;IACpB,SAAS,cAAc;IACvB,MAAM,WAAW;CAClB;AAED,oBAAY,gBAAgB;IAC1B,IAAI,SAAS;IACb,KAAK,UAAU;IACf;;OAEG;IACH,IAAI,SAAS;CACd;AAED,oBAAY,eAAe;IACzB,UAAU,SAAS;IACnB,gBAAgB,OAAO;IACvB,WAAW,QAAQ;IACnB,IAAI,SAAS;IACb,IAAI,SAAS;IACb,GAAG,QAAQ;CACZ;AAED,qDAAqD;AACrD,MAAM,MAAM,YAAY,GAAG;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,gBAAgB,CAAC;IACxB,KAAK,EAAE,IAAI,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,YAAY,EAAE,CAAC;AAE7C,MAAM,MAAM,eAAe,GAAG;IAC5B,kBAAkB,EAAE,YAAY,CAAC;IACjC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-feature-flag-controller-types.mjs","sourceRoot":"","sources":["../src/remote-feature-flag-controller-types.ts"],"names":[],"mappings":"AAEA,mEAAmE;AACnE,MAAM,CAAN,IAAY,UAGX;AAHD,WAAY,UAAU;IACpB,qCAAuB,CAAA;IACvB,+BAAiB,CAAA;AACnB,CAAC,EAHW,UAAU,KAAV,UAAU,QAGrB;AAED,MAAM,CAAN,IAAY,gBAOX;AAPD,WAAY,gBAAgB;IAC1B,iCAAa,CAAA;IACb,mCAAe,CAAA;IACf;;OAEG;IACH,iCAAa,CAAA;AACf,CAAC,EAPW,gBAAgB,KAAhB,gBAAgB,QAO3B;AAED,MAAM,CAAN,IAAY,eAOX;AAPD,WAAY,eAAe;IACzB,sCAAmB,CAAA;IACnB,0CAAuB,CAAA;IACvB,sCAAmB,CAAA;IACnB,gCAAa,CAAA;IACb,gCAAa,CAAA;IACb,8BAAW,CAAA;AACb,CAAC,EAPW,eAAe,KAAf,eAAe,QAO1B","sourcesContent":["import type { Json } from '@metamask/utils';\n\n// Define accepted values for client, distribution, and environment\nexport enum ClientType {\n Extension = 'extension',\n Mobile = 'mobile',\n}\n\nexport enum DistributionType {\n Main = 'main',\n Flask = 'flask',\n /**\n * @deprecated Use DistributionType Main with EnvironmentType Beta instead\n */\n Beta = 'beta',\n}\n\nexport enum EnvironmentType {\n Production = 'prod',\n ReleaseCandidate = 'rc',\n Development = 'dev',\n Beta = 'beta',\n Test = 'test',\n Exp = 'exp',\n}\n\n/** Type representing the feature flags collection */\nexport type FeatureFlags = {\n [key: string]: Json;\n};\n\nexport type FeatureFlagScope = {\n type: string;\n value: number;\n};\n\nexport type FeatureFlagScopeValue = {\n name: string;\n scope: FeatureFlagScope;\n value: Json;\n};\n\nexport type ApiDataResponse = FeatureFlags[];\n\nexport type ServiceResponse = {\n remoteFeatureFlags: FeatureFlags;\n cacheTimestamp: number | null;\n};\n
|
|
1
|
+
{"version":3,"file":"remote-feature-flag-controller-types.mjs","sourceRoot":"","sources":["../src/remote-feature-flag-controller-types.ts"],"names":[],"mappings":"AAEA,mEAAmE;AACnE,MAAM,CAAN,IAAY,UAGX;AAHD,WAAY,UAAU;IACpB,qCAAuB,CAAA;IACvB,+BAAiB,CAAA;AACnB,CAAC,EAHW,UAAU,KAAV,UAAU,QAGrB;AAED,MAAM,CAAN,IAAY,gBAOX;AAPD,WAAY,gBAAgB;IAC1B,iCAAa,CAAA;IACb,mCAAe,CAAA;IACf;;OAEG;IACH,iCAAa,CAAA;AACf,CAAC,EAPW,gBAAgB,KAAhB,gBAAgB,QAO3B;AAED,MAAM,CAAN,IAAY,eAOX;AAPD,WAAY,eAAe;IACzB,sCAAmB,CAAA;IACnB,0CAAuB,CAAA;IACvB,sCAAmB,CAAA;IACnB,gCAAa,CAAA;IACb,gCAAa,CAAA;IACb,8BAAW,CAAA;AACb,CAAC,EAPW,eAAe,KAAf,eAAe,QAO1B","sourcesContent":["import type { Json } from '@metamask/utils';\n\n// Define accepted values for client, distribution, and environment\nexport enum ClientType {\n Extension = 'extension',\n Mobile = 'mobile',\n}\n\nexport enum DistributionType {\n Main = 'main',\n Flask = 'flask',\n /**\n * @deprecated Use DistributionType Main with EnvironmentType Beta instead\n */\n Beta = 'beta',\n}\n\nexport enum EnvironmentType {\n Production = 'prod',\n ReleaseCandidate = 'rc',\n Development = 'dev',\n Beta = 'beta',\n Test = 'test',\n Exp = 'exp',\n}\n\n/** Type representing the feature flags collection */\nexport type FeatureFlags = {\n [key: string]: Json;\n};\n\nexport type FeatureFlagScope = {\n type: string;\n value: number;\n};\n\nexport type FeatureFlagScopeValue = {\n name: string;\n scope: FeatureFlagScope;\n value: Json;\n};\n\nexport type ApiDataResponse = FeatureFlags[];\n\nexport type ServiceResponse = {\n remoteFeatureFlags: FeatureFlags;\n cacheTimestamp: number | null;\n};\n"]}
|
|
@@ -12,23 +12,23 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
12
12
|
};
|
|
13
13
|
var _RemoteFeatureFlagController_instances, _RemoteFeatureFlagController_fetchInterval, _RemoteFeatureFlagController_disabled, _RemoteFeatureFlagController_clientConfigApiService, _RemoteFeatureFlagController_inProgressFlagUpdate, _RemoteFeatureFlagController_getMetaMetricsId, _RemoteFeatureFlagController_isCacheExpired, _RemoteFeatureFlagController_updateCache, _RemoteFeatureFlagController_processRemoteFeatureFlags;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.RemoteFeatureFlagController = exports.getDefaultRemoteFeatureFlagControllerState = exports.DEFAULT_CACHE_DURATION =
|
|
15
|
+
exports.RemoteFeatureFlagController = exports.getDefaultRemoteFeatureFlagControllerState = exports.DEFAULT_CACHE_DURATION = void 0;
|
|
16
16
|
const base_controller_1 = require("@metamask/base-controller");
|
|
17
17
|
const user_segmentation_utils_1 = require("./utils/user-segmentation-utils.cjs");
|
|
18
18
|
// === GENERAL ===
|
|
19
|
-
|
|
19
|
+
const controllerName = 'RemoteFeatureFlagController';
|
|
20
20
|
exports.DEFAULT_CACHE_DURATION = 24 * 60 * 60 * 1000; // 1 day
|
|
21
21
|
const remoteFeatureFlagControllerMetadata = {
|
|
22
22
|
remoteFeatureFlags: {
|
|
23
23
|
includeInStateLogs: true,
|
|
24
24
|
persist: true,
|
|
25
|
-
|
|
25
|
+
includeInDebugSnapshot: true,
|
|
26
26
|
usedInUi: true,
|
|
27
27
|
},
|
|
28
28
|
cacheTimestamp: {
|
|
29
29
|
includeInStateLogs: true,
|
|
30
30
|
persist: true,
|
|
31
|
-
|
|
31
|
+
includeInDebugSnapshot: true,
|
|
32
32
|
usedInUi: false,
|
|
33
33
|
},
|
|
34
34
|
};
|
|
@@ -64,7 +64,7 @@ class RemoteFeatureFlagController extends base_controller_1.BaseController {
|
|
|
64
64
|
*/
|
|
65
65
|
constructor({ messenger, state, clientConfigApiService, fetchInterval = exports.DEFAULT_CACHE_DURATION, disabled = false, getMetaMetricsId, }) {
|
|
66
66
|
super({
|
|
67
|
-
name:
|
|
67
|
+
name: controllerName,
|
|
68
68
|
metadata: remoteFeatureFlagControllerMetadata,
|
|
69
69
|
messenger,
|
|
70
70
|
state: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-feature-flag-controller.cjs","sourceRoot":"","sources":["../src/remote-feature-flag-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseController } from '@metamask/base-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedMessenger,\n} from '@metamask/base-controller';\n\nimport type { AbstractClientConfigApiService } from './client-config-api-service/abstract-client-config-api-service';\nimport type {\n FeatureFlags,\n ServiceResponse,\n FeatureFlagScopeValue,\n} from './remote-feature-flag-controller-types';\nimport {\n generateDeterministicRandomNumber,\n isFeatureFlagWithScopeValue,\n} from './utils/user-segmentation-utils';\n\n// === GENERAL ===\n\nexport const controllerName = 'RemoteFeatureFlagController';\nexport const DEFAULT_CACHE_DURATION = 24 * 60 * 60 * 1000; // 1 day\n\n// === STATE ===\n\nexport type RemoteFeatureFlagControllerState = {\n remoteFeatureFlags: FeatureFlags;\n cacheTimestamp: number;\n};\n\nconst remoteFeatureFlagControllerMetadata = {\n remoteFeatureFlags: {\n includeInStateLogs: true,\n persist: true,\n anonymous: true,\n usedInUi: true,\n },\n cacheTimestamp: {\n includeInStateLogs: true,\n persist: true,\n anonymous: true,\n usedInUi: false,\n },\n};\n\n// === MESSENGER ===\n\n/**\n * The action to retrieve the state of the {@link RemoteFeatureFlagController}.\n */\nexport type RemoteFeatureFlagControllerGetStateAction =\n ControllerGetStateAction<\n typeof controllerName,\n RemoteFeatureFlagControllerState\n >;\n\nexport type RemoteFeatureFlagControllerUpdateRemoteFeatureFlagsAction = {\n type: `${typeof controllerName}:updateRemoteFeatureFlags`;\n handler: RemoteFeatureFlagController['updateRemoteFeatureFlags'];\n};\n\nexport type RemoteFeatureFlagControllerActions =\n | RemoteFeatureFlagControllerGetStateAction\n | RemoteFeatureFlagControllerUpdateRemoteFeatureFlagsAction;\n\nexport type AllowedActions = never;\n\nexport type RemoteFeatureFlagControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n RemoteFeatureFlagControllerState\n >;\n\nexport type RemoteFeatureFlagControllerEvents =\n RemoteFeatureFlagControllerStateChangeEvent;\n\nexport type AllowedEvents = never;\n\nexport type RemoteFeatureFlagControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n RemoteFeatureFlagControllerActions | AllowedActions,\n RemoteFeatureFlagControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Returns the default state for the RemoteFeatureFlagController.\n *\n * @returns The default controller state.\n */\nexport function getDefaultRemoteFeatureFlagControllerState(): RemoteFeatureFlagControllerState {\n return {\n remoteFeatureFlags: {},\n cacheTimestamp: 0,\n };\n}\n\n/**\n * The RemoteFeatureFlagController manages the retrieval and caching of remote feature flags.\n * It fetches feature flags from a remote API, caches them, and provides methods to access\n * and manage these flags. The controller ensures that feature flags are refreshed based on\n * a specified interval and handles cases where the controller is disabled or the network is unavailable.\n */\nexport class RemoteFeatureFlagController extends BaseController<\n typeof controllerName,\n RemoteFeatureFlagControllerState,\n RemoteFeatureFlagControllerMessenger\n> {\n readonly #fetchInterval: number;\n\n #disabled: boolean;\n\n readonly #clientConfigApiService: AbstractClientConfigApiService;\n\n #inProgressFlagUpdate?: Promise<ServiceResponse>;\n\n #getMetaMetricsId: () => string;\n\n /**\n * Constructs a new RemoteFeatureFlagController instance.\n *\n * @param options - The controller options.\n * @param options.messenger - The messenger used for communication.\n * @param options.state - The initial state of the controller.\n * @param options.clientConfigApiService - The service instance to fetch remote feature flags.\n * @param options.fetchInterval - The interval in milliseconds before cached flags expire. Defaults to 1 day.\n * @param options.disabled - Determines if the controller should be disabled initially. Defaults to false.\n * @param options.getMetaMetricsId - Returns metaMetricsId.\n */\n constructor({\n messenger,\n state,\n clientConfigApiService,\n fetchInterval = DEFAULT_CACHE_DURATION,\n disabled = false,\n getMetaMetricsId,\n }: {\n messenger: RemoteFeatureFlagControllerMessenger;\n state?: Partial<RemoteFeatureFlagControllerState>;\n clientConfigApiService: AbstractClientConfigApiService;\n getMetaMetricsId: () => string;\n fetchInterval?: number;\n disabled?: boolean;\n }) {\n super({\n name: controllerName,\n metadata: remoteFeatureFlagControllerMetadata,\n messenger,\n state: {\n ...getDefaultRemoteFeatureFlagControllerState(),\n ...state,\n },\n });\n\n this.#fetchInterval = fetchInterval;\n this.#disabled = disabled;\n this.#clientConfigApiService = clientConfigApiService;\n this.#getMetaMetricsId = getMetaMetricsId;\n }\n\n /**\n * Checks if the cached feature flags are expired based on the fetch interval.\n *\n * @returns Whether the cache is expired (`true`) or still valid (`false`).\n * @private\n */\n #isCacheExpired(): boolean {\n return Date.now() - this.state.cacheTimestamp > this.#fetchInterval;\n }\n\n /**\n * Retrieves the remote feature flags, fetching from the API if necessary.\n * Uses caching to prevent redundant API calls and handles concurrent fetches.\n *\n * @returns A promise that resolves to the current set of feature flags.\n */\n async updateRemoteFeatureFlags(): Promise<void> {\n if (this.#disabled || !this.#isCacheExpired()) {\n return;\n }\n\n let serverData;\n\n if (this.#inProgressFlagUpdate) {\n await this.#inProgressFlagUpdate;\n return;\n }\n\n try {\n this.#inProgressFlagUpdate =\n this.#clientConfigApiService.fetchRemoteFeatureFlags();\n\n serverData = await this.#inProgressFlagUpdate;\n } finally {\n this.#inProgressFlagUpdate = undefined;\n }\n\n await this.#updateCache(serverData.remoteFeatureFlags);\n }\n\n /**\n * Updates the controller's state with new feature flags and resets the cache timestamp.\n *\n * @param remoteFeatureFlags - The new feature flags to cache.\n * @private\n */\n async #updateCache(remoteFeatureFlags: FeatureFlags) {\n const processedRemoteFeatureFlags =\n await this.#processRemoteFeatureFlags(remoteFeatureFlags);\n this.update(() => {\n return {\n remoteFeatureFlags: processedRemoteFeatureFlags,\n cacheTimestamp: Date.now(),\n };\n });\n }\n\n async #processRemoteFeatureFlags(\n remoteFeatureFlags: FeatureFlags,\n ): Promise<FeatureFlags> {\n const processedRemoteFeatureFlags: FeatureFlags = {};\n const metaMetricsId = this.#getMetaMetricsId();\n const thresholdValue = generateDeterministicRandomNumber(metaMetricsId);\n\n for (const [\n remoteFeatureFlagName,\n remoteFeatureFlagValue,\n ] of Object.entries(remoteFeatureFlags)) {\n let processedValue = remoteFeatureFlagValue;\n\n if (Array.isArray(remoteFeatureFlagValue) && thresholdValue) {\n const selectedGroup = remoteFeatureFlagValue.find(\n (featureFlag): featureFlag is FeatureFlagScopeValue => {\n if (!isFeatureFlagWithScopeValue(featureFlag)) {\n return false;\n }\n\n return thresholdValue <= featureFlag.scope.value;\n },\n );\n if (selectedGroup) {\n processedValue = {\n name: selectedGroup.name,\n value: selectedGroup.value,\n };\n }\n }\n\n processedRemoteFeatureFlags[remoteFeatureFlagName] = processedValue;\n }\n return processedRemoteFeatureFlags;\n }\n\n /**\n * Enables the controller, allowing it to make network requests.\n */\n enable(): void {\n this.#disabled = false;\n }\n\n /**\n * Disables the controller, preventing it from making network requests.\n */\n disable(): void {\n this.#disabled = true;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"remote-feature-flag-controller.cjs","sourceRoot":"","sources":["../src/remote-feature-flag-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n BaseController,\n type ControllerGetStateAction,\n type ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\n\nimport type { AbstractClientConfigApiService } from './client-config-api-service/abstract-client-config-api-service';\nimport type {\n FeatureFlags,\n ServiceResponse,\n FeatureFlagScopeValue,\n} from './remote-feature-flag-controller-types';\nimport {\n generateDeterministicRandomNumber,\n isFeatureFlagWithScopeValue,\n} from './utils/user-segmentation-utils';\n\n// === GENERAL ===\n\nconst controllerName = 'RemoteFeatureFlagController';\nexport const DEFAULT_CACHE_DURATION = 24 * 60 * 60 * 1000; // 1 day\n\n// === STATE ===\n\nexport type RemoteFeatureFlagControllerState = {\n remoteFeatureFlags: FeatureFlags;\n cacheTimestamp: number;\n};\n\nconst remoteFeatureFlagControllerMetadata = {\n remoteFeatureFlags: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: true,\n },\n cacheTimestamp: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: false,\n },\n};\n\n// === MESSENGER ===\n\n/**\n * The action to retrieve the state of the {@link RemoteFeatureFlagController}.\n */\nexport type RemoteFeatureFlagControllerGetStateAction =\n ControllerGetStateAction<\n typeof controllerName,\n RemoteFeatureFlagControllerState\n >;\n\nexport type RemoteFeatureFlagControllerUpdateRemoteFeatureFlagsAction = {\n type: `${typeof controllerName}:updateRemoteFeatureFlags`;\n handler: RemoteFeatureFlagController['updateRemoteFeatureFlags'];\n};\n\nexport type RemoteFeatureFlagControllerActions =\n | RemoteFeatureFlagControllerGetStateAction\n | RemoteFeatureFlagControllerUpdateRemoteFeatureFlagsAction;\n\nexport type RemoteFeatureFlagControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n RemoteFeatureFlagControllerState\n >;\n\nexport type RemoteFeatureFlagControllerEvents =\n RemoteFeatureFlagControllerStateChangeEvent;\n\nexport type RemoteFeatureFlagControllerMessenger = Messenger<\n typeof controllerName,\n RemoteFeatureFlagControllerActions,\n RemoteFeatureFlagControllerEvents\n>;\n\n/**\n * Returns the default state for the RemoteFeatureFlagController.\n *\n * @returns The default controller state.\n */\nexport function getDefaultRemoteFeatureFlagControllerState(): RemoteFeatureFlagControllerState {\n return {\n remoteFeatureFlags: {},\n cacheTimestamp: 0,\n };\n}\n\n/**\n * The RemoteFeatureFlagController manages the retrieval and caching of remote feature flags.\n * It fetches feature flags from a remote API, caches them, and provides methods to access\n * and manage these flags. The controller ensures that feature flags are refreshed based on\n * a specified interval and handles cases where the controller is disabled or the network is unavailable.\n */\nexport class RemoteFeatureFlagController extends BaseController<\n typeof controllerName,\n RemoteFeatureFlagControllerState,\n RemoteFeatureFlagControllerMessenger\n> {\n readonly #fetchInterval: number;\n\n #disabled: boolean;\n\n readonly #clientConfigApiService: AbstractClientConfigApiService;\n\n #inProgressFlagUpdate?: Promise<ServiceResponse>;\n\n #getMetaMetricsId: () => string;\n\n /**\n * Constructs a new RemoteFeatureFlagController instance.\n *\n * @param options - The controller options.\n * @param options.messenger - The messenger used for communication.\n * @param options.state - The initial state of the controller.\n * @param options.clientConfigApiService - The service instance to fetch remote feature flags.\n * @param options.fetchInterval - The interval in milliseconds before cached flags expire. Defaults to 1 day.\n * @param options.disabled - Determines if the controller should be disabled initially. Defaults to false.\n * @param options.getMetaMetricsId - Returns metaMetricsId.\n */\n constructor({\n messenger,\n state,\n clientConfigApiService,\n fetchInterval = DEFAULT_CACHE_DURATION,\n disabled = false,\n getMetaMetricsId,\n }: {\n messenger: RemoteFeatureFlagControllerMessenger;\n state?: Partial<RemoteFeatureFlagControllerState>;\n clientConfigApiService: AbstractClientConfigApiService;\n getMetaMetricsId: () => string;\n fetchInterval?: number;\n disabled?: boolean;\n }) {\n super({\n name: controllerName,\n metadata: remoteFeatureFlagControllerMetadata,\n messenger,\n state: {\n ...getDefaultRemoteFeatureFlagControllerState(),\n ...state,\n },\n });\n\n this.#fetchInterval = fetchInterval;\n this.#disabled = disabled;\n this.#clientConfigApiService = clientConfigApiService;\n this.#getMetaMetricsId = getMetaMetricsId;\n }\n\n /**\n * Checks if the cached feature flags are expired based on the fetch interval.\n *\n * @returns Whether the cache is expired (`true`) or still valid (`false`).\n * @private\n */\n #isCacheExpired(): boolean {\n return Date.now() - this.state.cacheTimestamp > this.#fetchInterval;\n }\n\n /**\n * Retrieves the remote feature flags, fetching from the API if necessary.\n * Uses caching to prevent redundant API calls and handles concurrent fetches.\n *\n * @returns A promise that resolves to the current set of feature flags.\n */\n async updateRemoteFeatureFlags(): Promise<void> {\n if (this.#disabled || !this.#isCacheExpired()) {\n return;\n }\n\n let serverData;\n\n if (this.#inProgressFlagUpdate) {\n await this.#inProgressFlagUpdate;\n return;\n }\n\n try {\n this.#inProgressFlagUpdate =\n this.#clientConfigApiService.fetchRemoteFeatureFlags();\n\n serverData = await this.#inProgressFlagUpdate;\n } finally {\n this.#inProgressFlagUpdate = undefined;\n }\n\n await this.#updateCache(serverData.remoteFeatureFlags);\n }\n\n /**\n * Updates the controller's state with new feature flags and resets the cache timestamp.\n *\n * @param remoteFeatureFlags - The new feature flags to cache.\n * @private\n */\n async #updateCache(remoteFeatureFlags: FeatureFlags) {\n const processedRemoteFeatureFlags =\n await this.#processRemoteFeatureFlags(remoteFeatureFlags);\n this.update(() => {\n return {\n remoteFeatureFlags: processedRemoteFeatureFlags,\n cacheTimestamp: Date.now(),\n };\n });\n }\n\n async #processRemoteFeatureFlags(\n remoteFeatureFlags: FeatureFlags,\n ): Promise<FeatureFlags> {\n const processedRemoteFeatureFlags: FeatureFlags = {};\n const metaMetricsId = this.#getMetaMetricsId();\n const thresholdValue = generateDeterministicRandomNumber(metaMetricsId);\n\n for (const [\n remoteFeatureFlagName,\n remoteFeatureFlagValue,\n ] of Object.entries(remoteFeatureFlags)) {\n let processedValue = remoteFeatureFlagValue;\n\n if (Array.isArray(remoteFeatureFlagValue) && thresholdValue) {\n const selectedGroup = remoteFeatureFlagValue.find(\n (featureFlag): featureFlag is FeatureFlagScopeValue => {\n if (!isFeatureFlagWithScopeValue(featureFlag)) {\n return false;\n }\n\n return thresholdValue <= featureFlag.scope.value;\n },\n );\n if (selectedGroup) {\n processedValue = {\n name: selectedGroup.name,\n value: selectedGroup.value,\n };\n }\n }\n\n processedRemoteFeatureFlags[remoteFeatureFlagName] = processedValue;\n }\n return processedRemoteFeatureFlags;\n }\n\n /**\n * Enables the controller, allowing it to make network requests.\n */\n enable(): void {\n this.#disabled = false;\n }\n\n /**\n * Disables the controller, preventing it from making network requests.\n */\n disable(): void {\n this.#disabled = true;\n }\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { BaseController } from "@metamask/base-controller";
|
|
2
|
-
import type {
|
|
1
|
+
import { BaseController, type ControllerGetStateAction, type ControllerStateChangeEvent } from "@metamask/base-controller";
|
|
2
|
+
import type { Messenger } from "@metamask/messenger";
|
|
3
3
|
import type { AbstractClientConfigApiService } from "./client-config-api-service/abstract-client-config-api-service.cjs";
|
|
4
4
|
import type { FeatureFlags } from "./remote-feature-flag-controller-types.cjs";
|
|
5
|
-
|
|
5
|
+
declare const controllerName = "RemoteFeatureFlagController";
|
|
6
6
|
export declare const DEFAULT_CACHE_DURATION: number;
|
|
7
7
|
export type RemoteFeatureFlagControllerState = {
|
|
8
8
|
remoteFeatureFlags: FeatureFlags;
|
|
@@ -17,11 +17,9 @@ export type RemoteFeatureFlagControllerUpdateRemoteFeatureFlagsAction = {
|
|
|
17
17
|
handler: RemoteFeatureFlagController['updateRemoteFeatureFlags'];
|
|
18
18
|
};
|
|
19
19
|
export type RemoteFeatureFlagControllerActions = RemoteFeatureFlagControllerGetStateAction | RemoteFeatureFlagControllerUpdateRemoteFeatureFlagsAction;
|
|
20
|
-
export type AllowedActions = never;
|
|
21
20
|
export type RemoteFeatureFlagControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, RemoteFeatureFlagControllerState>;
|
|
22
21
|
export type RemoteFeatureFlagControllerEvents = RemoteFeatureFlagControllerStateChangeEvent;
|
|
23
|
-
export type
|
|
24
|
-
export type RemoteFeatureFlagControllerMessenger = RestrictedMessenger<typeof controllerName, RemoteFeatureFlagControllerActions | AllowedActions, RemoteFeatureFlagControllerEvents | AllowedEvents, AllowedActions['type'], AllowedEvents['type']>;
|
|
22
|
+
export type RemoteFeatureFlagControllerMessenger = Messenger<typeof controllerName, RemoteFeatureFlagControllerActions, RemoteFeatureFlagControllerEvents>;
|
|
25
23
|
/**
|
|
26
24
|
* Returns the default state for the RemoteFeatureFlagController.
|
|
27
25
|
*
|
|
@@ -71,4 +69,5 @@ export declare class RemoteFeatureFlagController extends BaseController<typeof c
|
|
|
71
69
|
*/
|
|
72
70
|
disable(): void;
|
|
73
71
|
}
|
|
72
|
+
export {};
|
|
74
73
|
//# sourceMappingURL=remote-feature-flag-controller.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-feature-flag-controller.d.cts","sourceRoot":"","sources":["../src/remote-feature-flag-controller.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"remote-feature-flag-controller.d.cts","sourceRoot":"","sources":["../src/remote-feature-flag-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAChC,kCAAkC;AACnC,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAErD,OAAO,KAAK,EAAE,8BAA8B,EAAE,2EAAuE;AACrH,OAAO,KAAK,EACV,YAAY,EAGb,mDAA+C;AAQhD,QAAA,MAAM,cAAc,gCAAgC,CAAC;AACrD,eAAO,MAAM,sBAAsB,QAAsB,CAAC;AAI1D,MAAM,MAAM,gCAAgC,GAAG;IAC7C,kBAAkB,EAAE,YAAY,CAAC;IACjC,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAmBF;;GAEG;AACH,MAAM,MAAM,yCAAyC,GACnD,wBAAwB,CACtB,OAAO,cAAc,EACrB,gCAAgC,CACjC,CAAC;AAEJ,MAAM,MAAM,yDAAyD,GAAG;IACtE,IAAI,EAAE,GAAG,OAAO,cAAc,2BAA2B,CAAC;IAC1D,OAAO,EAAE,2BAA2B,CAAC,0BAA0B,CAAC,CAAC;CAClE,CAAC;AAEF,MAAM,MAAM,kCAAkC,GAC1C,yCAAyC,GACzC,yDAAyD,CAAC;AAE9D,MAAM,MAAM,2CAA2C,GACrD,0BAA0B,CACxB,OAAO,cAAc,EACrB,gCAAgC,CACjC,CAAC;AAEJ,MAAM,MAAM,iCAAiC,GAC3C,2CAA2C,CAAC;AAE9C,MAAM,MAAM,oCAAoC,GAAG,SAAS,CAC1D,OAAO,cAAc,EACrB,kCAAkC,EAClC,iCAAiC,CAClC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,0CAA0C,IAAI,gCAAgC,CAK7F;AAED;;;;;GAKG;AACH,qBAAa,2BAA4B,SAAQ,cAAc,CAC7D,OAAO,cAAc,EACrB,gCAAgC,EAChC,oCAAoC,CACrC;;IAWC;;;;;;;;;;OAUG;gBACS,EACV,SAAS,EACT,KAAK,EACL,sBAAsB,EACtB,aAAsC,EACtC,QAAgB,EAChB,gBAAgB,GACjB,EAAE;QACD,SAAS,EAAE,oCAAoC,CAAC;QAChD,KAAK,CAAC,EAAE,OAAO,CAAC,gCAAgC,CAAC,CAAC;QAClD,sBAAsB,EAAE,8BAA8B,CAAC;QACvD,gBAAgB,EAAE,MAAM,MAAM,CAAC;QAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB;IA2BD;;;;;OAKG;IACG,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC;IA6E/C;;OAEG;IACH,MAAM,IAAI,IAAI;IAId;;OAEG;IACH,OAAO,IAAI,IAAI;CAGhB"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { BaseController } from "@metamask/base-controller";
|
|
2
|
-
import type {
|
|
1
|
+
import { BaseController, type ControllerGetStateAction, type ControllerStateChangeEvent } from "@metamask/base-controller";
|
|
2
|
+
import type { Messenger } from "@metamask/messenger";
|
|
3
3
|
import type { AbstractClientConfigApiService } from "./client-config-api-service/abstract-client-config-api-service.mjs";
|
|
4
4
|
import type { FeatureFlags } from "./remote-feature-flag-controller-types.mjs";
|
|
5
|
-
|
|
5
|
+
declare const controllerName = "RemoteFeatureFlagController";
|
|
6
6
|
export declare const DEFAULT_CACHE_DURATION: number;
|
|
7
7
|
export type RemoteFeatureFlagControllerState = {
|
|
8
8
|
remoteFeatureFlags: FeatureFlags;
|
|
@@ -17,11 +17,9 @@ export type RemoteFeatureFlagControllerUpdateRemoteFeatureFlagsAction = {
|
|
|
17
17
|
handler: RemoteFeatureFlagController['updateRemoteFeatureFlags'];
|
|
18
18
|
};
|
|
19
19
|
export type RemoteFeatureFlagControllerActions = RemoteFeatureFlagControllerGetStateAction | RemoteFeatureFlagControllerUpdateRemoteFeatureFlagsAction;
|
|
20
|
-
export type AllowedActions = never;
|
|
21
20
|
export type RemoteFeatureFlagControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, RemoteFeatureFlagControllerState>;
|
|
22
21
|
export type RemoteFeatureFlagControllerEvents = RemoteFeatureFlagControllerStateChangeEvent;
|
|
23
|
-
export type
|
|
24
|
-
export type RemoteFeatureFlagControllerMessenger = RestrictedMessenger<typeof controllerName, RemoteFeatureFlagControllerActions | AllowedActions, RemoteFeatureFlagControllerEvents | AllowedEvents, AllowedActions['type'], AllowedEvents['type']>;
|
|
22
|
+
export type RemoteFeatureFlagControllerMessenger = Messenger<typeof controllerName, RemoteFeatureFlagControllerActions, RemoteFeatureFlagControllerEvents>;
|
|
25
23
|
/**
|
|
26
24
|
* Returns the default state for the RemoteFeatureFlagController.
|
|
27
25
|
*
|
|
@@ -71,4 +69,5 @@ export declare class RemoteFeatureFlagController extends BaseController<typeof c
|
|
|
71
69
|
*/
|
|
72
70
|
disable(): void;
|
|
73
71
|
}
|
|
72
|
+
export {};
|
|
74
73
|
//# sourceMappingURL=remote-feature-flag-controller.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-feature-flag-controller.d.mts","sourceRoot":"","sources":["../src/remote-feature-flag-controller.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"remote-feature-flag-controller.d.mts","sourceRoot":"","sources":["../src/remote-feature-flag-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAChC,kCAAkC;AACnC,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAErD,OAAO,KAAK,EAAE,8BAA8B,EAAE,2EAAuE;AACrH,OAAO,KAAK,EACV,YAAY,EAGb,mDAA+C;AAQhD,QAAA,MAAM,cAAc,gCAAgC,CAAC;AACrD,eAAO,MAAM,sBAAsB,QAAsB,CAAC;AAI1D,MAAM,MAAM,gCAAgC,GAAG;IAC7C,kBAAkB,EAAE,YAAY,CAAC;IACjC,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAmBF;;GAEG;AACH,MAAM,MAAM,yCAAyC,GACnD,wBAAwB,CACtB,OAAO,cAAc,EACrB,gCAAgC,CACjC,CAAC;AAEJ,MAAM,MAAM,yDAAyD,GAAG;IACtE,IAAI,EAAE,GAAG,OAAO,cAAc,2BAA2B,CAAC;IAC1D,OAAO,EAAE,2BAA2B,CAAC,0BAA0B,CAAC,CAAC;CAClE,CAAC;AAEF,MAAM,MAAM,kCAAkC,GAC1C,yCAAyC,GACzC,yDAAyD,CAAC;AAE9D,MAAM,MAAM,2CAA2C,GACrD,0BAA0B,CACxB,OAAO,cAAc,EACrB,gCAAgC,CACjC,CAAC;AAEJ,MAAM,MAAM,iCAAiC,GAC3C,2CAA2C,CAAC;AAE9C,MAAM,MAAM,oCAAoC,GAAG,SAAS,CAC1D,OAAO,cAAc,EACrB,kCAAkC,EAClC,iCAAiC,CAClC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,0CAA0C,IAAI,gCAAgC,CAK7F;AAED;;;;;GAKG;AACH,qBAAa,2BAA4B,SAAQ,cAAc,CAC7D,OAAO,cAAc,EACrB,gCAAgC,EAChC,oCAAoC,CACrC;;IAWC;;;;;;;;;;OAUG;gBACS,EACV,SAAS,EACT,KAAK,EACL,sBAAsB,EACtB,aAAsC,EACtC,QAAgB,EAChB,gBAAgB,GACjB,EAAE;QACD,SAAS,EAAE,oCAAoC,CAAC;QAChD,KAAK,CAAC,EAAE,OAAO,CAAC,gCAAgC,CAAC,CAAC;QAClD,sBAAsB,EAAE,8BAA8B,CAAC;QACvD,gBAAgB,EAAE,MAAM,MAAM,CAAC;QAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB;IA2BD;;;;;OAKG;IACG,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC;IA6E/C;;OAEG;IACH,MAAM,IAAI,IAAI;IAId;;OAEG;IACH,OAAO,IAAI,IAAI;CAGhB"}
|
|
@@ -13,19 +13,19 @@ var _RemoteFeatureFlagController_instances, _RemoteFeatureFlagController_fetchIn
|
|
|
13
13
|
import { BaseController } from "@metamask/base-controller";
|
|
14
14
|
import { generateDeterministicRandomNumber, isFeatureFlagWithScopeValue } from "./utils/user-segmentation-utils.mjs";
|
|
15
15
|
// === GENERAL ===
|
|
16
|
-
|
|
16
|
+
const controllerName = 'RemoteFeatureFlagController';
|
|
17
17
|
export const DEFAULT_CACHE_DURATION = 24 * 60 * 60 * 1000; // 1 day
|
|
18
18
|
const remoteFeatureFlagControllerMetadata = {
|
|
19
19
|
remoteFeatureFlags: {
|
|
20
20
|
includeInStateLogs: true,
|
|
21
21
|
persist: true,
|
|
22
|
-
|
|
22
|
+
includeInDebugSnapshot: true,
|
|
23
23
|
usedInUi: true,
|
|
24
24
|
},
|
|
25
25
|
cacheTimestamp: {
|
|
26
26
|
includeInStateLogs: true,
|
|
27
27
|
persist: true,
|
|
28
|
-
|
|
28
|
+
includeInDebugSnapshot: true,
|
|
29
29
|
usedInUi: false,
|
|
30
30
|
},
|
|
31
31
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-feature-flag-controller.mjs","sourceRoot":"","sources":["../src/remote-feature-flag-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseController } from '@metamask/base-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedMessenger,\n} from '@metamask/base-controller';\n\nimport type { AbstractClientConfigApiService } from './client-config-api-service/abstract-client-config-api-service';\nimport type {\n FeatureFlags,\n ServiceResponse,\n FeatureFlagScopeValue,\n} from './remote-feature-flag-controller-types';\nimport {\n generateDeterministicRandomNumber,\n isFeatureFlagWithScopeValue,\n} from './utils/user-segmentation-utils';\n\n// === GENERAL ===\n\nexport const controllerName = 'RemoteFeatureFlagController';\nexport const DEFAULT_CACHE_DURATION = 24 * 60 * 60 * 1000; // 1 day\n\n// === STATE ===\n\nexport type RemoteFeatureFlagControllerState = {\n remoteFeatureFlags: FeatureFlags;\n cacheTimestamp: number;\n};\n\nconst remoteFeatureFlagControllerMetadata = {\n remoteFeatureFlags: {\n includeInStateLogs: true,\n persist: true,\n anonymous: true,\n usedInUi: true,\n },\n cacheTimestamp: {\n includeInStateLogs: true,\n persist: true,\n anonymous: true,\n usedInUi: false,\n },\n};\n\n// === MESSENGER ===\n\n/**\n * The action to retrieve the state of the {@link RemoteFeatureFlagController}.\n */\nexport type RemoteFeatureFlagControllerGetStateAction =\n ControllerGetStateAction<\n typeof controllerName,\n RemoteFeatureFlagControllerState\n >;\n\nexport type RemoteFeatureFlagControllerUpdateRemoteFeatureFlagsAction = {\n type: `${typeof controllerName}:updateRemoteFeatureFlags`;\n handler: RemoteFeatureFlagController['updateRemoteFeatureFlags'];\n};\n\nexport type RemoteFeatureFlagControllerActions =\n | RemoteFeatureFlagControllerGetStateAction\n | RemoteFeatureFlagControllerUpdateRemoteFeatureFlagsAction;\n\nexport type AllowedActions = never;\n\nexport type RemoteFeatureFlagControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n RemoteFeatureFlagControllerState\n >;\n\nexport type RemoteFeatureFlagControllerEvents =\n RemoteFeatureFlagControllerStateChangeEvent;\n\nexport type AllowedEvents = never;\n\nexport type RemoteFeatureFlagControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n RemoteFeatureFlagControllerActions | AllowedActions,\n RemoteFeatureFlagControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Returns the default state for the RemoteFeatureFlagController.\n *\n * @returns The default controller state.\n */\nexport function getDefaultRemoteFeatureFlagControllerState(): RemoteFeatureFlagControllerState {\n return {\n remoteFeatureFlags: {},\n cacheTimestamp: 0,\n };\n}\n\n/**\n * The RemoteFeatureFlagController manages the retrieval and caching of remote feature flags.\n * It fetches feature flags from a remote API, caches them, and provides methods to access\n * and manage these flags. The controller ensures that feature flags are refreshed based on\n * a specified interval and handles cases where the controller is disabled or the network is unavailable.\n */\nexport class RemoteFeatureFlagController extends BaseController<\n typeof controllerName,\n RemoteFeatureFlagControllerState,\n RemoteFeatureFlagControllerMessenger\n> {\n readonly #fetchInterval: number;\n\n #disabled: boolean;\n\n readonly #clientConfigApiService: AbstractClientConfigApiService;\n\n #inProgressFlagUpdate?: Promise<ServiceResponse>;\n\n #getMetaMetricsId: () => string;\n\n /**\n * Constructs a new RemoteFeatureFlagController instance.\n *\n * @param options - The controller options.\n * @param options.messenger - The messenger used for communication.\n * @param options.state - The initial state of the controller.\n * @param options.clientConfigApiService - The service instance to fetch remote feature flags.\n * @param options.fetchInterval - The interval in milliseconds before cached flags expire. Defaults to 1 day.\n * @param options.disabled - Determines if the controller should be disabled initially. Defaults to false.\n * @param options.getMetaMetricsId - Returns metaMetricsId.\n */\n constructor({\n messenger,\n state,\n clientConfigApiService,\n fetchInterval = DEFAULT_CACHE_DURATION,\n disabled = false,\n getMetaMetricsId,\n }: {\n messenger: RemoteFeatureFlagControllerMessenger;\n state?: Partial<RemoteFeatureFlagControllerState>;\n clientConfigApiService: AbstractClientConfigApiService;\n getMetaMetricsId: () => string;\n fetchInterval?: number;\n disabled?: boolean;\n }) {\n super({\n name: controllerName,\n metadata: remoteFeatureFlagControllerMetadata,\n messenger,\n state: {\n ...getDefaultRemoteFeatureFlagControllerState(),\n ...state,\n },\n });\n\n this.#fetchInterval = fetchInterval;\n this.#disabled = disabled;\n this.#clientConfigApiService = clientConfigApiService;\n this.#getMetaMetricsId = getMetaMetricsId;\n }\n\n /**\n * Checks if the cached feature flags are expired based on the fetch interval.\n *\n * @returns Whether the cache is expired (`true`) or still valid (`false`).\n * @private\n */\n #isCacheExpired(): boolean {\n return Date.now() - this.state.cacheTimestamp > this.#fetchInterval;\n }\n\n /**\n * Retrieves the remote feature flags, fetching from the API if necessary.\n * Uses caching to prevent redundant API calls and handles concurrent fetches.\n *\n * @returns A promise that resolves to the current set of feature flags.\n */\n async updateRemoteFeatureFlags(): Promise<void> {\n if (this.#disabled || !this.#isCacheExpired()) {\n return;\n }\n\n let serverData;\n\n if (this.#inProgressFlagUpdate) {\n await this.#inProgressFlagUpdate;\n return;\n }\n\n try {\n this.#inProgressFlagUpdate =\n this.#clientConfigApiService.fetchRemoteFeatureFlags();\n\n serverData = await this.#inProgressFlagUpdate;\n } finally {\n this.#inProgressFlagUpdate = undefined;\n }\n\n await this.#updateCache(serverData.remoteFeatureFlags);\n }\n\n /**\n * Updates the controller's state with new feature flags and resets the cache timestamp.\n *\n * @param remoteFeatureFlags - The new feature flags to cache.\n * @private\n */\n async #updateCache(remoteFeatureFlags: FeatureFlags) {\n const processedRemoteFeatureFlags =\n await this.#processRemoteFeatureFlags(remoteFeatureFlags);\n this.update(() => {\n return {\n remoteFeatureFlags: processedRemoteFeatureFlags,\n cacheTimestamp: Date.now(),\n };\n });\n }\n\n async #processRemoteFeatureFlags(\n remoteFeatureFlags: FeatureFlags,\n ): Promise<FeatureFlags> {\n const processedRemoteFeatureFlags: FeatureFlags = {};\n const metaMetricsId = this.#getMetaMetricsId();\n const thresholdValue = generateDeterministicRandomNumber(metaMetricsId);\n\n for (const [\n remoteFeatureFlagName,\n remoteFeatureFlagValue,\n ] of Object.entries(remoteFeatureFlags)) {\n let processedValue = remoteFeatureFlagValue;\n\n if (Array.isArray(remoteFeatureFlagValue) && thresholdValue) {\n const selectedGroup = remoteFeatureFlagValue.find(\n (featureFlag): featureFlag is FeatureFlagScopeValue => {\n if (!isFeatureFlagWithScopeValue(featureFlag)) {\n return false;\n }\n\n return thresholdValue <= featureFlag.scope.value;\n },\n );\n if (selectedGroup) {\n processedValue = {\n name: selectedGroup.name,\n value: selectedGroup.value,\n };\n }\n }\n\n processedRemoteFeatureFlags[remoteFeatureFlagName] = processedValue;\n }\n return processedRemoteFeatureFlags;\n }\n\n /**\n * Enables the controller, allowing it to make network requests.\n */\n enable(): void {\n this.#disabled = false;\n }\n\n /**\n * Disables the controller, preventing it from making network requests.\n */\n disable(): void {\n this.#disabled = true;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"remote-feature-flag-controller.mjs","sourceRoot":"","sources":["../src/remote-feature-flag-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n BaseController,\n type ControllerGetStateAction,\n type ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\n\nimport type { AbstractClientConfigApiService } from './client-config-api-service/abstract-client-config-api-service';\nimport type {\n FeatureFlags,\n ServiceResponse,\n FeatureFlagScopeValue,\n} from './remote-feature-flag-controller-types';\nimport {\n generateDeterministicRandomNumber,\n isFeatureFlagWithScopeValue,\n} from './utils/user-segmentation-utils';\n\n// === GENERAL ===\n\nconst controllerName = 'RemoteFeatureFlagController';\nexport const DEFAULT_CACHE_DURATION = 24 * 60 * 60 * 1000; // 1 day\n\n// === STATE ===\n\nexport type RemoteFeatureFlagControllerState = {\n remoteFeatureFlags: FeatureFlags;\n cacheTimestamp: number;\n};\n\nconst remoteFeatureFlagControllerMetadata = {\n remoteFeatureFlags: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: true,\n },\n cacheTimestamp: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: false,\n },\n};\n\n// === MESSENGER ===\n\n/**\n * The action to retrieve the state of the {@link RemoteFeatureFlagController}.\n */\nexport type RemoteFeatureFlagControllerGetStateAction =\n ControllerGetStateAction<\n typeof controllerName,\n RemoteFeatureFlagControllerState\n >;\n\nexport type RemoteFeatureFlagControllerUpdateRemoteFeatureFlagsAction = {\n type: `${typeof controllerName}:updateRemoteFeatureFlags`;\n handler: RemoteFeatureFlagController['updateRemoteFeatureFlags'];\n};\n\nexport type RemoteFeatureFlagControllerActions =\n | RemoteFeatureFlagControllerGetStateAction\n | RemoteFeatureFlagControllerUpdateRemoteFeatureFlagsAction;\n\nexport type RemoteFeatureFlagControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n RemoteFeatureFlagControllerState\n >;\n\nexport type RemoteFeatureFlagControllerEvents =\n RemoteFeatureFlagControllerStateChangeEvent;\n\nexport type RemoteFeatureFlagControllerMessenger = Messenger<\n typeof controllerName,\n RemoteFeatureFlagControllerActions,\n RemoteFeatureFlagControllerEvents\n>;\n\n/**\n * Returns the default state for the RemoteFeatureFlagController.\n *\n * @returns The default controller state.\n */\nexport function getDefaultRemoteFeatureFlagControllerState(): RemoteFeatureFlagControllerState {\n return {\n remoteFeatureFlags: {},\n cacheTimestamp: 0,\n };\n}\n\n/**\n * The RemoteFeatureFlagController manages the retrieval and caching of remote feature flags.\n * It fetches feature flags from a remote API, caches them, and provides methods to access\n * and manage these flags. The controller ensures that feature flags are refreshed based on\n * a specified interval and handles cases where the controller is disabled or the network is unavailable.\n */\nexport class RemoteFeatureFlagController extends BaseController<\n typeof controllerName,\n RemoteFeatureFlagControllerState,\n RemoteFeatureFlagControllerMessenger\n> {\n readonly #fetchInterval: number;\n\n #disabled: boolean;\n\n readonly #clientConfigApiService: AbstractClientConfigApiService;\n\n #inProgressFlagUpdate?: Promise<ServiceResponse>;\n\n #getMetaMetricsId: () => string;\n\n /**\n * Constructs a new RemoteFeatureFlagController instance.\n *\n * @param options - The controller options.\n * @param options.messenger - The messenger used for communication.\n * @param options.state - The initial state of the controller.\n * @param options.clientConfigApiService - The service instance to fetch remote feature flags.\n * @param options.fetchInterval - The interval in milliseconds before cached flags expire. Defaults to 1 day.\n * @param options.disabled - Determines if the controller should be disabled initially. Defaults to false.\n * @param options.getMetaMetricsId - Returns metaMetricsId.\n */\n constructor({\n messenger,\n state,\n clientConfigApiService,\n fetchInterval = DEFAULT_CACHE_DURATION,\n disabled = false,\n getMetaMetricsId,\n }: {\n messenger: RemoteFeatureFlagControllerMessenger;\n state?: Partial<RemoteFeatureFlagControllerState>;\n clientConfigApiService: AbstractClientConfigApiService;\n getMetaMetricsId: () => string;\n fetchInterval?: number;\n disabled?: boolean;\n }) {\n super({\n name: controllerName,\n metadata: remoteFeatureFlagControllerMetadata,\n messenger,\n state: {\n ...getDefaultRemoteFeatureFlagControllerState(),\n ...state,\n },\n });\n\n this.#fetchInterval = fetchInterval;\n this.#disabled = disabled;\n this.#clientConfigApiService = clientConfigApiService;\n this.#getMetaMetricsId = getMetaMetricsId;\n }\n\n /**\n * Checks if the cached feature flags are expired based on the fetch interval.\n *\n * @returns Whether the cache is expired (`true`) or still valid (`false`).\n * @private\n */\n #isCacheExpired(): boolean {\n return Date.now() - this.state.cacheTimestamp > this.#fetchInterval;\n }\n\n /**\n * Retrieves the remote feature flags, fetching from the API if necessary.\n * Uses caching to prevent redundant API calls and handles concurrent fetches.\n *\n * @returns A promise that resolves to the current set of feature flags.\n */\n async updateRemoteFeatureFlags(): Promise<void> {\n if (this.#disabled || !this.#isCacheExpired()) {\n return;\n }\n\n let serverData;\n\n if (this.#inProgressFlagUpdate) {\n await this.#inProgressFlagUpdate;\n return;\n }\n\n try {\n this.#inProgressFlagUpdate =\n this.#clientConfigApiService.fetchRemoteFeatureFlags();\n\n serverData = await this.#inProgressFlagUpdate;\n } finally {\n this.#inProgressFlagUpdate = undefined;\n }\n\n await this.#updateCache(serverData.remoteFeatureFlags);\n }\n\n /**\n * Updates the controller's state with new feature flags and resets the cache timestamp.\n *\n * @param remoteFeatureFlags - The new feature flags to cache.\n * @private\n */\n async #updateCache(remoteFeatureFlags: FeatureFlags) {\n const processedRemoteFeatureFlags =\n await this.#processRemoteFeatureFlags(remoteFeatureFlags);\n this.update(() => {\n return {\n remoteFeatureFlags: processedRemoteFeatureFlags,\n cacheTimestamp: Date.now(),\n };\n });\n }\n\n async #processRemoteFeatureFlags(\n remoteFeatureFlags: FeatureFlags,\n ): Promise<FeatureFlags> {\n const processedRemoteFeatureFlags: FeatureFlags = {};\n const metaMetricsId = this.#getMetaMetricsId();\n const thresholdValue = generateDeterministicRandomNumber(metaMetricsId);\n\n for (const [\n remoteFeatureFlagName,\n remoteFeatureFlagValue,\n ] of Object.entries(remoteFeatureFlags)) {\n let processedValue = remoteFeatureFlagValue;\n\n if (Array.isArray(remoteFeatureFlagValue) && thresholdValue) {\n const selectedGroup = remoteFeatureFlagValue.find(\n (featureFlag): featureFlag is FeatureFlagScopeValue => {\n if (!isFeatureFlagWithScopeValue(featureFlag)) {\n return false;\n }\n\n return thresholdValue <= featureFlag.scope.value;\n },\n );\n if (selectedGroup) {\n processedValue = {\n name: selectedGroup.name,\n value: selectedGroup.value,\n };\n }\n }\n\n processedRemoteFeatureFlags[remoteFeatureFlagName] = processedValue;\n }\n return processedRemoteFeatureFlags;\n }\n\n /**\n * Enables the controller, allowing it to make network requests.\n */\n enable(): void {\n this.#disabled = false;\n }\n\n /**\n * Disables the controller, preventing it from making network requests.\n */\n disable(): void {\n this.#disabled = true;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask-previews/remote-feature-flag-controller",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-preview-46d2c977",
|
|
4
4
|
"description": "The RemoteFeatureFlagController manages the retrieval and caching of remote feature flags",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"MetaMask",
|
|
@@ -47,8 +47,9 @@
|
|
|
47
47
|
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@metamask/base-controller": "^
|
|
50
|
+
"@metamask/base-controller": "^9.0.0",
|
|
51
51
|
"@metamask/controller-utils": "^11.14.1",
|
|
52
|
+
"@metamask/messenger": "^0.3.0",
|
|
52
53
|
"@metamask/utils": "^11.8.1",
|
|
53
54
|
"uuid": "^8.3.2"
|
|
54
55
|
},
|