Skip to content

Commit fe7cc86

Browse files
committed
Consolidate flow response transformers into a single utility module
1 parent c67119e commit fe7cc86

File tree

6 files changed

+177
-144
lines changed

6 files changed

+177
-144
lines changed

packages/react/src/components/presentation/SignIn/v2/BaseSignIn.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import useFlow from '../../../../contexts/Flow/useFlow';
3535
import FlowProvider from '../../../../contexts/Flow/FlowProvider';
3636
import {FormField, useForm} from '../../../../hooks/useForm';
3737
import {renderSignInComponents} from './SignInOptionFactory';
38-
import {extractErrorMessage} from '../../SignUp/v2/transformer';
38+
import {extractErrorMessage} from '../../../../utils/v2/flowTransformer';
3939
import getAuthComponentHeadings from '../../../../utils/getAuthComponentHeadings';
4040

4141
/**

packages/react/src/components/presentation/SignIn/v2/SignIn.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import {
2828
EmbeddedSignInFlowStatusV2,
2929
EmbeddedSignInFlowTypeV2,
3030
} from '@asgardeo/browser';
31-
import {normalizeFlowResponse} from './transformer';
31+
import {normalizeFlowResponse} from '../../../../utils/v2/flowTransformer';
3232
import useTranslation from '../../../../hooks/useTranslation';
3333

3434
/**

packages/react/src/components/presentation/SignIn/v2/transformer.ts

Lines changed: 0 additions & 53 deletions
This file was deleted.

packages/react/src/components/presentation/SignUp/v2/BaseSignUp.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import {
2727
import {cx} from '@emotion/css';
2828
import {FC, ReactElement, ReactNode, useEffect, useState, useCallback, useRef} from 'react';
2929
import {renderSignUpComponents} from './SignUpOptionFactory';
30-
import {normalizeFlowResponse, extractErrorMessage} from './transformer';
30+
import {normalizeFlowResponse, extractErrorMessage} from '../../../../utils/v2/flowTransformer';
3131
import FlowProvider from '../../../../contexts/Flow/FlowProvider';
3232
import useFlow from '../../../../contexts/Flow/useFlow';
3333
import {useForm, FormField} from '../../../../hooks/useForm';
@@ -300,7 +300,9 @@ const BaseSignUpContent: FC<BaseSignUpProps> = ({
300300
// Use the transformer to handle meta.components structure
301301
if (response?.data) {
302302
try {
303-
const {components} = normalizeFlowResponse(response, t);
303+
const {components} = normalizeFlowResponse(response, t, {
304+
defaultErrorKey: 'components.signUp.errors.generic',
305+
});
304306

305307
return {
306308
...response,

packages/react/src/components/presentation/SignUp/v2/transformer.ts

Lines changed: 0 additions & 87 deletions
This file was deleted.
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/**
2+
* Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
3+
*
4+
* WSO2 LLC. licenses this file to you under the Apache License,
5+
* Version 2.0 (the "License"); you may not use this file except
6+
* in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing,
12+
* software distributed under the License is distributed on an
13+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
* KIND, either express or implied. See the License for the
15+
* specific language governing permissions and limitations
16+
* under the License.
17+
*/
18+
19+
/**
20+
* @fileoverview Shared flow response transformer utilities for v2 embedded flows.
21+
*
22+
* This module provides reusable transformation functions for normalizing embedded flow
23+
* responses from Asgardeo APIs. It handles both successful responses with component
24+
* extraction and error responses with proper error message extraction.
25+
*
26+
* Key features:
27+
* - Component extraction from flow meta structure
28+
* - Translation string resolution in components
29+
* - Error response detection and message extraction
30+
* - Configurable error handling (throw vs return errors)
31+
*
32+
* Usage:
33+
* ```typescript
34+
* import { normalizeFlowResponse } from '../../../utils/v2/flowTransformer';
35+
*
36+
* const { flowId, components } = normalizeFlowResponse(apiResponse, t, {
37+
* defaultErrorKey: 'components.signIn.errors.generic'
38+
* });
39+
* ```
40+
*
41+
* This transformer is used by both SignIn and SignUp v2 components to ensure
42+
* consistent response handling across all embedded flows.
43+
*/
44+
45+
import {
46+
EmbeddedFlowComponentV2 as EmbeddedFlowComponent,
47+
EmbeddedSignUpFlowErrorResponseV2 as EmbeddedSignUpFlowErrorResponse,
48+
} from '@asgardeo/browser';
49+
import {UseTranslation} from '../../hooks/useTranslation';
50+
import resolveTranslationsInArray from './resolveTranslationsInArray';
51+
52+
/**
53+
* Generic flow error response interface that covers common error structure
54+
*/
55+
export interface FlowErrorResponse {
56+
flowId: string;
57+
flowStatus: 'ERROR';
58+
failureReason?: string;
59+
}
60+
61+
/**
62+
* Configuration options for flow transformation
63+
*/
64+
export interface FlowTransformOptions {
65+
/**
66+
* Whether to throw errors or return them as normalized response
67+
* @default true
68+
*/
69+
throwOnError?: boolean;
70+
/**
71+
* Default error message key for translation fallback
72+
* @default 'errors.flow.generic'
73+
*/
74+
defaultErrorKey?: string;
75+
}
76+
77+
/**
78+
* Transform and resolve translations in components from flow response.
79+
* This function extracts components from the response meta structure and resolves
80+
* any translation strings within them.
81+
*
82+
* @param response - The flow response object containing components in meta structure
83+
* @param t - Translation function from useTranslation hook
84+
* @returns Array of flow components with resolved translations
85+
*/
86+
export const transformComponents = (response: any, t: UseTranslation['t']): EmbeddedFlowComponent[] => {
87+
if (!response?.data?.meta?.components) {
88+
return [];
89+
}
90+
91+
const components: EmbeddedFlowComponent[] = response.data.meta.components;
92+
93+
return resolveTranslationsInArray(components, t);
94+
};
95+
96+
/**
97+
* Extract error message from flow error response.
98+
* Supports any flow error response that follows the standard structure.
99+
*
100+
* @param error - The error response object
101+
* @param t - Translation function for fallback messages
102+
* @param defaultErrorKey - Default translation key for generic errors
103+
* @returns Extracted error message or fallback
104+
*/
105+
export const extractErrorMessage = (
106+
error: FlowErrorResponse | any,
107+
t: UseTranslation['t'],
108+
defaultErrorKey: string = 'errors.flow.generic',
109+
): string => {
110+
if (error && typeof error === 'object' && error.failureReason) {
111+
return error.failureReason;
112+
}
113+
114+
// Fallback to a generic error message
115+
return t(defaultErrorKey);
116+
};
117+
118+
/**
119+
* Check if a response is an error response and extract the error message.
120+
* This function identifies error responses by checking for ERROR status and failure reasons.
121+
*
122+
* @param response - The flow response to check
123+
* @param t - Translation function for error messages
124+
* @param defaultErrorKey - Default translation key for generic errors
125+
* @returns Error message string if response is an error, null otherwise
126+
*/
127+
export const checkForErrorResponse = (
128+
response: any,
129+
t: UseTranslation['t'],
130+
defaultErrorKey: string = 'errors.flow.generic',
131+
): string | null => {
132+
if (response?.flowStatus === 'ERROR') {
133+
return extractErrorMessage(response, t, defaultErrorKey);
134+
}
135+
136+
return null;
137+
};
138+
139+
/**
140+
* Generic flow response normalizer that handles both success and error responses.
141+
* This is the main transformer function that should be used by all flow components.
142+
*
143+
* @param response - The raw flow response from the API
144+
* @param t - Translation function from useTranslation hook
145+
* @param options - Configuration options for transformation behavior
146+
* @returns Normalized flow response with flowId and transformed components
147+
* @throws {any} The original response if it's an error and throwOnError is true
148+
*/
149+
export const normalizeFlowResponse = (
150+
response: any,
151+
t: UseTranslation['t'],
152+
options: FlowTransformOptions = {},
153+
): {
154+
flowId: string;
155+
components: EmbeddedFlowComponent[];
156+
} => {
157+
const {throwOnError = true, defaultErrorKey = 'errors.flow.generic'} = options;
158+
159+
// Check if this is an error response
160+
const errorMessage: string | null = checkForErrorResponse(response, t, defaultErrorKey);
161+
162+
if (errorMessage && throwOnError) {
163+
// Throw the original response so it can be caught by error handling
164+
throw response;
165+
}
166+
167+
return {
168+
flowId: response.flowId,
169+
components: transformComponents(response, t),
170+
};
171+
};

0 commit comments

Comments
 (0)