@tailor-platform/app-shell 0.18.0 → 0.19.0

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,7 @@
1
+ import { AuthState } from '@tailor-platform/auth-browser-client';
2
+ import { DocumentNode } from 'graphql';
1
3
  import { JSX } from 'react/jsx-runtime';
2
4
  import { Link } from 'react-router';
3
- import { PropsWithChildren } from 'react';
4
5
  import { ReactNode } from 'react';
5
6
  import { useLocation } from 'react-router';
6
7
  import { useNavigate } from 'react-router';
@@ -89,32 +90,127 @@ export declare type AppShellProps = React.PropsWithChildren<{
89
90
  errorBoundary?: ErrorBoundaryComponent;
90
91
  }>;
91
92
 
93
+ declare type AuthContextType = {
94
+ /**
95
+ * Current authentication state.
96
+ */
97
+ authState: AuthState<User>;
98
+ /**
99
+ * Initiates the login process.
100
+ *
101
+ * This redirects the user to the Tailor Platform authentication page.
102
+ */
103
+ login: () => Promise<void>;
104
+ /**
105
+ * Logs out the current user.
106
+ *
107
+ * This clears the authentication tokens and user session.
108
+ */
109
+ logout: () => Promise<void>;
110
+ /**
111
+ * Checks the current authentication status.
112
+ *
113
+ * Remember that this method always makes a network request to verify the auth status.
114
+ * If the user is authenticated, returns the user information and updates `authState` in the context.
115
+ *
116
+ * This also attempts to refresh tokens internally if they are expired.
117
+ */
118
+ checkAuthStatus: () => Promise<AuthState<User>>;
119
+ /**
120
+ * OAuth callback handler.
121
+ */
122
+ handleCallback: () => Promise<void>;
123
+ };
124
+
92
125
  /**
93
- * We need to build a Login URL with the correct parameters to redirect
94
- * to our OAuth endpoint login page
126
+ * Authentication provider component.
127
+ *
128
+ * Wrap your application with this component to provide authentication context.
129
+ *
130
+ * @example
131
+ * ```tsx
132
+ * import { AuthProvider } from "@tailor-platform/app-shell";
133
+ *
134
+ * function App() {
135
+ * return (
136
+ * <AuthProvider
137
+ * apiEndpoint="https://xyz.erp.dev"
138
+ * clientId="your-client-id"
139
+ * >
140
+ * <YourAppComponents />
141
+ * </AuthProvider>
142
+ * );
143
+ * }
144
+ * ```
95
145
  */
96
- export declare const buildAuthorizationUrl: ({ apiEndpoint, clientId, state, codeChallenge, redirectUri, }: BuildAuthorizationUrlParams) => string;
146
+ export declare const AuthProvider: (props: React.PropsWithChildren<AuthProviderProps>) => JSX.Element;
97
147
 
98
- declare interface BuildAuthorizationUrlParams {
148
+ declare type AuthProviderProps = {
149
+ /**
150
+ * API endpoint of your Tailor Platform application. No `/query` suffix needed.
151
+ *
152
+ * @example https://xyz.erp.dev
153
+ */
99
154
  apiEndpoint: string;
155
+ /**
156
+ * OAuth2 Client ID of your Tailor Platform application.
157
+ */
100
158
  clientId: string;
101
- state: string;
102
- codeChallenge: string;
159
+ /**
160
+ * GraphQL query to fetch the current authenticated user.
161
+ *
162
+ * The result of this query should return the user object.
163
+ * If you override `AuthRegister["user"]`, make sure to have the fields match your custom user type.
164
+ *
165
+ * @defaults
166
+ * ```graphql
167
+ * query {
168
+ * me {
169
+ * id
170
+ * email
171
+ * name
172
+ * }
173
+ * }
174
+ * ```
175
+ */
176
+ meQuery?: string | DocumentNode;
177
+ /**
178
+ * Redirect URI after login is successful.
179
+ *
180
+ * @defaults `window.location.origin`
181
+ */
103
182
  redirectUri?: string;
104
- }
105
-
106
- declare interface BuiltinIdPAuthContextType {
107
183
  /**
108
- * Initiates the login process by redirecting to the OAuth2 authorization endpoint.
184
+ * Enable automatic login on initialization.
109
185
  */
110
- login: () => Promise<void>;
186
+ autoLogin?: boolean;
111
187
  /**
112
- * Logs out the user by revoking the token and clearing session data.
188
+ * Guard UI component to show when loading or unauthenticated.
189
+ *
190
+ * If not provided, children will be just rendered in any auth state.
113
191
  */
114
- logout: () => Promise<void>;
115
- }
192
+ guardComponent?: () => React.ReactNode;
193
+ };
116
194
 
117
- export declare const BuiltinIdPAuthProvider: ({ apiEndpoint, clientId, redirectUri, children, }: PropsWithChildren<Props>) => JSX.Element;
195
+ /**
196
+ * Registerable interface for type extension via module augmentation.
197
+ *
198
+ * @example
199
+ * // In your project's TypeScript file (e.g., app-shell.d.ts, App.tsx, etc.)
200
+ * declare module "@tailor-platform/app-shell" {
201
+ * interface AuthRegister {
202
+ * user: {
203
+ * id: string;
204
+ * email: string;
205
+ * name?: string;
206
+ * role: "admin" | "user";
207
+ * organizationId: string;
208
+ * }
209
+ * }
210
+ * }
211
+ */
212
+ export declare interface AuthRegister {
213
+ }
118
214
 
119
215
  declare type CommonModuleProps = {
120
216
  /**
@@ -157,6 +253,26 @@ declare type DefaultSidebarProps = {
157
253
  footer?: React.ReactNode;
158
254
  };
159
255
 
256
+ /**
257
+ * Default user type when no custom user type is registered.
258
+ *
259
+ * You can extend this type via module augmentation:
260
+ * @example
261
+ * declare module "@tailor-platform/app-shell" {
262
+ * interface Register {
263
+ * user: DefaultUser & {
264
+ * role: "admin" | "user";
265
+ * organizationId: string;
266
+ * }
267
+ * }
268
+ * }
269
+ */
270
+ export declare type DefaultUser = {
271
+ id: string;
272
+ email: string;
273
+ name?: string;
274
+ };
275
+
160
276
  /**
161
277
  * Defines internationalization labels for multiple locales.
162
278
  *
@@ -353,33 +469,6 @@ declare type DynamicLocales<Def extends Record<string, LabelValue>> = {
353
469
  */
354
470
  export declare type ErrorBoundaryComponent = ReactNode;
355
471
 
356
- /**
357
- * We need to exchange the code and state we received from the OAuth endpoint
358
- * for an actual authorization token, in Browser Client case, we get the token
359
- * inside of a cookie so there is nothing else to do beyond that point
360
- */
361
- export declare const exchangeCodeForToken: ({ code, returnedState, apiEndpoint, clientId, redirectUri, }: ExchangeCodeForTokenParams) => Promise<string>;
362
-
363
- declare interface ExchangeCodeForTokenParams {
364
- apiEndpoint: string;
365
- clientId: string;
366
- returnedState: string | null;
367
- code: string | null;
368
- redirectUri?: string;
369
- silent?: boolean;
370
- }
371
-
372
- /**
373
- * When redirected from our IdP Provider, we need to exchange code and state
374
- * for a token and clean up the URL params
375
- */
376
- export declare const handleOAuthCallback: ({ currentUrl, apiEndpoint, clientId, redirectUri, }: {
377
- currentUrl: URL;
378
- apiEndpoint: string;
379
- clientId: string;
380
- redirectUri: string;
381
- }) => Promise<void>;
382
-
383
472
  export declare type I18nLabels<Def extends Record<string, LabelValue> = Record<string, LabelValue>, L extends string = never> = {
384
473
  en: Def;
385
474
  } & {
@@ -432,38 +521,6 @@ declare type NavItem = {
432
521
  items?: Array<NavChildItem>;
433
522
  };
434
523
 
435
- export declare const OAUTH_STATE_KEY = "oauth_state";
436
-
437
- export declare const PKCE_VERIFIER_KEY = "oauth_pkce_verifier";
438
-
439
- /**
440
- * We need to generate a challenge and state key for OAuth login
441
- * and stores them in sessionStorage for verification on callback redirect
442
- */
443
- export declare const prepareLogin: () => Promise<{
444
- codeChallenge: string;
445
- state: string;
446
- }>;
447
-
448
- declare type Props = {
449
- /**
450
- * API endpoint of your Tailor Platform application. No `/query` suffix needed.
451
- *
452
- * @example https://xyz.erp.dev
453
- */
454
- apiEndpoint: string;
455
- /**
456
- * OAuth2 Client ID of your Tailor Platform application.
457
- */
458
- clientId: string;
459
- /**
460
- * Redirect URI after login is successful.
461
- *
462
- * @defaults `window.location.origin`
463
- */
464
- redirectUri?: string;
465
- };
466
-
467
524
  declare type ReactResourceProps = {
468
525
  /**
469
526
  * React component to render.
@@ -555,7 +612,7 @@ declare type ThemeProviderState = {
555
612
 
556
613
  export declare const useAppShell: () => AppShellContextType;
557
614
 
558
- export declare const useBuiltinIdpAuth: () => BuiltinIdPAuthContextType;
615
+ export declare const useAuth: () => AuthContextType;
559
616
 
560
617
  export { useLocation }
561
618
 
@@ -563,6 +620,16 @@ export { useNavigate }
563
620
 
564
621
  export { useParams }
565
622
 
623
+ /**
624
+ * User type that can be extended via the AuthRegister interface.
625
+ *
626
+ * If `AuthRegister["user"]` is defined, it will be used as the User type.
627
+ * Otherwise, the DefaultUser type will be used.
628
+ */
629
+ declare type User = AuthRegister extends {
630
+ user: infer TUser;
631
+ } ? TUser : DefaultUser;
632
+
566
633
  export { useRouteError }
567
634
 
568
635
  export { useSearchParams }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tailor-platform/app-shell",
3
- "version": "0.18.0",
3
+ "version": "0.19.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./styles": "./dist/app-shell.css",
@@ -22,21 +22,21 @@
22
22
  "@radix-ui/react-checkbox": "^1.3.3",
23
23
  "@radix-ui/react-collapsible": "^1.1.3",
24
24
  "@radix-ui/react-dialog": "^1.1.15",
25
- "@radix-ui/react-dropdown-menu": "^2.1.6",
25
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
26
26
  "@radix-ui/react-label": "^2.1.8",
27
27
  "@radix-ui/react-navigation-menu": "^1.2.5",
28
28
  "@radix-ui/react-popover": "^1.1.6",
29
29
  "@radix-ui/react-select": "^2.1.6",
30
30
  "@radix-ui/react-separator": "^1.1.8",
31
- "@radix-ui/react-slot": "^1.1.2",
31
+ "@radix-ui/react-slot": "^1.2.4",
32
32
  "@radix-ui/react-tooltip": "^1.1.8",
33
+ "@tailor-platform/auth-browser-client": "^0.3.0",
33
34
  "@tanstack/react-table": "^8.21.2",
34
- "@urql/core": "^6.0.0",
35
- "@urql/exchange-auth": "^3.0.0",
36
35
  "change-case": "^5.4.4",
37
36
  "class-variance-authority": "^0.7.1",
38
37
  "clsx": "^2.1.1",
39
38
  "es-toolkit": "^1.41.0",
39
+ "graphql": "^16.12.0",
40
40
  "lucide-react": "^0.487.0",
41
41
  "next-themes": "^0.4.6",
42
42
  "oauth4webapi": "^3.8.1",
@@ -45,8 +45,7 @@
45
45
  "react-hook-form": "^7.54.2",
46
46
  "react-router": "^7.4.0",
47
47
  "sonner": "^2.0.7",
48
- "tailwind-merge": "^3.4.0",
49
- "urql": "^5.0.1"
48
+ "tailwind-merge": "^3.4.0"
50
49
  },
51
50
  "devDependencies": {
52
51
  "@tailwindcss/postcss": "^4.1.2",
@@ -54,9 +53,8 @@
54
53
  "@types/node": "^22",
55
54
  "@types/react": "^19",
56
55
  "@types/react-dom": "^19",
57
- "happy-dom": "^20.0.11",
58
56
  "@vitejs/plugin-react": "^5.1.1",
59
- "msw": "^2.11.2",
57
+ "happy-dom": "^20.0.11",
60
58
  "postcss": "^8",
61
59
  "prettier": "^3.6.2",
62
60
  "tailwindcss": "^4.1.3",