@tailor-platform/app-shell 0.25.0 → 0.26.1

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.
package/dist/index.d.ts CHANGED
@@ -1,6 +1,5 @@
1
- import { AuthState } from '@tailor-platform/auth-browser-client';
1
+ import { AuthClient } from '@tailor-platform/auth-public-client';
2
2
  import { ClassProp } from 'class-variance-authority/types';
3
- import { DocumentNode } from 'graphql';
4
3
  import { JSX } from 'react/jsx-runtime';
5
4
  import { Link } from 'react-router';
6
5
  import { LoaderFunctionArgs } from 'react-router';
@@ -147,37 +146,19 @@ export declare type AppShellProps = React.PropsWithChildren<{
147
146
  export declare interface AppShellRegister {
148
147
  }
149
148
 
150
- declare type AuthContextType = {
151
- /**
152
- * Current authentication state.
153
- */
154
- authState: AuthState<User>;
155
- /**
156
- * Initiates the login process.
157
- *
158
- * This redirects the user to the Tailor Platform authentication page.
159
- */
160
- login: () => Promise<void>;
161
- /**
162
- * Logs out the current user.
163
- *
164
- * This clears the authentication tokens and user session.
165
- */
166
- logout: () => Promise<void>;
167
- /**
168
- * Checks the current authentication status.
169
- *
170
- * Remember that this method always makes a network request to verify the auth status.
171
- * If the user is authenticated, returns the user information and updates `authState` in the context.
172
- *
173
- * This also attempts to refresh tokens internally if they are expired.
174
- */
175
- checkAuthStatus: () => Promise<AuthState<User>>;
176
- /**
177
- * OAuth callback handler.
178
- */
179
- handleCallback: () => Promise<void>;
180
- };
149
+ export { AuthClient }
150
+
151
+ /**
152
+ * Configuration for creating an enhanced auth client
153
+ */
154
+ export declare interface AuthClientConfig {
155
+ /** OAuth client ID */
156
+ clientId: string;
157
+ /** Authorization server base URL (e.g., https://your-app.erp.dev) */
158
+ appUri: string;
159
+ /** Redirect URI after authorization (default: window.location.origin) */
160
+ redirectUri?: string;
161
+ }
181
162
 
182
163
  /**
183
164
  * Authentication provider component.
@@ -186,14 +167,17 @@ declare type AuthContextType = {
186
167
  *
187
168
  * @example
188
169
  * ```tsx
189
- * import { AuthProvider } from "@tailor-platform/app-shell";
170
+ * import { createAuthClient, AuthProvider } from "@tailor-platform/app-shell";
171
+ *
172
+ * // Create the auth client outside of the component
173
+ * const authClient = createAuthClient({
174
+ * clientId: "your-client-id",
175
+ * appUri: "https://xyz.erp.dev",
176
+ * });
190
177
  *
191
178
  * function App() {
192
179
  * return (
193
- * <AuthProvider
194
- * apiEndpoint="https://xyz.erp.dev"
195
- * clientId="your-client-id"
196
- * >
180
+ * <AuthProvider client={authClient}>
197
181
  * <YourAppComponents />
198
182
  * </AuthProvider>
199
183
  * );
@@ -204,39 +188,10 @@ export declare const AuthProvider: (props: React.PropsWithChildren<AuthProviderP
204
188
 
205
189
  declare type AuthProviderProps = {
206
190
  /**
207
- * API endpoint of your Tailor Platform application. No `/query` suffix needed.
208
- *
209
- * @example https://xyz.erp.dev
191
+ * The EnhancedAuthClient instance created with createAuthClient from @tailor-platform/app-shell.
192
+ * This allows you to initialize the client outside the component.
210
193
  */
211
- apiEndpoint: string;
212
- /**
213
- * OAuth2 Client ID of your Tailor Platform application.
214
- */
215
- clientId: string;
216
- /**
217
- * GraphQL query to fetch the current authenticated user.
218
- *
219
- * The result of this query should return the user object.
220
- * If you override `AuthRegister["user"]`, make sure to have the fields match your custom user type.
221
- *
222
- * @defaults
223
- * ```graphql
224
- * query {
225
- * me {
226
- * id
227
- * email
228
- * name
229
- * }
230
- * }
231
- * ```
232
- */
233
- meQuery?: string | DocumentNode;
234
- /**
235
- * Redirect URI after login is successful.
236
- *
237
- * @defaults `window.location.origin`
238
- */
239
- redirectUri?: string;
194
+ client: EnhancedAuthClient;
240
195
  /**
241
196
  * Enable automatic login on initialization.
242
197
  */
@@ -250,24 +205,24 @@ declare type AuthProviderProps = {
250
205
  };
251
206
 
252
207
  /**
253
- * Registerable interface for type extension via module augmentation.
208
+ * Authentication state.
254
209
  *
255
- * @example
256
- * // In your project's TypeScript file (e.g., app-shell.d.ts, App.tsx, etc.)
257
- * declare module "@tailor-platform/app-shell" {
258
- * interface AuthRegister {
259
- * user: {
260
- * id: string;
261
- * email: string;
262
- * name?: string;
263
- * role: "admin" | "user";
264
- * organizationId: string;
265
- * }
266
- * }
267
- * }
210
+ * This type matches the AuthState from @tailor-platform/auth-public-client.
268
211
  */
269
- export declare interface AuthRegister {
270
- }
212
+ export declare type AuthState = {
213
+ /**
214
+ * Whether the user is authenticated.
215
+ */
216
+ isAuthenticated: boolean;
217
+ /**
218
+ * Error message if authentication failed.
219
+ */
220
+ error: string | null;
221
+ /**
222
+ * Whether the initial authentication check has completed.
223
+ */
224
+ isReady: boolean;
225
+ };
271
226
 
272
227
  export declare function Badge({ className, variant, children, ...props }: BadgeProps): JSX.Element;
273
228
 
@@ -364,6 +319,8 @@ export declare type ContextData = AppShellRegister extends {
364
319
  contextData: infer T;
365
320
  } ? T : Record<string, unknown>;
366
321
 
322
+ export declare function createAuthClient(config: AuthClientConfig): EnhancedAuthClient;
323
+
367
324
  /**
368
325
  * Date format options
369
326
  */
@@ -376,26 +333,6 @@ declare type DefaultSidebarProps = {
376
333
  footer?: React.ReactNode;
377
334
  };
378
335
 
379
- /**
380
- * Default user type when no custom user type is registered.
381
- *
382
- * You can extend this type via module augmentation:
383
- * @example
384
- * declare module "@tailor-platform/app-shell" {
385
- * interface Register {
386
- * user: DefaultUser & {
387
- * role: "admin" | "user";
388
- * organizationId: string;
389
- * }
390
- * }
391
- * }
392
- */
393
- export declare type DefaultUser = {
394
- id: string;
395
- email: string;
396
- name?: string;
397
- };
398
-
399
336
  /**
400
337
  * Defines internationalization labels for multiple locales.
401
338
  *
@@ -628,6 +565,27 @@ declare type DynamicLocales<Def extends Record<string, LabelValue>> = {
628
565
  */
629
566
  declare type EmptyBehavior = "dash" | "hide";
630
567
 
568
+ /**
569
+ * Enhanced auth client with additional helper methods
570
+ */
571
+ export declare interface EnhancedAuthClient extends AuthClient {
572
+ /**
573
+ * Get the appUri used to create this client
574
+ */
575
+ getAppUri(): string;
576
+ /**
577
+ * Get Authorization and DPoP headers for protected resource requests.
578
+ * This version automatically uses the appUri for the /query endpoint.
579
+ *
580
+ * @param path - Optional path to append to appUri (default: "/query")
581
+ * @param method - HTTP method (default: "POST")
582
+ */
583
+ getAuthHeadersForQuery(path?: string, method?: string): Promise<{
584
+ Authorization: string;
585
+ DPoP: string;
586
+ }>;
587
+ }
588
+
631
589
  /**
632
590
  * Error boundary element type for route error handling.
633
591
  *
@@ -976,7 +934,92 @@ export declare const useAppShellConfig: () => AppShellConfigContextType;
976
934
  */
977
935
  export declare const useAppShellData: () => AppShellDataContextType;
978
936
 
979
- export declare const useAuth: () => AuthContextType;
937
+ /**
938
+ * Authentication hook.
939
+ *
940
+ * Returns authentication state and methods. Use `isReady` to check if
941
+ * the initial authentication check has completed before rendering
942
+ * authenticated content.
943
+ *
944
+ * @example
945
+ * ```tsx
946
+ * function MyComponent() {
947
+ * const { isAuthenticated, isReady, login, logout } = useAuth();
948
+ *
949
+ * if (!isReady) return <Loading />;
950
+ * if (!isAuthenticated) return <button onClick={login}>Log In</button>;
951
+ *
952
+ * return <button onClick={logout}>Log Out</button>;
953
+ * }
954
+ * ```
955
+ */
956
+ export declare const useAuth: () => {
957
+ error: string | null;
958
+ isAuthenticated: boolean;
959
+ isReady: boolean;
960
+ login: () => Promise<void>;
961
+ logout: () => Promise<void>;
962
+ checkAuthStatus: () => Promise<AuthState>;
963
+ };
964
+
965
+ /**
966
+ * Suspense-compatible authentication hook.
967
+ *
968
+ * This hook integrates with React Suspense by throwing a promise while
969
+ * the authentication state is loading. Use this hook when you want to
970
+ * leverage Suspense boundaries for loading states.
971
+ *
972
+ * This uses the `ready()` function from the underlying auth client, which
973
+ * returns a Promise that resolves when the initial authentication check has completed.
974
+ *
975
+ * @throws {Promise} Throws a promise while authentication is loading
976
+ * @throws {Error} Throws an error if used outside AuthProvider
977
+ *
978
+ * @example
979
+ * ```tsx
980
+ * import { Suspense } from 'react';
981
+ * import { createAuthClient, AuthProvider, useAuthSuspense } from '@tailor-platform/app-shell';
982
+ *
983
+ * const authClient = createAuthClient({
984
+ * clientId: 'your-client-id',
985
+ * appUri: 'https://api.example.com',
986
+ * });
987
+ *
988
+ * function App() {
989
+ * return (
990
+ * <AuthProvider client={authClient}>
991
+ * <Suspense fallback={<div>Loading authentication...</div>}>
992
+ * <ProtectedContent />
993
+ * </Suspense>
994
+ * </AuthProvider>
995
+ * );
996
+ * }
997
+ *
998
+ * function ProtectedContent() {
999
+ * const { isAuthenticated, login, logout } = useAuthSuspense();
1000
+ *
1001
+ * // isReady is guaranteed to be true here (Suspense handles loading)
1002
+ *
1003
+ * if (!isAuthenticated) {
1004
+ * return <button onClick={login}>Log In</button>;
1005
+ * }
1006
+ *
1007
+ * return (
1008
+ * <div>
1009
+ * <p>Welcome!</p>
1010
+ * <button onClick={logout}>Log Out</button>
1011
+ * </div>
1012
+ * );
1013
+ * }
1014
+ * ```
1015
+ */
1016
+ export declare const useAuthSuspense: () => {
1017
+ error: string | null;
1018
+ isAuthenticated: boolean;
1019
+ login: () => Promise<void>;
1020
+ logout: () => Promise<void>;
1021
+ checkAuthStatus: () => Promise<AuthState>;
1022
+ };
980
1023
 
981
1024
  export { useLocation }
982
1025
 
@@ -984,16 +1027,6 @@ export { useNavigate }
984
1027
 
985
1028
  export { useParams }
986
1029
 
987
- /**
988
- * User type that can be extended via the AuthRegister interface.
989
- *
990
- * If `AuthRegister["user"]` is defined, it will be used as the User type.
991
- * Otherwise, the DefaultUser type will be used.
992
- */
993
- declare type User = AuthRegister extends {
994
- user: infer TUser;
995
- } ? TUser : DefaultUser;
996
-
997
1030
  export { useRouteError }
998
1031
 
999
1032
  export { useSearchParams }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tailor-platform/app-shell",
3
- "version": "0.25.0",
3
+ "version": "0.26.1",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./styles": "./dist/app-shell.css",
@@ -28,7 +28,7 @@
28
28
  "@radix-ui/react-separator": "^1.1.8",
29
29
  "@radix-ui/react-slot": "^1.2.4",
30
30
  "@radix-ui/react-tooltip": "^1.2.8",
31
- "@tailor-platform/auth-browser-client": "^0.3.0",
31
+ "@tailor-platform/auth-public-client": "^0.4.0",
32
32
  "@tanstack/react-table": "^8.21.2",
33
33
  "change-case": "^5.4.4",
34
34
  "class-variance-authority": "^0.7.1",