@ledgerhq/live-config 1.0.0-next.0

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.
Files changed (136) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.js +20 -0
  3. package/.turbo/turbo-build.log +4 -0
  4. package/.unimportedrc.json +5 -0
  5. package/CHANGELOG.md +14 -0
  6. package/LICENSE.txt +21 -0
  7. package/jest.config.js +10 -0
  8. package/lib/featureFlags/FeatureFlagsContext.d.ts +41 -0
  9. package/lib/featureFlags/FeatureFlagsContext.d.ts.map +1 -0
  10. package/lib/featureFlags/FeatureFlagsContext.js +26 -0
  11. package/lib/featureFlags/FeatureFlagsContext.js.map +1 -0
  12. package/lib/featureFlags/FeatureFlagsContext.test.d.ts +2 -0
  13. package/lib/featureFlags/FeatureFlagsContext.test.d.ts.map +1 -0
  14. package/lib/featureFlags/FeatureFlagsContext.test.js +15 -0
  15. package/lib/featureFlags/FeatureFlagsContext.test.js.map +1 -0
  16. package/lib/featureFlags/FeatureToggle.d.ts +10 -0
  17. package/lib/featureFlags/FeatureToggle.d.ts.map +1 -0
  18. package/lib/featureFlags/FeatureToggle.js +16 -0
  19. package/lib/featureFlags/FeatureToggle.js.map +1 -0
  20. package/lib/featureFlags/LiveConfig.d.ts +25 -0
  21. package/lib/featureFlags/LiveConfig.d.ts.map +1 -0
  22. package/lib/featureFlags/LiveConfig.js +30 -0
  23. package/lib/featureFlags/LiveConfig.js.map +1 -0
  24. package/lib/featureFlags/defaultFeatures.d.ts +61 -0
  25. package/lib/featureFlags/defaultFeatures.d.ts.map +1 -0
  26. package/lib/featureFlags/defaultFeatures.js +319 -0
  27. package/lib/featureFlags/defaultFeatures.js.map +1 -0
  28. package/lib/featureFlags/firebaseFeatureFlags.d.ts +109 -0
  29. package/lib/featureFlags/firebaseFeatureFlags.d.ts.map +1 -0
  30. package/lib/featureFlags/firebaseFeatureFlags.js +90 -0
  31. package/lib/featureFlags/firebaseFeatureFlags.js.map +1 -0
  32. package/lib/featureFlags/groupedFeatures.d.ts +6 -0
  33. package/lib/featureFlags/groupedFeatures.d.ts.map +1 -0
  34. package/lib/featureFlags/groupedFeatures.js +22 -0
  35. package/lib/featureFlags/groupedFeatures.js.map +1 -0
  36. package/lib/featureFlags/helper.d.ts +2 -0
  37. package/lib/featureFlags/helper.d.ts.map +1 -0
  38. package/lib/featureFlags/helper.js +10 -0
  39. package/lib/featureFlags/helper.js.map +1 -0
  40. package/lib/featureFlags/index.d.ts +11 -0
  41. package/lib/featureFlags/index.d.ts.map +1 -0
  42. package/lib/featureFlags/index.js +32 -0
  43. package/lib/featureFlags/index.js.map +1 -0
  44. package/lib/featureFlags/mock.d.ts +11 -0
  45. package/lib/featureFlags/mock.d.ts.map +1 -0
  46. package/lib/featureFlags/mock.js +25 -0
  47. package/lib/featureFlags/mock.js.map +1 -0
  48. package/lib/featureFlags/useFeature.d.ts +14 -0
  49. package/lib/featureFlags/useFeature.d.ts.map +1 -0
  50. package/lib/featureFlags/useFeature.js +21 -0
  51. package/lib/featureFlags/useFeature.js.map +1 -0
  52. package/lib/featureFlags/useFeature.test.d.ts +2 -0
  53. package/lib/featureFlags/useFeature.test.d.ts.map +1 -0
  54. package/lib/featureFlags/useFeature.test.js +27 -0
  55. package/lib/featureFlags/useFeature.test.js.map +1 -0
  56. package/lib/featureFlags/useHasOverriddenFeatureFlags.d.ts +6 -0
  57. package/lib/featureFlags/useHasOverriddenFeatureFlags.d.ts.map +1 -0
  58. package/lib/featureFlags/useHasOverriddenFeatureFlags.js +24 -0
  59. package/lib/featureFlags/useHasOverriddenFeatureFlags.js.map +1 -0
  60. package/lib/index.d.ts +2 -0
  61. package/lib/index.d.ts.map +1 -0
  62. package/lib/index.js +18 -0
  63. package/lib/index.js.map +1 -0
  64. package/lib-es/featureFlags/FeatureFlagsContext.d.ts +41 -0
  65. package/lib-es/featureFlags/FeatureFlagsContext.d.ts.map +1 -0
  66. package/lib-es/featureFlags/FeatureFlagsContext.js +22 -0
  67. package/lib-es/featureFlags/FeatureFlagsContext.js.map +1 -0
  68. package/lib-es/featureFlags/FeatureFlagsContext.test.d.ts +2 -0
  69. package/lib-es/featureFlags/FeatureFlagsContext.test.d.ts.map +1 -0
  70. package/lib-es/featureFlags/FeatureFlagsContext.test.js +13 -0
  71. package/lib-es/featureFlags/FeatureFlagsContext.test.js.map +1 -0
  72. package/lib-es/featureFlags/FeatureToggle.d.ts +10 -0
  73. package/lib-es/featureFlags/FeatureToggle.d.ts.map +1 -0
  74. package/lib-es/featureFlags/FeatureToggle.js +11 -0
  75. package/lib-es/featureFlags/FeatureToggle.js.map +1 -0
  76. package/lib-es/featureFlags/LiveConfig.d.ts +25 -0
  77. package/lib-es/featureFlags/LiveConfig.d.ts.map +1 -0
  78. package/lib-es/featureFlags/LiveConfig.js +26 -0
  79. package/lib-es/featureFlags/LiveConfig.js.map +1 -0
  80. package/lib-es/featureFlags/defaultFeatures.d.ts +61 -0
  81. package/lib-es/featureFlags/defaultFeatures.d.ts.map +1 -0
  82. package/lib-es/featureFlags/defaultFeatures.js +314 -0
  83. package/lib-es/featureFlags/defaultFeatures.js.map +1 -0
  84. package/lib-es/featureFlags/firebaseFeatureFlags.d.ts +109 -0
  85. package/lib-es/featureFlags/firebaseFeatureFlags.d.ts.map +1 -0
  86. package/lib-es/featureFlags/firebaseFeatureFlags.js +80 -0
  87. package/lib-es/featureFlags/firebaseFeatureFlags.js.map +1 -0
  88. package/lib-es/featureFlags/groupedFeatures.d.ts +6 -0
  89. package/lib-es/featureFlags/groupedFeatures.d.ts.map +1 -0
  90. package/lib-es/featureFlags/groupedFeatures.js +19 -0
  91. package/lib-es/featureFlags/groupedFeatures.js.map +1 -0
  92. package/lib-es/featureFlags/helper.d.ts +2 -0
  93. package/lib-es/featureFlags/helper.d.ts.map +1 -0
  94. package/lib-es/featureFlags/helper.js +6 -0
  95. package/lib-es/featureFlags/helper.js.map +1 -0
  96. package/lib-es/featureFlags/index.d.ts +11 -0
  97. package/lib-es/featureFlags/index.d.ts.map +1 -0
  98. package/lib-es/featureFlags/index.js +11 -0
  99. package/lib-es/featureFlags/index.js.map +1 -0
  100. package/lib-es/featureFlags/mock.d.ts +11 -0
  101. package/lib-es/featureFlags/mock.d.ts.map +1 -0
  102. package/lib-es/featureFlags/mock.js +17 -0
  103. package/lib-es/featureFlags/mock.js.map +1 -0
  104. package/lib-es/featureFlags/useFeature.d.ts +14 -0
  105. package/lib-es/featureFlags/useFeature.d.ts.map +1 -0
  106. package/lib-es/featureFlags/useFeature.js +19 -0
  107. package/lib-es/featureFlags/useFeature.js.map +1 -0
  108. package/lib-es/featureFlags/useFeature.test.d.ts +2 -0
  109. package/lib-es/featureFlags/useFeature.test.d.ts.map +1 -0
  110. package/lib-es/featureFlags/useFeature.test.js +22 -0
  111. package/lib-es/featureFlags/useFeature.test.js.map +1 -0
  112. package/lib-es/featureFlags/useHasOverriddenFeatureFlags.d.ts +6 -0
  113. package/lib-es/featureFlags/useHasOverriddenFeatureFlags.d.ts.map +1 -0
  114. package/lib-es/featureFlags/useHasOverriddenFeatureFlags.js +20 -0
  115. package/lib-es/featureFlags/useHasOverriddenFeatureFlags.js.map +1 -0
  116. package/lib-es/index.d.ts +2 -0
  117. package/lib-es/index.d.ts.map +1 -0
  118. package/lib-es/index.js +2 -0
  119. package/lib-es/index.js.map +1 -0
  120. package/package.json +82 -0
  121. package/src/featureFlags/FeatureFlagsContext.test.tsx +13 -0
  122. package/src/featureFlags/FeatureFlagsContext.tsx +62 -0
  123. package/src/featureFlags/FeatureToggle.tsx +22 -0
  124. package/src/featureFlags/LiveConfig.ts +45 -0
  125. package/src/featureFlags/defaultFeatures.ts +428 -0
  126. package/src/featureFlags/firebaseFeatureFlags.ts +115 -0
  127. package/src/featureFlags/groupedFeatures.ts +25 -0
  128. package/src/featureFlags/helper.tsx +9 -0
  129. package/src/featureFlags/index.ts +12 -0
  130. package/src/featureFlags/mock.tsx +28 -0
  131. package/src/featureFlags/useFeature.test.tsx +23 -0
  132. package/src/featureFlags/useFeature.ts +21 -0
  133. package/src/featureFlags/useHasOverriddenFeatureFlags.ts +24 -0
  134. package/src/index.ts +1 -0
  135. package/tsconfig.json +15 -0
  136. package/types.ts +5 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock.js","sourceRoot":"","sources":["../../src/featureFlags/mock.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAA4B,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAEvF,MAAM,UAAU,sBAAsB,CACpC,cAAmD;IAEnD,OAAO;QACL,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI;QACrB,UAAU,EAAE,CAAC,SAAoB,EAAE,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC,IAAI,IAAI;QACvE,eAAe,EAAE,GAAG,EAAE,GAAE,CAAC;QACzB,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC;QACtB,aAAa,EAAE,GAAG,EAAE,GAAE,CAAC;KACxB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qCAAqC,CACnD,kBAA4C;IAE5C,MAAM,4BAA4B,GAAmD,CAAC,EACpF,QAAQ,GACT,EAAE,EAAE,CAAC,oBAAC,oBAAoB,IAAC,KAAK,EAAE,kBAAkB,IAAG,QAAQ,CAAwB,CAAC;IACzF,OAAO,4BAA4B,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,MAAM,sCAAsC,GAAG,qCAAqC,CACzF,sBAAsB,CAAC,EAAE,CAAC,CAC3B,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { Feature, FeatureParam } from "@ledgerhq/types-live";
2
+ /**
3
+ * Hook that returns the value of a feature flag based on its `featureId`.
4
+ *
5
+ * @dev do not modify this function to make it return a default arbitrary value
6
+ * instead of null, this should not be handled at this level.
7
+ *
8
+ * @param featureId
9
+ * @returns a feature flag value or null if the feature flag is not found
10
+ * (neither in the remote configuration, in the cache or in the local defaults).
11
+ */
12
+ declare const useFeature: <T extends keyof import("@ledgerhq/types-live").CurrencyFeatures | "learn" | "brazePushNotifications" | "brazeLearn" | "llmNewDeviceSelection" | "llmNewFirmwareUpdateUx" | "ratingsPrompt" | "npsRatingsPrompt" | "counterValue" | "deviceInitialApps" | "buyDeviceFromLive" | "ptxEarn" | "depositNetworkBannerMobile" | "depositWithdrawBannerMobile" | "mockFeature" | "multibuyNavigation" | "syncOnboarding" | "walletConnectEntryPoint" | "customImage" | "referralProgramDiscoverCard" | "referralProgramDesktopBanner" | "referralProgramDesktopSidebar" | "referralProgramMobile" | "disableNftSend" | "disableNftLedgerMarket" | "disableNftRaribleOpensea" | "walletNftGallery" | "receiveStakingFlowConfigDesktop" | "ethStakingProviders" | "storyly" | "staxWelcomeScreen" | "postOnboardingClaimNft" | "postOnboardingAssetsTransfer" | "firebaseEnvironmentReadOnly" | "protectServicesMobile" | "protectServicesDesktop" | "ptxServiceCtaExchangeDrawer" | "ptxServiceCtaScreens" | "swapWalletApiPartnerList" | "stakePrograms" | "portfolioExchangeBanner" | "objkt" | "editEvmTx" | "stakeAccountBanner" | "newsfeedPage" | "domainInputResolution" | "discover" | "protectServicesDiscoverDesktop" | "transactionsAlerts" | "listAppsV2minor1" | "llmWalletQuickActions" | "cexDepositEntryPointsDesktop" | "cexDepositEntryPointsMobile" | "fetchAdditionalCoins" | "ptxSwapLiveApp" | "ptxSwapMoonpayProvider">(featureId: T) => Feature<FeatureParam<T>> | null;
13
+ export default useFeature;
14
+ //# sourceMappingURL=useFeature.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFeature.d.ts","sourceRoot":"","sources":["../../src/featureFlags/useFeature.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAExE;;;;;;;;;GASG;AACH,QAAA,MAAM,UAAU,05CAIf,CAAC;AAEF,eAAe,UAAU,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { useMemo } from "react";
2
+ import { useFeatureFlags } from "./FeatureFlagsContext";
3
+ /**
4
+ * Hook that returns the value of a feature flag based on its `featureId`.
5
+ *
6
+ * @dev do not modify this function to make it return a default arbitrary value
7
+ * instead of null, this should not be handled at this level.
8
+ *
9
+ * @param featureId
10
+ * @returns a feature flag value or null if the feature flag is not found
11
+ * (neither in the remote configuration, in the cache or in the local defaults).
12
+ */
13
+ const useFeature = (featureId) => {
14
+ const featureFlags = useFeatureFlags();
15
+ const value = useMemo(() => featureFlags.getFeature(featureId), [featureFlags, featureId]);
16
+ return value;
17
+ };
18
+ export default useFeature;
19
+ //# sourceMappingURL=useFeature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFeature.js","sourceRoot":"","sources":["../../src/featureFlags/useFeature.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD;;;;;;;;;GASG;AACH,MAAM,UAAU,GAAG,CAAsB,SAAY,EAAmC,EAAE;IACxF,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;IACvC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC;IAC3F,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,eAAe,UAAU,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=useFeature.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFeature.test.d.ts","sourceRoot":"","sources":["../../src/featureFlags/useFeature.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ import { renderHook } from "@testing-library/react-hooks";
2
+ import useFeature from "./useFeature";
3
+ import { makeMockedFeatureFlagsProviderWrapper, makeMockedContextValue } from "./mock";
4
+ describe("useFeature hook", () => {
5
+ it("should return null if a flag is not defined remotely", () => {
6
+ const mockedFeatures = {};
7
+ const { result } = renderHook(() => useFeature("mockFeature"), {
8
+ wrapper: makeMockedFeatureFlagsProviderWrapper(makeMockedContextValue(mockedFeatures)),
9
+ });
10
+ expect(result.current).toBeNull();
11
+ });
12
+ it("should return the feature flag value if the feature flag is defined", () => {
13
+ const mockedFeatures = {
14
+ mockFeature: { enabled: true, params: { blabla: "hello" } },
15
+ };
16
+ const { result } = renderHook(() => useFeature("mockFeature"), {
17
+ wrapper: makeMockedFeatureFlagsProviderWrapper(makeMockedContextValue(mockedFeatures)),
18
+ });
19
+ expect(result.current).toBe(mockedFeatures.mockFeature);
20
+ });
21
+ });
22
+ //# sourceMappingURL=useFeature.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFeature.test.js","sourceRoot":"","sources":["../../src/featureFlags/useFeature.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,UAAU,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,qCAAqC,EAAE,sBAAsB,EAAE,MAAM,QAAQ,CAAC;AAEvF,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,cAAc,GAAG,EAAE,CAAC;QAC1B,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE;YAC7D,OAAO,EAAE,qCAAqC,CAAC,sBAAsB,CAAC,cAAc,CAAC,CAAC;SACvF,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE,GAAG,EAAE;QAC7E,MAAM,cAAc,GAAG;YACrB,WAAW,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE;SAC5D,CAAC;QACF,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE;YAC7D,OAAO,EAAE,qCAAqC,CAAC,sBAAsB,CAAC,cAAc,CAAC,CAAC;SACvF,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ *
3
+ * @returns whether one or more flags are locally overridden
4
+ */
5
+ export declare function useHasLocallyOverriddenFeatureFlags(): boolean;
6
+ //# sourceMappingURL=useHasOverriddenFeatureFlags.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useHasOverriddenFeatureFlags.d.ts","sourceRoot":"","sources":["../../src/featureFlags/useHasOverriddenFeatureFlags.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,wBAAgB,mCAAmC,IAAI,OAAO,CAc7D"}
@@ -0,0 +1,20 @@
1
+ import { useMemo } from "react";
2
+ import { useFeatureFlags } from "./FeatureFlagsContext";
3
+ import { DEFAULT_FEATURES } from "./defaultFeatures";
4
+ /**
5
+ *
6
+ * @returns whether one or more flags are locally overridden
7
+ */
8
+ export function useHasLocallyOverriddenFeatureFlags() {
9
+ const { getFeature } = useFeatureFlags();
10
+ return useMemo(() => Object.entries(DEFAULT_FEATURES).some(([featureId]) => {
11
+ try {
12
+ const val = getFeature(featureId);
13
+ return (val === null || val === void 0 ? void 0 : val.overridesRemote) || (val === null || val === void 0 ? void 0 : val.overriddenByEnv);
14
+ }
15
+ catch (e) {
16
+ return false;
17
+ }
18
+ }), [getFeature]);
19
+ }
20
+ //# sourceMappingURL=useHasOverriddenFeatureFlags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useHasOverriddenFeatureFlags.js","sourceRoot":"","sources":["../../src/featureFlags/useHasOverriddenFeatureFlags.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;GAGG;AACH,MAAM,UAAU,mCAAmC;IACjD,MAAM,EAAE,UAAU,EAAE,GAAG,eAAe,EAAE,CAAC;IACzC,OAAO,OAAO,CACZ,GAAG,EAAE,CACH,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE;QACpD,IAAI;YACF,MAAM,GAAG,GAAG,UAAU,CAAC,SAAsB,CAAC,CAAC;YAC/C,OAAO,CAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,eAAe,MAAI,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,eAAe,CAAA,CAAC;SACrD;QAAC,OAAO,CAAC,EAAE;YACV,OAAO,KAAK,CAAC;SACd;IACH,CAAC,CAAC,EACJ,CAAC,UAAU,CAAC,CACb,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from "./featureFlags";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from "./featureFlags";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,82 @@
1
+ {
2
+ "name": "@ledgerhq/live-config",
3
+ "version": "1.0.0-next.0",
4
+ "description": "Ledger Live configuration tools",
5
+ "license": "Apache-2.0",
6
+ "keywords": [
7
+ "Ledger"
8
+ ],
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/LedgerHQ/ledger-live.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/LedgerHQ/ledger-live/issues"
15
+ },
16
+ "homepage": "https://github.com/LedgerHQ/ledger-live/tree/develop/libs/live-config",
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "dependencies": {
21
+ "lodash": "^4.17.21",
22
+ "@ledgerhq/errors": "^6.16.1-next.0",
23
+ "@ledgerhq/live-env": "^0.8.0-next.0",
24
+ "@ledgerhq/live-promise": "^0.0.3",
25
+ "@ledgerhq/logs": "^6.12.0",
26
+ "@ledgerhq/types-live": "^6.43.1-next.0"
27
+ },
28
+ "devDependencies": {
29
+ "@testing-library/react": "12",
30
+ "@testing-library/react-hooks": "^8.0.0",
31
+ "@types/invariant": "^2.2.35",
32
+ "@types/jest": "^29.5.4",
33
+ "@types/lodash": "^4.14.182",
34
+ "@types/node": "^20.2.5",
35
+ "jest": "^28.1.1",
36
+ "jest-environment-jsdom": "28",
37
+ "react": "^18.2.0",
38
+ "react-dom": "18.2.0",
39
+ "semver": "^7.3.5",
40
+ "ts-jest": "^28.0.5"
41
+ },
42
+ "typesVersions": {
43
+ "*": {
44
+ "*.json": [
45
+ "*.json"
46
+ ],
47
+ "*": [
48
+ "lib/*"
49
+ ],
50
+ "lib/*": [
51
+ "lib/*"
52
+ ],
53
+ "lib-es/*": [
54
+ "lib-es/*"
55
+ ]
56
+ }
57
+ },
58
+ "exports": {
59
+ "./lib/*": "./lib/*.js",
60
+ "./lib/*.js": "./lib/*.js",
61
+ "./lib-es/*": "./lib-es/*.js",
62
+ "./lib-es/*.js": "./lib-es/*.js",
63
+ "./*": {
64
+ "require": "./lib/*.js",
65
+ "default": "./lib-es/*.js"
66
+ },
67
+ "./*.js": {
68
+ "require": "./lib/*.js",
69
+ "default": "./lib-es/*.js"
70
+ },
71
+ "./package.json": "./package.json"
72
+ },
73
+ "scripts": {
74
+ "clean": "rimraf lib lib-es",
75
+ "build": "tsc && tsc -m ES6 --outDir lib-es",
76
+ "prewatch": "pnpm build",
77
+ "watch": "tsc --watch",
78
+ "lint": "eslint ./src --no-error-on-unmatched-pattern --ext .ts,.tsx",
79
+ "lint:fix": "pnpm lint --fix",
80
+ "test": "jest"
81
+ }
82
+ }
@@ -0,0 +1,13 @@
1
+ import { renderHook } from "@testing-library/react-hooks";
2
+ import { makeMockedContextValue, makeMockedFeatureFlagsProviderWrapper } from "./mock";
3
+ import { useFeatureFlags } from "./FeatureFlagsContext";
4
+
5
+ describe("useFeatureFlags hook", () => {
6
+ it("should return the context value if it is used inside a context provider", () => {
7
+ const mockedContextValue = makeMockedContextValue({});
8
+ const { result } = renderHook(() => useFeatureFlags(), {
9
+ wrapper: makeMockedFeatureFlagsProviderWrapper(mockedContextValue),
10
+ });
11
+ expect(result?.current).toStrictEqual(mockedContextValue);
12
+ });
13
+ });
@@ -0,0 +1,62 @@
1
+ import { createContext, useContext } from "react";
2
+ import type { FeatureId, Feature } from "@ledgerhq/types-live";
3
+
4
+ export type FeatureFlagsContextValue = {
5
+ /**
6
+ *
7
+ * @param featureId featureId identifying a potential feature flag
8
+ * @returns true if and only if the parameter matches a feature that is configured.
9
+ */
10
+ isFeature: (featureId: string) => boolean;
11
+
12
+ /**
13
+ *
14
+ * @param featureId featureId identifying a feature flag
15
+ * @returns the value of the feature flag if it is defined (remotely or through a default value), otherwise returns null
16
+ */
17
+ getFeature: (featureId: FeatureId) => Feature | null;
18
+
19
+ /**
20
+ * function that allows to override the value of a feature flag
21
+ *
22
+ * @param featureId featureId identifying a feature flag
23
+ * @param newValue new value of the feature flag
24
+ * @returns undefined
25
+ */
26
+ overrideFeature: (featureId: FeatureId, newValue: Feature) => void;
27
+
28
+ /**
29
+ * resets the overridden feature flag value for a given featureId
30
+ * @param featureId featureId identifying a feature flag
31
+ * @returns undefined
32
+ */
33
+ resetFeature: (featureId: FeatureId) => void;
34
+ /**
35
+ * resets all the overridden feature flags
36
+ * @returns undefined
37
+ */
38
+ resetFeatures: () => void;
39
+ };
40
+
41
+ /**
42
+ * Context used for injecting the feature flagging implementation logic.
43
+ *
44
+ * @dev do not export this, it should be accessed exclusively through
45
+ * useFeatureFlags and FeatureFlagsProvider
46
+ */
47
+ const FeatureFlagsContext = createContext<FeatureFlagsContextValue>({
48
+ isFeature: _ => false,
49
+ getFeature: _ => null,
50
+ overrideFeature: _ => {},
51
+ resetFeature: _ => {},
52
+ resetFeatures: () => {},
53
+ });
54
+
55
+ export const FeatureFlagsProvider = FeatureFlagsContext.Provider;
56
+
57
+ /**
58
+ * Hook to consume a FeatureFlagsContext
59
+ */
60
+ export function useFeatureFlags(): FeatureFlagsContextValue {
61
+ return useContext(FeatureFlagsContext);
62
+ }
@@ -0,0 +1,22 @@
1
+ import React, { ReactNode } from "react";
2
+
3
+ import useFeature from "./useFeature";
4
+ import type { FeatureId } from "@ledgerhq/types-live";
5
+
6
+ type Props = {
7
+ featureId: FeatureId;
8
+ fallback?: ReactNode;
9
+ children?: ReactNode;
10
+ };
11
+
12
+ const FeatureToggle = ({ featureId, fallback, children }: Props): JSX.Element => {
13
+ const feature = useFeature(featureId);
14
+
15
+ if (!feature || !feature.enabled) {
16
+ return <>{fallback || null}</>;
17
+ }
18
+
19
+ return <>{children || null}</>;
20
+ };
21
+
22
+ export default FeatureToggle;
@@ -0,0 +1,45 @@
1
+ // refer to https://github.com/firebase/firebase-js-sdk/blob/master/packages/remote-config/src/public_types.ts#L71 for the firebase config value interface
2
+ export declare interface Value {
3
+ asBoolean(): boolean;
4
+ asNumber(): number;
5
+ asString(): string;
6
+ }
7
+
8
+ export class LiveConfig {
9
+ public appVersion?: string;
10
+ public platform?: string;
11
+ public environment?: string;
12
+ public providerGetvalueMethod?: { [provider: string]: (key: string) => Value };
13
+
14
+ private static instance: LiveConfig; // Singleton instance
15
+ private constructor() {}
16
+ public static init(config: { appVersion: string; platform: string; environment: string }) {
17
+ if (!LiveConfig.instance) {
18
+ LiveConfig.instance = new LiveConfig();
19
+ LiveConfig.instance.appVersion = config.appVersion;
20
+ LiveConfig.instance.platform = config.platform;
21
+ }
22
+ }
23
+
24
+ public static setProviderGetValueMethod(provider2Method: {
25
+ [provider: string]: (key: string) => Value;
26
+ }) {
27
+ if (!LiveConfig.instance) {
28
+ throw new Error("LiveConfig instance is not initialized. Call init() first.");
29
+ }
30
+ if (!LiveConfig.instance.providerGetvalueMethod) {
31
+ LiveConfig.instance.providerGetvalueMethod = {};
32
+ }
33
+ LiveConfig.instance.providerGetvalueMethod = {
34
+ ...LiveConfig.instance.providerGetvalueMethod,
35
+ ...provider2Method,
36
+ };
37
+ }
38
+
39
+ public static getInstance(): LiveConfig {
40
+ if (!LiveConfig.instance) {
41
+ throw new Error("LiveConfig instance is not initialized. Call init() first.");
42
+ }
43
+ return LiveConfig.instance;
44
+ }
45
+ }