Skip to content

Commit cd01943

Browse files
authored
Merge pull request #92 from brionmario/next
fix(nextjs): fix issues with server provider
2 parents 1fc71bd + 1ce6a26 commit cd01943

File tree

9 files changed

+136
-110
lines changed

9 files changed

+136
-110
lines changed

.changeset/early-boxes-hide.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@asgardeo/nextjs': patch
3+
'@asgardeo/react': patch
4+
---
5+
6+
Fix issues in next components

packages/nextjs/src/client/components/presentation/CreateOrganization/CreateOrganization.tsx

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,11 @@
1818

1919
'use client';
2020

21-
import {FC, ReactElement, useState} from 'react';
22-
21+
import {CreateOrganizationPayload, AsgardeoRuntimeError} from '@asgardeo/node';
2322
import {BaseCreateOrganization, BaseCreateOrganizationProps, useOrganization} from '@asgardeo/react';
24-
import {CreateOrganizationPayload} from '@asgardeo/node';
25-
import useAsgardeo from '../../../contexts/Asgardeo/useAsgardeo';
26-
import createOrganizationAction from '../../../../server/actions/createOrganizationAction';
23+
import {FC, ReactElement, useState} from 'react';
2724
import getSessionId from '../../../../server/actions/getSessionId';
25+
import useAsgardeo from '../../../contexts/Asgardeo/useAsgardeo';
2826

2927
/**
3028
* Props interface for the CreateOrganization component.
@@ -80,7 +78,7 @@ export const CreateOrganization: FC<CreateOrganizationProps> = ({
8078
...props
8179
}: CreateOrganizationProps): ReactElement => {
8280
const {isSignedIn, baseUrl} = useAsgardeo();
83-
const {currentOrganization, revalidateMyOrganizations} = useOrganization();
81+
const {currentOrganization, revalidateMyOrganizations, createOrganization} = useOrganization();
8482
const [loading, setLoading] = useState(false);
8583
const [error, setError] = useState<string | null>(null);
8684

@@ -104,14 +102,22 @@ export const CreateOrganization: FC<CreateOrganizationProps> = ({
104102
let result: any;
105103

106104
if (onCreateOrganization) {
107-
// Use the provided custom creation function
108105
result = await onCreateOrganization(payload);
109106
} else {
110-
// Use the default API
111107
if (!baseUrl) {
112108
throw new Error('Base URL is required for organization creation');
113109
}
114-
result = await createOrganizationAction(
110+
111+
if (!createOrganization) {
112+
throw new AsgardeoRuntimeError(
113+
`createOrganization function is not available.`,
114+
'CreateOrganization-handleSubmit-RuntimeError-001',
115+
'nextjs',
116+
'The createOrganization function must be provided by the Organization context.',
117+
);
118+
}
119+
120+
result = await createOrganization(
115121
{
116122
...payload,
117123
parentId,
@@ -121,7 +127,9 @@ export const CreateOrganization: FC<CreateOrganizationProps> = ({
121127
}
122128

123129
// Refresh organizations list to include the new organization
124-
await revalidateMyOrganizations();
130+
if (revalidateMyOrganizations) {
131+
await revalidateMyOrganizations();
132+
}
125133

126134
// Call success callback if provided
127135
if (onSuccess) {

packages/nextjs/src/client/contexts/Asgardeo/AsgardeoProvider.tsx

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
import {
2222
AllOrganizationsApiResponse,
23-
AsgardeoRuntimeError,
2423
EmbeddedFlowExecuteRequestConfig,
2524
EmbeddedFlowExecuteRequestPayload,
2625
EmbeddedSignInFlowHandleRequestPayload,
@@ -30,6 +29,8 @@ import {
3029
User,
3130
UserProfile,
3231
BrandingPreference,
32+
TokenResponse,
33+
CreateOrganizationPayload,
3334
} from '@asgardeo/node';
3435
import {
3536
I18nProvider,
@@ -40,38 +41,39 @@ import {
4041
OrganizationProvider,
4142
BrandingProvider,
4243
} from '@asgardeo/react';
43-
import {FC, PropsWithChildren, RefObject, useEffect, useMemo, useRef, useState} from 'react';
4444
import {useRouter, useSearchParams} from 'next/navigation';
45+
import {FC, PropsWithChildren, RefObject, useEffect, useMemo, useRef, useState} from 'react';
4546
import AsgardeoContext, {AsgardeoContextProps} from './AsgardeoContext';
4647

4748
/**
4849
* Props interface of {@link AsgardeoClientProvider}
4950
*/
5051
export type AsgardeoClientProviderProps = Partial<Omit<AsgardeoProviderProps, 'baseUrl' | 'clientId'>> &
5152
Pick<AsgardeoProviderProps, 'baseUrl' | 'clientId'> & {
52-
signOut: AsgardeoContextProps['signOut'];
53-
signIn: AsgardeoContextProps['signIn'];
54-
signUp: AsgardeoContextProps['signUp'];
5553
applicationId: AsgardeoContextProps['applicationId'];
56-
organizationHandle: AsgardeoContextProps['organizationHandle'];
54+
brandingPreference?: BrandingPreference | null;
55+
createOrganization: (payload: CreateOrganizationPayload, sessionId: string) => Promise<Organization>;
56+
currentOrganization: Organization;
57+
getAllOrganizations: (options?: any, sessionId?: string) => Promise<AllOrganizationsApiResponse>;
5758
handleOAuthCallback: (
5859
code: string,
5960
state: string,
6061
sessionState?: string,
61-
) => Promise<{success: boolean; error?: string; redirectUrl?: string}>;
62+
) => Promise<{error?: string; redirectUrl?: string; success: boolean}>;
6263
isSignedIn: boolean;
63-
userProfile: UserProfile;
64-
currentOrganization: Organization;
65-
user: User | null;
64+
myOrganizations: Organization[];
65+
organizationHandle: AsgardeoContextProps['organizationHandle'];
66+
revalidateMyOrganizations?: (sessionId?: string) => Promise<Organization[]>;
67+
signIn: AsgardeoContextProps['signIn'];
68+
signOut: AsgardeoContextProps['signOut'];
69+
signUp: AsgardeoContextProps['signUp'];
70+
switchOrganization: (organization: Organization, sessionId?: string) => Promise<TokenResponse | Response>;
6671
updateProfile: (
6772
requestConfig: UpdateMeProfileConfig,
6873
sessionId?: string,
69-
) => Promise<{success: boolean; data: {user: User}; error: string}>;
70-
getAllOrganizations: (options?: any, sessionId?: string) => Promise<AllOrganizationsApiResponse>;
71-
myOrganizations: Organization[];
72-
revalidateMyOrganizations?: (sessionId?: string) => Promise<Organization[]>;
73-
brandingPreference?: BrandingPreference | null;
74-
switchOrganization: (organization: Organization, sessionId?: string) => Promise<void>;
74+
) => Promise<{data: {user: User}; error: string; success: boolean}>;
75+
user: User | null;
76+
userProfile: UserProfile;
7577
};
7678

7779
const AsgardeoClientProvider: FC<PropsWithChildren<AsgardeoClientProviderProps>> = ({
@@ -81,6 +83,7 @@ const AsgardeoClientProvider: FC<PropsWithChildren<AsgardeoClientProviderProps>>
8183
signOut,
8284
signUp,
8385
handleOAuthCallback,
86+
createOrganization,
8487
preferences,
8588
isSignedIn,
8689
signInUrl,
@@ -297,10 +300,11 @@ const AsgardeoClientProvider: FC<PropsWithChildren<AsgardeoClientProviderProps>>
297300
<FlowProvider>
298301
<UserProvider profile={userProfile} onUpdateProfile={handleProfileUpdate} updateProfile={updateProfile}>
299302
<OrganizationProvider
303+
createOrganization={createOrganization}
300304
getAllOrganizations={getAllOrganizations}
301305
myOrganizations={myOrganizations}
302306
currentOrganization={currentOrganization}
303-
onOrganizationSwitch={switchOrganization}
307+
onOrganizationSwitch={switchOrganization as any}
304308
revalidateMyOrganizations={revalidateMyOrganizations as any}
305309
>
306310
{children}

packages/nextjs/src/server/AsgardeoProvider.tsx

Lines changed: 19 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -18,34 +18,27 @@
1818

1919
'use server';
2020

21+
import {BrandingPreference, AsgardeoRuntimeError, Organization, User, UserProfile} from '@asgardeo/node';
22+
import {AsgardeoProviderProps} from '@asgardeo/react';
2123
import {FC, PropsWithChildren, ReactElement} from 'react';
22-
import {
23-
BrandingPreference,
24-
AllOrganizationsApiResponse,
25-
AsgardeoRuntimeError,
26-
Organization,
27-
User,
28-
UserProfile,
29-
IdToken,
30-
} from '@asgardeo/node';
31-
import AsgardeoClientProvider from '../client/contexts/Asgardeo/AsgardeoProvider';
32-
import AsgardeoNextClient from '../AsgardeoNextClient';
33-
import signInAction from './actions/signInAction';
34-
import signOutAction from './actions/signOutAction';
35-
import {AsgardeoNextConfig} from '../models/config';
36-
import isSignedIn from './actions/isSignedIn';
37-
import getUserAction from './actions/getUserAction';
24+
import createOrganization from './actions/createOrganization';
25+
import getAllOrganizations from './actions/getAllOrganizations';
26+
import getBrandingPreference from './actions/getBrandingPreference';
27+
import getCurrentOrganizationAction from './actions/getCurrentOrganizationAction';
28+
import getMyOrganizations from './actions/getMyOrganizations';
3829
import getSessionId from './actions/getSessionId';
30+
import getUserAction from './actions/getUserAction';
3931
import getUserProfileAction from './actions/getUserProfileAction';
40-
import signUpAction from './actions/signUpAction';
4132
import handleOAuthCallbackAction from './actions/handleOAuthCallbackAction';
42-
import {AsgardeoProviderProps} from '@asgardeo/react';
43-
import getCurrentOrganizationAction from './actions/getCurrentOrganizationAction';
44-
import updateUserProfileAction from './actions/updateUserProfileAction';
45-
import getMyOrganizations from './actions/getMyOrganizations';
46-
import getAllOrganizations from './actions/getAllOrganizations';
47-
import getBrandingPreference from './actions/getBrandingPreference';
33+
import isSignedIn from './actions/isSignedIn';
34+
import signInAction from './actions/signInAction';
35+
import signOutAction from './actions/signOutAction';
36+
import signUpAction from './actions/signUpAction';
4837
import switchOrganization from './actions/switchOrganization';
38+
import updateUserProfileAction from './actions/updateUserProfileAction';
39+
import AsgardeoNextClient from '../AsgardeoNextClient';
40+
import AsgardeoClientProvider from '../client/contexts/Asgardeo/AsgardeoProvider';
41+
import {AsgardeoNextConfig} from '../models/config';
4942

5043
/**
5144
* Props interface of {@link AsgardeoServerProvider}
@@ -150,26 +143,6 @@ const AsgardeoServerProvider: FC<PropsWithChildren<AsgardeoServerProviderProps>>
150143
}
151144
}
152145

153-
const handleGetAllOrganizations = async (
154-
options?: any,
155-
_sessionId?: string,
156-
): Promise<AllOrganizationsApiResponse> => {
157-
'use server';
158-
return await getAllOrganizations(options, sessionId);
159-
};
160-
161-
const handleSwitchOrganization = async (organization: Organization, _sessionId?: string): Promise<void> => {
162-
'use server';
163-
await switchOrganization(organization, sessionId);
164-
165-
// After switching organization, we need to refresh the page to get updated session data
166-
// This is because server components don't maintain state between function calls
167-
const {revalidatePath} = await import('next/cache');
168-
169-
// Revalidate the current path to refresh the component with new data
170-
revalidatePath('/');
171-
};
172-
173146
return (
174147
<AsgardeoClientProvider
175148
organizationHandle={config?.organizationHandle}
@@ -189,9 +162,10 @@ const AsgardeoServerProvider: FC<PropsWithChildren<AsgardeoServerProviderProps>>
189162
updateProfile={updateUserProfileAction}
190163
isSignedIn={_isSignedIn}
191164
myOrganizations={myOrganizations}
192-
getAllOrganizations={handleGetAllOrganizations}
193-
switchOrganization={handleSwitchOrganization}
165+
getAllOrganizations={getAllOrganizations}
166+
switchOrganization={switchOrganization}
194167
brandingPreference={brandingPreference}
168+
createOrganization={createOrganization}
195169
>
196170
{children}
197171
</AsgardeoClientProvider>

packages/nextjs/src/server/actions/createOrganizationAction.ts renamed to packages/nextjs/src/server/actions/createOrganization.ts

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,25 @@
1818

1919
'use server';
2020

21-
import {CreateOrganizationPayload, Organization} from '@asgardeo/node';
21+
import {CreateOrganizationPayload, Organization, AsgardeoAPIError} from '@asgardeo/node';
22+
import getSessionId from './getSessionId';
2223
import AsgardeoNextClient from '../../AsgardeoNextClient';
2324

2425
/**
2526
* Server action to create an organization.
2627
*/
27-
const createOrganizationAction = async (payload: CreateOrganizationPayload, sessionId: string) => {
28+
const createOrganization = async (payload: CreateOrganizationPayload, sessionId: string): Promise<Organization> => {
2829
try {
29-
const client = AsgardeoNextClient.getInstance();
30-
const organization: Organization = await client.createOrganization(payload, sessionId);
31-
return {success: true, data: {organization}, error: null};
30+
const client: AsgardeoNextClient = AsgardeoNextClient.getInstance();
31+
return await client.createOrganization(payload, sessionId ?? ((await getSessionId()) as string));
3232
} catch (error) {
33-
return {
34-
success: false,
35-
data: {
36-
user: {},
37-
},
38-
error: 'Failed to create organization',
39-
};
33+
throw new AsgardeoAPIError(
34+
`Failed to create the organization: ${error instanceof Error ? error.message : String(error)}`,
35+
'createOrganization-ServerActionError-001',
36+
'nextjs',
37+
error instanceof AsgardeoAPIError ? error.statusCode : undefined,
38+
);
4039
}
4140
};
4241

43-
export default createOrganizationAction;
42+
export default createOrganization;

packages/nextjs/src/server/actions/getAllOrganizations.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,20 @@
1818

1919
'use server';
2020

21-
import {AllOrganizationsApiResponse, AsgardeoAPIError, Organization} from '@asgardeo/node';
21+
import {AllOrganizationsApiResponse, AsgardeoAPIError} from '@asgardeo/node';
22+
import getSessionId from './getSessionId';
2223
import AsgardeoNextClient from '../../AsgardeoNextClient';
2324

2425
/**
2526
* Server action to get organizations.
2627
*/
27-
const getAllOrganizations = async (options?: any, sessionId?: string | undefined): Promise<AllOrganizationsApiResponse> => {
28+
const getAllOrganizations = async (
29+
options?: any,
30+
sessionId?: string | undefined,
31+
): Promise<AllOrganizationsApiResponse> => {
2832
try {
29-
const client = AsgardeoNextClient.getInstance();
30-
return client.getAllOrganizations(options, sessionId);
33+
const client: AsgardeoNextClient = AsgardeoNextClient.getInstance();
34+
return await client.getAllOrganizations(options, sessionId ?? ((await getSessionId()) as string));
3135
} catch (error) {
3236
throw new AsgardeoAPIError(
3337
`Failed to get all the organizations for the user: ${error instanceof Error ? error.message : String(error)}`,

packages/nextjs/src/server/actions/switchOrganization.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,35 @@
1818

1919
'use server';
2020

21-
import {Organization, AsgardeoAPIError, AsgardeoRuntimeError, TokenResponse} from '@asgardeo/node';
21+
import {Organization, AsgardeoAPIError, TokenResponse} from '@asgardeo/node';
22+
import getSessionId from './getSessionId';
2223
import AsgardeoNextClient from '../../AsgardeoNextClient';
2324

2425
/**
2526
* Server action to switch organization.
2627
*/
27-
const switchOrganization = async (organization: Organization, sessionId: string): Promise<TokenResponse | Response> => {
28+
const switchOrganization = async (
29+
organization: Organization,
30+
sessionId: string | undefined,
31+
): Promise<TokenResponse | Response> => {
2832
try {
29-
const client = AsgardeoNextClient.getInstance();
30-
return await client.switchOrganization(organization, sessionId);
33+
const client: AsgardeoNextClient = AsgardeoNextClient.getInstance();
34+
const response: TokenResponse | Response = await client.switchOrganization(
35+
organization,
36+
sessionId ?? ((await getSessionId()) as string),
37+
);
38+
39+
// After switching organization, we need to refresh the page to get updated session data
40+
// This is because server components don't maintain state between function calls
41+
const {revalidatePath} = await import('next/cache');
42+
43+
// Revalidate the current path to refresh the component with new data
44+
revalidatePath('/');
45+
46+
return response;
3147
} catch (error) {
3248
throw new AsgardeoAPIError(
33-
`Failed to switch the organizations: ${
34-
error instanceof AsgardeoRuntimeError ? error.message : error instanceof Error ? error.message : String(error)
35-
}`,
49+
`Failed to switch the organizations: ${error instanceof Error ? error.message : String(error)}`,
3650
'switchOrganization-ServerActionError-001',
3751
'nextjs',
3852
error instanceof AsgardeoAPIError ? error.statusCode : undefined,

0 commit comments

Comments
 (0)