@tailor-platform/app-shell 0.18.0 → 0.20.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,129 @@ 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>;
192
+ guardComponent?: () => React.ReactNode;
193
+ };
194
+
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 {
115
213
  }
116
214
 
117
- export declare const BuiltinIdPAuthProvider: ({ apiEndpoint, clientId, redirectUri, children, }: PropsWithChildren<Props>) => JSX.Element;
215
+ export declare function CommandPalette(): JSX.Element;
118
216
 
119
217
  declare type CommonModuleProps = {
120
218
  /**
@@ -157,6 +255,26 @@ declare type DefaultSidebarProps = {
157
255
  footer?: React.ReactNode;
158
256
  };
159
257
 
258
+ /**
259
+ * Default user type when no custom user type is registered.
260
+ *
261
+ * You can extend this type via module augmentation:
262
+ * @example
263
+ * declare module "@tailor-platform/app-shell" {
264
+ * interface Register {
265
+ * user: DefaultUser & {
266
+ * role: "admin" | "user";
267
+ * organizationId: string;
268
+ * }
269
+ * }
270
+ * }
271
+ */
272
+ export declare type DefaultUser = {
273
+ id: string;
274
+ email: string;
275
+ name?: string;
276
+ };
277
+
160
278
  /**
161
279
  * Defines internationalization labels for multiple locales.
162
280
  *
@@ -353,33 +471,6 @@ declare type DynamicLocales<Def extends Record<string, LabelValue>> = {
353
471
  */
354
472
  export declare type ErrorBoundaryComponent = ReactNode;
355
473
 
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
474
  export declare type I18nLabels<Def extends Record<string, LabelValue> = Record<string, LabelValue>, L extends string = never> = {
384
475
  en: Def;
385
476
  } & {
@@ -432,38 +523,6 @@ declare type NavItem = {
432
523
  items?: Array<NavChildItem>;
433
524
  };
434
525
 
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
526
  declare type ReactResourceProps = {
468
527
  /**
469
528
  * React component to render.
@@ -555,7 +614,7 @@ declare type ThemeProviderState = {
555
614
 
556
615
  export declare const useAppShell: () => AppShellContextType;
557
616
 
558
- export declare const useBuiltinIdpAuth: () => BuiltinIdPAuthContextType;
617
+ export declare const useAuth: () => AuthContextType;
559
618
 
560
619
  export { useLocation }
561
620
 
@@ -563,6 +622,16 @@ export { useNavigate }
563
622
 
564
623
  export { useParams }
565
624
 
625
+ /**
626
+ * User type that can be extended via the AuthRegister interface.
627
+ *
628
+ * If `AuthRegister["user"]` is defined, it will be used as the User type.
629
+ * Otherwise, the DefaultUser type will be used.
630
+ */
631
+ declare type User = AuthRegister extends {
632
+ user: infer TUser;
633
+ } ? TUser : DefaultUser;
634
+
566
635
  export { useRouteError }
567
636
 
568
637
  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.20.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./styles": "./dist/app-shell.css",
@@ -22,41 +22,40 @@
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
- "@radix-ui/react-popover": "^1.1.6",
28
+ "@radix-ui/react-popover": "^1.1.15",
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",
32
- "@radix-ui/react-tooltip": "^1.1.8",
31
+ "@radix-ui/react-slot": "^1.2.4",
32
+ "@radix-ui/react-tooltip": "^1.2.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",
40
- "lucide-react": "^0.487.0",
39
+ "graphql": "^16.12.0",
40
+ "lucide-react": "^0.562.0",
41
41
  "next-themes": "^0.4.6",
42
- "oauth4webapi": "^3.8.1",
42
+ "oauth4webapi": "^3.8.3",
43
43
  "react": "^19.2.1",
44
44
  "react-dom": "^19.2.1",
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",
53
52
  "@testing-library/react": "^16.3.0",
53
+ "@testing-library/user-event": "^14.6.1",
54
54
  "@types/node": "^22",
55
55
  "@types/react": "^19",
56
56
  "@types/react-dom": "^19",
57
- "happy-dom": "^20.0.11",
58
57
  "@vitejs/plugin-react": "^5.1.1",
59
- "msw": "^2.11.2",
58
+ "happy-dom": "^20.0.11",
60
59
  "postcss": "^8",
61
60
  "prettier": "^3.6.2",
62
61
  "tailwindcss": "^4.1.3",
@@ -66,7 +65,7 @@
66
65
  "vite-plugin-dts": "^4.5.0",
67
66
  "vite-plugin-externalize-deps": "^0.10.0",
68
67
  "vite-tsconfig-paths": "^5.1.4",
69
- "vitest": "^4.0.15"
68
+ "vitest": "^4.0.16"
70
69
  },
71
70
  "scripts": {
72
71
  "dev": "vite build --watch --mode development",