feat: superposition sdk/config consumption#524
Conversation
| @@ -0,0 +1,35 @@ | |||
|
|
|||
| // will be checked where this logic should live | |||
| let useGetSuperpositionRawConfigs = () => { | |||
There was a problem hiding this comment.
Move to shared-code
| } | ||
|
|
||
| let lookupLocaleString = (localeObject, key) => | ||
| switch localeObject->Obj.magic->Dict.get(key) { |
There was a problem hiding this comment.
try removing the .magic and if not possible wrap it in try{} catch{}
| let handleInputChange = (value: string) => { | ||
| let formattedValue = value //formatValue(value, phoneNumberConfig.fieldType) | ||
| phoneNumberInput.onChange(formattedValue) | ||
| phoneNumberInput.onChange(value) |
There was a problem hiding this comment.
for Phone-code and postal code for formatting there is a file
There was a problem hiding this comment.
Noted as a TODO, Pick this up later
8066300 to
7aefc01
Compare
| | _ => () | ||
| let isCountryDropdown = | ||
| (field.fieldRenderType === Dropdown || field.fieldRenderType === Country) && | ||
| field.confirmRequestWritePath->String.endsWith(".country") |
There was a problem hiding this comment.
These many checks are not required
|
|
||
| let isStateDropdown = (field: SuperpositionTypes.fieldConfig) => | ||
| field.fieldRenderType === State || | ||
| (field.fieldRenderType === Dropdown && field.confirmRequestWritePath->String.endsWith(".state")) |
There was a problem hiding this comment.
These many checks might not be required
0e1ae60 to
2490027
Compare
01ad827 to
262dc50
Compare
| ~config={validate: createFieldValidator(CardNetwork(enabledCardSchemes))}, | ||
| cardNetworkPath, | ||
| ~config={ | ||
| validate: ?(hasNetwork && enabledCardSchemes->Array.length > 0 |
There was a problem hiding this comment.
Why not have a unified logic for check and render?
There was a problem hiding this comment.
Done — extracted a useOptionalCardField(config, ~sentinel, ~validate) → (present, input, meta) hook that unifies the presence-check + real/sentinel path + conditional validator in one place.
- The optional cvc and network fields now each resolve in a single call.
- The render guard uses the returned present flag.
| let cardExpiryMonthConfig = findField(SuperpositionTypes.CardExpiryMonth) | ||
| let cardExpiryYearConfig = findField(SuperpositionTypes.CardExpiryYear) | ||
| let cardCvcConfig = findField(SuperpositionTypes.Cvc) | ||
| let cardNetworkConfig = findField(SuperpositionTypes.CardNetwork) |
There was a problem hiding this comment.
Shouldn't fields controlled by priority?
There was a problem hiding this comment.
- Previously, the CardElement logic relied on the order and priority of fields in the array (for example, assuming fields[0] was card number, fields[1] was expiry month, etc.). This approach was fragile because any change in field priority ordering it fell through to | _ => React.null
- To make the rendering logic more robust and independent of field ordering, we have extended fieldRenderType with dedicated values such as CardExpiryMonth, CardExpiryYear, and CardNetwork. CardElement and other Special UX components now identify and consume fields based on fieldRenderType rather than array position or priority. Since fieldRenderType is a stable, explicit, and non-changing identifier, this ensures the components receive the correct fields regardless of ordering changes.
|
Remove all logic based on |
262dc50 to
65dd4e1
Compare
GenericTabElement.res
DynamicFieldsContext.res
|
65dd4e1 to
972e31a
Compare
| maxLength=Some(7) | ||
| borderTopWidth=?{splitCardFields ? None : Some(borderWidth /. 2.)} | ||
| borderRightWidth=?{splitCardFields ? None : Some(borderWidth /. 2.)} | ||
| borderRightWidth=?{splitCardFields |
There was a problem hiding this comment.
Why are we changing this borderWidth
There was a problem hiding this comment.
- Because CVC is now optional (driven by the resolved config). When CVC is present, the expiry field sits to its left in the same row and shares a half-width border (borderWidth /. 2.). When CVC is hidden (hasCvc = false), expiry becomes the right-most element, so it needs the full borderWidth on its right edge; otherwise, the row's outer border renders thin. Hence Some(hasCvc ? borderWidth /. 2. : borderWidth).
| }} | ||
| </UIUtils.RenderIf> | ||
| </View> | ||
| <UIUtils.RenderIf condition={hasCvc}> |
There was a problem hiding this comment.
What exactly are we doing here?
Are we rendering CVC based on the superposition
There was a problem hiding this comment.
- Yes — CVC is config-driven now. hasCvc = findField(Cvc)->Option.isSome, so it's true only when the resolved dynamic-fields (superposition) config includes the CVC field.
- The card block used to assume all five sub-fields always exist; now the CVC and network fields are optional. The useField for CVC is still called unconditionally via a sentinel path (Rules of Hooks), and hasCvc only gates the visual render and its validator.
| React.useEffect1(() => { | ||
| let cancelled = ref(false) | ||
|
|
||
| setResult(_ => defaultSdkConfigValue) |
There was a problem hiding this comment.
Why are you setting back to the defaultSdkConfigValue?
on refetchKey changes it will be triggered, you are already using the initial state with the defaultSdkConfigValue
let (result, setResult) = React.useState(() => defaultSdkConfigValue)
There was a problem hiding this comment.
this may leads to broken UI
There was a problem hiding this comment.
- Good catch — agreed. setResult(_ => defaultSdkConfigValue) at the top of the effect would blank the config on every refetch and cause a UI flash.
- In the latest revision, i've removed this bespoke loader entirely. The config is now fetched the same way as PML (via NavigationRouter) and stored in AllApiDataContextNew as an option. During refetches, the previous config is retained until the new response arrives, so there's no reset-to-default state and no empty flash.
- This file is deleted
| } | ||
| Promise.resolve() | ||
| }) | ||
| ->Promise.catch(_ => { |
There was a problem hiding this comment.
@sh-iv-am should we add a retry or lets skip this time
| ~appId=nativeProp.sdkParams.appId, | ||
| (), | ||
| ) | ||
| if clientSecret->String.length > 0 { |
There was a problem hiding this comment.
Can we fetch sdkAuth without Client-Secret?
@sh-iv-am @Pradeep-kumar1202
There was a problem hiding this comment.
So, can we send a mesage client-secret is needed if not handled in the sdkTypes
c96dba3 to
e3c58ca
Compare
| if isValidConfig(parsed) { | ||
| setSdkConfigData(_ => Some(parsed)) | ||
| } else { | ||
| handleSuccessFailure(~apiResStatus=PaymentConfirmTypes.defaultConfirmError, ()) |
There was a problem hiding this comment.
Why are we using defaultConfirmError here? Its a get call no?
There was a problem hiding this comment.
Let's mark this as a TODO
There was a problem hiding this comment.
if its a small change can we not do this now? Is there a big change needed for this?
| let apiLogWrapper = LoggerHook.useApiLogWrapper() | ||
| let baseUrl = GlobalHooks.useGetBaseUrl()() | ||
| () => { | ||
| let uri = `${baseUrl}/v1/sdk/configs/web/sdk_config.json` |
There was a problem hiding this comment.
is /web in the uri intentional?
There was a problem hiding this comment.
Good Catch - it is not intensional it should be platform now it's modified
9d0af72 to
ff6bb00
Compare
|
ff6bb00 to
03549c3
Compare
03549c3 to
b783f85
Compare
Type of Change
Summary
The PML no longer decides which payment methods to show or which fields to collect. SDK now fetches a config for the payment and uses that as the source for both — what's eligible, and what to render.
New Contract
When the SDK loads, it fetches configuration once:
Headers:
api-key+client-secretFor each payment method and connector, the configuration defines:
What we do with it
Available everywhere — fetched once at startup and exposed through a context,so any screen reads the same config.
Eligibility
The configuration determines which payment method tiles are displayed.
Fields
For the selected payment method:
Field handling includes:
Rendering Implementation
Screenshots / Recordings
Affected Area & Impact
Android PR / status (if any):
iOS PR / status (if any):
**Shared Codebase PR / status (if any):**juspay/hyperswitch-sdk-utils#68
Testing
Notes:
Checklist