@@ -14,6 +14,8 @@ import { sealData, unsealData } from 'iron-session';
14
14
import { createRemoteJWKSet , decodeJwt , jwtVerify } from 'jose' ;
15
15
import { getConfig } from './config.js' ;
16
16
import { configureSessionStorage , getSessionStorage } from './sessionStorage.js' ;
17
+ import { isResponse } from './utils.js' ;
18
+ import { isRedirect } from '../dist/cjs/utils.js' ;
17
19
18
20
// must be a type since this is a subtype of response
19
21
// interfaces must conform to the types they extend
@@ -98,22 +100,114 @@ type AuthLoader<Data> = (
98
100
99
101
type AuthorizedAuthLoader < Data > = ( args : LoaderFunctionArgs & { auth : AuthorizedData } ) => LoaderReturnValue < Data > ;
100
102
103
+ /**
104
+ * This loader handles authentication state, session management, and access token refreshing
105
+ * automatically, making it easier to build authenticated routes.
106
+ *
107
+ * Creates an authentication-aware loader function for React Router.
108
+ *
109
+ * This loader handles authentication state, session management, and access token refreshing
110
+ * automatically, making it easier to build authenticated routes.
111
+ *
112
+ * @overload
113
+ * Basic usage with enforced authentication that redirects unauthenticated users to sign in.
114
+ *
115
+ * @param loaderArgs - The loader arguments provided by React Router
116
+ * @param options - Configuration options with enforced sign-in
117
+ *
118
+ * @example
119
+ * export async function loader({ request }: LoaderFunctionArgs) {
120
+ * return authkitLoader(
121
+ * { request },
122
+ * { ensureSignedIn: true }
123
+ * );
124
+ * }
125
+ */
101
126
async function authkitLoader (
102
127
loaderArgs : LoaderFunctionArgs ,
103
128
options : AuthKitLoaderOptions & { ensureSignedIn : true } ,
104
- ) : Promise < DataWithResponseInit < AuthorizedData > | Response > ;
105
-
129
+ ) : Promise < DataWithResponseInit < AuthorizedData > > ;
130
+
131
+ /**
132
+ * This loader handles authentication state, session management, and access token refreshing
133
+ * automatically, making it easier to build authenticated routes.
134
+ *
135
+ * @overload
136
+ * Basic usage without enforced authentication, allowing both signed-in and anonymous users.
137
+ *
138
+ * @param loaderArgs - The loader arguments provided by React Router
139
+ * @param options - Optional configuration options
140
+ *
141
+ * @example
142
+ * export async function loader({ request }: LoaderFunctionArgs) {
143
+ * return authkitLoader({ request });
144
+ * }
145
+ */
106
146
async function authkitLoader (
107
147
loaderArgs : LoaderFunctionArgs ,
108
148
options ?: AuthKitLoaderOptions ,
109
149
) : Promise < DataWithResponseInit < AuthorizedData | UnauthorizedData > > ;
110
150
151
+ /**
152
+ * This loader handles authentication state, session management, and access token refreshing
153
+ * automatically, making it easier to build authenticated routes.
154
+ *
155
+ * @overload
156
+ * Custom loader with enforced authentication, providing your own loader function
157
+ * that will only be called for authenticated users.
158
+ *
159
+ * @param loaderArgs - The loader arguments provided by React Router
160
+ * @param loader - A custom loader function that receives authentication data
161
+ * @param options - Configuration options with enforced sign-in
162
+ *
163
+ * @example
164
+ * export async function loader({ request }: LoaderFunctionArgs) {
165
+ * return authkitLoader(
166
+ * { request },
167
+ * async ({ auth }) => {
168
+ * // This will only be called for authenticated users
169
+ * const userData = await fetchUserData(auth.accessToken);
170
+ * return { userData };
171
+ * },
172
+ * { ensureSignedIn: true }
173
+ * );
174
+ * }
175
+ */
111
176
async function authkitLoader < Data = unknown > (
112
177
loaderArgs : LoaderFunctionArgs ,
113
178
loader : AuthorizedAuthLoader < Data > ,
114
179
options : AuthKitLoaderOptions & { ensureSignedIn : true } ,
115
180
) : Promise < DataWithResponseInit < Data & AuthorizedData > > ;
116
181
182
+ /**
183
+ * This loader handles authentication state, session management, and access token refreshing
184
+ * automatically, making it easier to build authenticated routes.
185
+ *
186
+ * @overload
187
+ * Custom loader without enforced authentication, providing your own loader function
188
+ * that will be called for both authenticated and unauthenticated users.
189
+ *
190
+ * @param loaderArgs - The loader arguments provided by React Router
191
+ * @param loader - A custom loader function that receives authentication data
192
+ * @param options - Optional configuration options
193
+ *
194
+ * @example
195
+ * export async function loader({ request }: LoaderFunctionArgs) {
196
+ * return authkitLoader(
197
+ * { request },
198
+ * async ({ auth }) => {
199
+ * if (auth.user) {
200
+ * // User is authenticated
201
+ * const userData = await fetchUserData(auth.accessToken);
202
+ * return { userData };
203
+ * } else {
204
+ * // User is not authenticated
205
+ * return { publicData: await fetchPublicData() };
206
+ * }
207
+ * }
208
+ * );
209
+ * }
210
+ */
117
211
async function authkitLoader < Data = unknown > (
118
212
loaderArgs : LoaderFunctionArgs ,
119
213
loader : AuthLoader < Data > ,
@@ -209,10 +303,10 @@ async function handleAuthLoader(
209
303
// auth data plus session cookie header
210
304
const loaderResult = await loader ( { ...args , auth : auth as AuthorizedData } ) ;
211
305
212
- if ( loaderResult instanceof Response ) {
306
+ if ( isResponse ( loaderResult ) ) {
213
307
// If the result is a redirect, return it unedited
214
- if ( loaderResult . status >= 300 && loaderResult . status < 400 ) {
215
- return loaderResult ;
308
+ if ( isRedirect ( loaderResult ) ) {
309
+ throw loaderResult ;
216
310
}
217
311
218
312
const newResponse = new Response ( loaderResult . body , loaderResult ) ;
0 commit comments