@vaadin/hilla-react-auth 25.0.0-alpha8 → 25.0.0-beta1

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.
@@ -1 +1 @@
1
- {"mappings":"AAAA,SAAS,yBAAoC;AAE7C,SAAgC,UAAoC,iCAAkC;AACtG,SAA2B,iCAAkC;;AAuB7D,SAAS,eAAe,EAAE,cAAc,QAAQ,SAA8B,EAAsB;CAClG,MAAM,EACJ,OAAO,EAAE,cAAc,SAAS,EAChC,WACD,GAAG,WAAW,YAAY;CAE3B,MAAM,WAAW,aAAa;AAE9B,KAAI,gBAAgB,SAAS;AAC3B,SAAO;GAAC;;;CAAU;CACnB;AAED,MAAK,UAAU,OAAO,EAAE;AACtB,SAAO,KAAC;GAAS,IAAI;GAAc,OAAO,EAAE,MAAM,SAAU;GAAE;IAAU;CACzE;AAED,QAAO;AACR;AAED,eAAe,OAAO;AAEtB,UAAU,SAAgCA,QAAiD;AACzF,MAAK,MAAM,SAAS,QAAQ;AAC1B,QAAM;AACN,MAAI,MAAM,UAAU;AAClB,UAAO,SAAS,MAAM,SAAgB;EACvC;CACF;AACF;;;;;;;;;;;;AAaD,OAAO,SAAS,aAAaC,OAA4BC,eAAuB,UAA+B;CAC7G,MAAM,EAAE,QAAQ,GAAG;CACnB,MAAM,eAAe,QAAQ,iBAAiB,QAAQ,iBAAiB,QAAQ,cAAc;AAE7F,KAAI,cAAc;AAChB,QAAM,UACJ,KAAC;GACe;GACd,QAAQ;GACR,SAAS,MAAM;IACf;CAEL;AAED,QAAO;AACR;;;;;;;;;AAUD,OAAO,SAAS,cAAcC,QAA+BD,eAAuB,UAAiC;AACnH,MAAK,MAAM,SAAS,SAAS,OAAO,EAAE;AACpC,eAAa,OAAO,aAAa;CAClC;AAED,QAAO;AACR","names":["routes: T[]","route: RouteObjectWithAuth","redirectPath: string","routes: RouteObjectWithAuth[]"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/react-auth/src/ProtectedRoute.tsx"],"sourcesContent":["import { useContext, type JSX } from 'react';\nimport type { RouteObject } from 'react-router';\nimport { type IndexRouteObject, Navigate, type NonIndexRouteObject, useLocation } from 'react-router';\nimport { type AccessProps, AuthContext } from './useAuth.js';\n\ntype CustomMetadata = Record<string, any>;\n\ntype HandleWithAuth = Readonly<{ handle?: AccessProps & CustomMetadata }>;\n\ntype Override<T, E> = E & Omit<T, keyof E>;\n\ntype IndexRouteObjectWithAuth = Override<IndexRouteObject, HandleWithAuth>;\ntype NonIndexRouteObjectWithAuth = Override<\n Override<NonIndexRouteObject, HandleWithAuth>,\n {\n children?: RouteObjectWithAuth[];\n }\n>;\nexport type RouteObjectWithAuth = IndexRouteObjectWithAuth | NonIndexRouteObjectWithAuth;\n\ninterface ProtectedRouteProps {\n redirectPath: string;\n access: AccessProps;\n element: JSX.Element;\n}\n\nfunction ProtectedRoute({ redirectPath, access, element }: ProtectedRouteProps): JSX.Element | null {\n const {\n state: { initializing, loading },\n hasAccess,\n } = useContext(AuthContext);\n\n const location = useLocation();\n\n if (initializing || loading) {\n return <div></div>;\n }\n\n if (!hasAccess(access)) {\n return <Navigate to={redirectPath} state={{ from: location }} replace />;\n }\n\n return element;\n}\n\nProtectedRoute.type = 'ProtectedRoute'; // This is for copilot to recognize this\n\nfunction* traverse<T extends RouteObject>(routes: T[]): Generator<T, undefined, undefined> {\n for (const route of routes) {\n yield route;\n if (route.children) {\n yield* traverse(route.children as T[]);\n }\n }\n}\n\n/**\n * Adds protection to a single route that requires authentication.\n * These route should contain the {@link AccessProps.loginRequired} and/or\n * {@link AccessProps.rolesAllowed} property to get the protection. Route\n * without that property won't be protected.\n *\n * @param route - the route to protect\n * @param redirectPath - the path to redirect to if the route is protected\n * and the user is not authenticated.\n * @returns the route extended with protection if needed\n */\nexport function protectRoute(route: RouteObjectWithAuth, redirectPath: string = '/login'): RouteObjectWithAuth {\n const { handle } = route;\n const requiresAuth = handle?.loginRequired ?? handle?.requiresLogin ?? handle?.rolesAllowed?.length;\n\n if (requiresAuth) {\n route.element = (\n <ProtectedRoute\n redirectPath={redirectPath}\n access={handle as AccessProps}\n element={route.element as JSX.Element}\n />\n );\n }\n\n return route;\n}\n\n/**\n * Protects a route tree with {@link protectRoute} function.\n *\n * @param routes - the roots of the route tree that requires protection.\n * @param redirectPath - the path to redirect to if the route is\n * protected and the user is not authenticated.\n * @returns the protected route tree\n */\nexport function protectRoutes(routes: RouteObjectWithAuth[], redirectPath: string = '/login'): RouteObjectWithAuth[] {\n for (const route of traverse(routes)) {\n protectRoute(route, redirectPath);\n }\n\n return routes;\n}\n"],"version":3}
1
+ {"mappings":"AAAA,SAAS,yBAAoC;AAE7C,SAAgC,UAAoC,iCAAkC;AACtG,SAA2B,iCAAkC;;AAuB7D,SAAS,eAAe,EAAE,cAAc,QAAQ,SAA8B,EAAsB;CAClG,MAAM,EACJ,OAAO,EAAE,cAAc,SAAS,EAChC,WACD,GAAG,WAAW,YAAY;CAE3B,MAAM,WAAW,aAAa;AAE9B,KAAI,gBAAgB,SAAS;AAC3B,SAAO;GAAC;;;CAAU;CACnB;AAED,MAAK,UAAU,OAAO,EAAE;AACtB,SAAO,KAAC;GAAS,IAAI;GAAc,OAAO,EAAE,MAAM,SAAU;GAAE;IAAU;CACzE;AAED,QAAO;AACR;AAED,eAAe,OAAO;AAEtB,UAAU,SAAgCA,QAAiD;AACzF,MAAK,MAAM,SAAS,QAAQ;AAC1B,QAAM;AACN,MAAI,MAAM,UAAU;AAClB,UAAO,SAAS,MAAM,SAAgB;EACvC;CACF;AACF;;;;;;;;;;;;AAaD,OAAO,SAAS,aAAaC,OAA4BC,eAAuB,UAA+B;CAC7G,MAAM,EAAE,QAAQ,GAAG;CACnB,MAAM,eAAe,QAAQ,iBAAiB,QAAQ,iBAAiB,QAAQ,cAAc;AAE7F,KAAI,cAAc;AAChB,QAAM,UACJ,KAAC;GACe;GACd,QAAQ;GACR,SAAS,MAAM;IACf;CAEL;AAED,QAAO;AACR;;;;;;;;;AAUD,OAAO,SAAS,cAAcC,QAA+BD,eAAuB,UAAiC;AACnH,MAAK,MAAM,SAAS,SAAS,OAAO,EAAE;AACpC,eAAa,OAAO,aAAa;CAClC;AAED,QAAO;AACR","names":["routes: T[]","route: RouteObjectWithAuth","redirectPath: string","routes: RouteObjectWithAuth[]"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/react-auth/src/ProtectedRoute.tsx"],"sourcesContent":["import { useContext, type JSX } from 'react';\nimport type { RouteObject } from 'react-router';\nimport { type IndexRouteObject, Navigate, type NonIndexRouteObject, useLocation } from 'react-router';\nimport { type AccessProps, AuthContext } from './useAuth.js';\n\ntype CustomMetadata = Record<string, any>;\n\ntype HandleWithAuth = Readonly<{ handle?: AccessProps & CustomMetadata }>;\n\ntype Override<T, E> = E & Omit<T, keyof E>;\n\ntype IndexRouteObjectWithAuth = Override<IndexRouteObject, HandleWithAuth>;\ntype NonIndexRouteObjectWithAuth = Override<\n Override<NonIndexRouteObject, HandleWithAuth>,\n {\n children?: RouteObjectWithAuth[];\n }\n>;\nexport type RouteObjectWithAuth = IndexRouteObjectWithAuth | NonIndexRouteObjectWithAuth;\n\ninterface ProtectedRouteProps {\n redirectPath: string;\n access: AccessProps;\n element: JSX.Element;\n}\n\nfunction ProtectedRoute({ redirectPath, access, element }: ProtectedRouteProps): JSX.Element | null {\n const {\n state: { initializing, loading },\n hasAccess,\n } = useContext(AuthContext);\n\n const location = useLocation();\n\n if (initializing || loading) {\n return <div></div>;\n }\n\n if (!hasAccess(access)) {\n return <Navigate to={redirectPath} state={{ from: location }} replace />;\n }\n\n return element;\n}\n\nProtectedRoute.type = 'ProtectedRoute'; // This is for copilot to recognize this\n\nfunction* traverse<T extends RouteObject>(routes: T[]): Generator<T, undefined, undefined> {\n for (const route of routes) {\n yield route;\n if (route.children) {\n yield* traverse(route.children as T[]);\n }\n }\n}\n\n/**\n * Adds protection to a single route that requires authentication.\n * These route should contain the {@link AccessProps.loginRequired} and/or\n * {@link AccessProps.rolesAllowed} property to get the protection. Route\n * without that property won't be protected.\n *\n * @param route - the route to protect\n * @param redirectPath - the path to redirect to if the route is protected\n * and the user is not authenticated.\n * @returns the route extended with protection if needed\n */\nexport function protectRoute(route: RouteObjectWithAuth, redirectPath: string = '/login'): RouteObjectWithAuth {\n const { handle } = route;\n const requiresAuth = handle?.loginRequired ?? handle?.requiresLogin ?? handle?.rolesAllowed?.length;\n\n if (requiresAuth) {\n route.element = (\n <ProtectedRoute\n redirectPath={redirectPath}\n access={handle as AccessProps}\n element={route.element as JSX.Element}\n />\n );\n }\n\n return route;\n}\n\n/**\n * Protects a route tree with {@link protectRoute} function.\n *\n * @param routes - the roots of the route tree that requires protection.\n * @param redirectPath - the path to redirect to if the route is\n * protected and the user is not authenticated.\n * @returns the protected route tree\n */\nexport function protectRoutes(routes: RouteObjectWithAuth[], redirectPath: string = '/login'): RouteObjectWithAuth[] {\n for (const route of traverse(routes)) {\n protectRoute(route, redirectPath);\n }\n\n return routes;\n}\n"],"version":3}
package/index.js CHANGED
@@ -4,7 +4,7 @@ export * from "./useAuth.js";
4
4
  vaadinObj.registrations ??= [];
5
5
  vaadinObj.registrations.push({
6
6
  is: feature ? `@vaadin/hilla-react-auth/${feature}` : "@vaadin/hilla-react-auth",
7
- version: "25.0.0-alpha8"
7
+ version: "25.0.0-beta1"
8
8
  });
9
9
  })();
10
10
  //# sourceMappingURL=./index.js.map
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"mappings":"AAAA;AACA;AAIA,CAAC,CAAC,SAAS,YAAa,WAAW,WAAW,CAAE,MAAM;AACpD,WAAU,kBAAkB,CAAE;AAC9B,WAAU,cAAc,KAAK;EAC3B,IAAI,WAAW,2BAA2B,QAAQ,IAAI;EACtD,SAAS;CACV,EAAC;AACH,IAAG","names":[],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/react-auth/src/index.ts"],"sourcesContent":["export * from './ProtectedRoute.js';\nexport * from './useAuth.js';\n\n// @ts-expect-error: esbuild injection\n// eslint-disable-next-line @typescript-eslint/no-unsafe-call\n((feature, vaadinObj = (globalThis.Vaadin ??= {})) => {\n vaadinObj.registrations ??= [];\n vaadinObj.registrations.push({\n is: feature ? `@vaadin/hilla-react-auth/${feature}` : '@vaadin/hilla-react-auth',\n version: '25.0.0-alpha8',\n });\n})();\n"],"version":3}
1
+ {"mappings":"AAAA;AACA;AAIA,CAAC,CAAC,SAAS,YAAa,WAAW,WAAW,CAAE,MAAM;AACpD,WAAU,kBAAkB,CAAE;AAC9B,WAAU,cAAc,KAAK;EAC3B,IAAI,WAAW,2BAA2B,QAAQ,IAAI;EACtD,SAAS;CACV,EAAC;AACH,IAAG","names":[],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/react-auth/src/index.ts"],"sourcesContent":["export * from './ProtectedRoute.js';\nexport * from './useAuth.js';\n\n// @ts-expect-error: esbuild injection\n// eslint-disable-next-line @typescript-eslint/no-unsafe-call\n((feature, vaadinObj = (globalThis.Vaadin ??= {})) => {\n vaadinObj.registrations ??= [];\n vaadinObj.registrations.push({\n is: feature ? `@vaadin/hilla-react-auth/${feature}` : '@vaadin/hilla-react-auth',\n version: '25.0.0-beta1',\n });\n})();\n"],"version":3}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/hilla-react-auth",
3
- "version": "25.0.0-alpha8",
3
+ "version": "25.0.0-beta1",
4
4
  "description": "Hilla auth utils for React",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
@@ -44,7 +44,7 @@
44
44
  "access": "public"
45
45
  },
46
46
  "dependencies": {
47
- "@vaadin/hilla-frontend": "25.0.0-alpha8"
47
+ "@vaadin/hilla-frontend": "25.0.0-beta1"
48
48
  },
49
49
  "peerDependencies": {
50
50
  "react": "18 || 19",
package/useAuth.js.map CHANGED
@@ -1 +1 @@
1
- {"mappings":"AAAA,SACE,SAAS,QAGT,UAAU,SAEV,yDAC8B;AAChC,SAAuB,eAA8B,YAAY,WAAW,yBAA0B;;AAKtG,MAAM,cAAc;AACpB,MAAM,gBAAgB;AACtB,MAAM,gBAAgB;AACtB,MAAM,SAAS;AAmCf,SAAS,wBAA+BA,UAAkCC,sBAAwC;CAChH,eAAe,eAAe;AAC5B,WAAS,EAAE,MAAM,YAAa,EAAC;EAG/B,MAAM,OAAO,MAAM,sBAAsB,CAAC,MAAM,CAACC,UAAmB;AAClE,OAAI,iBAAiB,2BAA2B;AAE9C,WAAO;GACR;AAED,SAAM;EACP,EAAC;AAEF,MAAI,MAAM;AACR,YAAS;IACP;IACA,MAAM;GACP,EAAC;EACH,OAAM;AACL,YAAS;IACP,OAAO;IACP,MAAM;GACP,EAAC;EACH;CACF;AAED,QAAO;AACR;AAED,SAAS,0BAA0BC,UAAkC;AACnE,QAAO,MAAM;AACX,WAAS,EAAE,MAAM,OAAQ,EAAC;CAC3B;AACF;AAED,MAAMC,eAAmC;CACvC,cAAc;CACd,SAAS;AACV;AAED,SAAS,QAAQC,OAA2BC,QAAqC;AAC/E,SAAQ,OAAO,MAAf;EACE,KAAK,YACH,QAAO;GACL,cAAc;GACd,SAAS;EACV;EACH,KAAK,cACH,QAAO;GACL,cAAc;GACd,SAAS;GACT,MAAM,OAAO;EACd;EACH,KAAK,cACH,QAAO;GACL,cAAc;GACd,SAAS;GACT,OAAO,OAAO;EACf;EACH,KAAK,OACH,QAAO;GAAE,cAAc;GAAO,SAAS;EAAO;EAChD,QACE,QAAO;CACV;AACF;;;;;AAqCD,OAAO,MAAMC,cAAgD,cAAuC;CAClG,OAAO;CACP,QAAQ;AACN,QAAM,IAAI,MAAM;CACjB;CACD,SAAS;AACP,QAAM,IAAI,MAAM;CACjB;CACD,YAAqB;AACnB,QAAM,IAAI,MAAM;CACjB;AACF,EAAC;AAeF,MAAM,kBAAkB,CAACC,SAAkB;CACzC,MAAM,gBAAgB;AACtB,QAAO,MAAM,QAAQ,cAAc,MAAM,GAAG,cAAc,QAAQ,CAAE;AACrE;AAED,SAAS,aAAoB,EAAE,UAAU,sBAAsB,QAAkC,EAAE;CACjG,MAAM,CAAC,OAAO,SAAS,GAAG,WAAW,SAAS,aAAa;CAC3D,MAAM,eAAe,wBAAwB,UAAU,qBAAqB;CAC5E,MAAM,iBAAiB,0BAA0B,SAAS;CAE1D,eAAe,MAAMC,UAAkBC,UAAkBC,SAA8C;EACrG,MAAM,SAAS,MAAM,OAAO,UAAU,UAAU,QAAQ;AAExD,OAAK,OAAO,OAAO;AACjB,SAAM,cAAc;EACrB;AAED,SAAO;CACR;CAED,eAAe,OAAOC,SAAwC;AAC5D,QAAM,QAAQ,QAAQ;AACtB,kBAAgB;CACjB;CAED,SAAS,UAAU,EAAE,eAAe,eAAe,cAA2B,EAAW;EACvF,MAAM,eAAe,iBAAiB,iBAAiB;AACvD,OAAK,cAAc;AACjB,UAAO;EACR;AAED,OAAK,MAAM,MAAM;AACf,UAAO;EACR;AAED,MAAI,cAAc;GAChB,MAAM,YAAY,QAAQ,WAAW,OAAO,SAAS,MAAM,KAAc,GAAG,gBAAgB,MAAM,KAAK;AACvG,UAAO,aAAa,KAAK,CAAC,gBAAgB,UAAU,SAAS,YAAY,CAAC;EAC3E;AAED,SAAO;CACR;AAED,WAAU,MAAM;AACd,gBAAc,CAAC,MAAM,MAAM,CAE1B,EAAC;CACH,GAAE,CAAE,EAAC;CAEN,MAAM,OAAO;EACX;EACA;EACA;EACA;CACD;AAED,QAAO,KAAC,YAAY;EAAS,OAAO;EAAO;GAAgC;AAC5E;;;;;;AASD,SAAS,UAAwC;AAC/C,QAAO,WAAW,YAAY;AAC/B;AAOD,OAAO,SAAS,cACdX,sBACAY,QACmB;CACnB,SAAS,0BAA0B,EAAE,UAAmC,EAAE;AACxE,SACE,KAAC;GAA0C;GAA8B;GACtE;IACY;CAElB;AAED,QAAO;EACL,cAAc;EACL;CACV;AACF","names":["dispatch: Dispatch<LoginActions>","getAuthenticatedUser: GetUserFn<TUser>","error: unknown","dispatch: Dispatch<LogoutAction>","initialState: AuthState<unknown>","state: AuthState<unknown>","action: LoginActions | LogoutAction","AuthContext: Context<Authentication<unknown>>","user: unknown","username: string","password: string","options?: LoginOptions","options?: LogoutOptions","config?: AuthConfig<TUser>"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/react-auth/src/useAuth.tsx"],"sourcesContent":["import {\n login as _login,\n type LoginOptions,\n type LoginResult,\n logout as _logout,\n type LogoutOptions,\n UnauthorizedResponseError,\n} from '@vaadin/hilla-frontend';\nimport { type Context, createContext, type Dispatch, useContext, useEffect, useReducer } from 'react';\n\ntype LoginFunction = (username: string, password: string, options?: LoginOptions) => Promise<LoginResult>;\ntype LogoutFunction = () => Promise<void>;\n\nconst LOGIN_FETCH = 'LOGIN_FETCH';\nconst LOGIN_SUCCESS = 'LOGIN_SUCCESS';\nconst LOGIN_FAILURE = 'LOGIN_FAILURE';\nconst LOGOUT = 'LOGOUT';\n\n/**\n * The type of the function that is used to get the authenticated user.\n */\nexport type GetUserFn<TUser> = () => Promise<TUser | undefined>;\n\ntype AuthState<TUser> = Readonly<{\n initializing: boolean;\n loading: boolean;\n user?: TUser;\n error?: string;\n getAuthenticatedUser?: GetUserFn<TUser>;\n}>;\n\ntype LoginFetchAction = Readonly<{\n type: typeof LOGIN_FETCH;\n}>;\n\ntype LoginSuccessAction = Readonly<{\n user: unknown;\n type: typeof LOGIN_SUCCESS;\n}>;\n\ntype LoginFailureAction = Readonly<{\n error: string;\n type: typeof LOGIN_FAILURE;\n}>;\n\ntype LoginActions = LoginFailureAction | LoginFetchAction | LoginSuccessAction;\n\ntype LogoutAction = Readonly<{\n type: typeof LOGOUT;\n}>;\n\nfunction createAuthenticateThunk<TUser>(dispatch: Dispatch<LoginActions>, getAuthenticatedUser: GetUserFn<TUser>) {\n async function authenticate() {\n dispatch({ type: LOGIN_FETCH });\n\n // Get user info from endpoint\n const user = await getAuthenticatedUser().catch((error: unknown) => {\n if (error instanceof UnauthorizedResponseError) {\n // 401 response: the user is not authenticated\n return undefined;\n }\n\n throw error;\n });\n\n if (user) {\n dispatch({\n user,\n type: LOGIN_SUCCESS,\n });\n } else {\n dispatch({\n error: 'Not authenticated',\n type: LOGIN_FAILURE,\n });\n }\n }\n\n return authenticate;\n}\n\nfunction createUnauthenticateThunk(dispatch: Dispatch<LogoutAction>) {\n return () => {\n dispatch({ type: LOGOUT });\n };\n}\n\nconst initialState: AuthState<unknown> = {\n initializing: true,\n loading: false,\n};\n\nfunction reducer(state: AuthState<unknown>, action: LoginActions | LogoutAction) {\n switch (action.type) {\n case LOGIN_FETCH:\n return {\n initializing: false,\n loading: true,\n };\n case LOGIN_SUCCESS:\n return {\n initializing: false,\n loading: false,\n user: action.user,\n };\n case LOGIN_FAILURE:\n return {\n initializing: false,\n loading: false,\n error: action.error,\n };\n case LOGOUT:\n return { initializing: false, loading: false };\n default:\n return state;\n }\n}\n\n/**\n * The properties that can be used to control access to a route.\n * They can be added to the route type handler as properties.\n */\nexport type AccessProps = Readonly<{\n /**\n * If true, the user must be logged in to access the route.\n */\n loginRequired?: boolean;\n /**\n * If true, the user must be logged in to access the route.\n *\n * @deprecated Use `loginRequired` instead.\n */\n requiresLogin?: boolean;\n /**\n * The list of roles that are allowed to access the route.\n */\n rolesAllowed?: readonly [string, ...string[]];\n}>;\n\n/**\n * The type of the authentication hook.\n */\nexport type Authentication<TUser> = Readonly<{\n state: AuthState<TUser>;\n login: LoginFunction;\n logout: LogoutFunction;\n hasAccess(accessProps: AccessProps): boolean;\n}>;\n\n/**\n * The hook that can be used to get the authentication state.\n * It returns the state of the authentication.\n */\nexport const AuthContext: Context<Authentication<unknown>> = createContext<Authentication<unknown>>({\n state: initialState,\n login() {\n throw new Error('AuthContext not initialized');\n },\n logout() {\n throw new Error('AuthContext not initialized');\n },\n hasAccess(): boolean {\n throw new Error('AuthContext not initialized');\n },\n});\n\ninterface AuthConfig<TUser> {\n getRoles?(user: TUser): readonly string[];\n}\n\ninterface AuthProviderProps<TUser> extends React.PropsWithChildren {\n getAuthenticatedUser: GetUserFn<TUser>;\n config?: AuthConfig<TUser>;\n}\n\ninterface UserWithRoles {\n roles?: any;\n}\n\nconst getDefaultRoles = (user: unknown) => {\n const userWithRoles = user as UserWithRoles;\n return Array.isArray(userWithRoles.roles) ? userWithRoles.roles : [];\n};\n\nfunction AuthProvider<TUser>({ children, getAuthenticatedUser, config }: AuthProviderProps<TUser>) {\n const [state, dispatch] = useReducer(reducer, initialState);\n const authenticate = createAuthenticateThunk(dispatch, getAuthenticatedUser);\n const unauthenticate = createUnauthenticateThunk(dispatch);\n\n async function login(username: string, password: string, options?: LoginOptions): Promise<LoginResult> {\n const result = await _login(username, password, options);\n\n if (!result.error) {\n await authenticate();\n }\n\n return result;\n }\n\n async function logout(options?: LogoutOptions): Promise<void> {\n await _logout(options);\n unauthenticate();\n }\n\n function hasAccess({ loginRequired, requiresLogin, rolesAllowed }: AccessProps): boolean {\n const requiresAuth = loginRequired ?? requiresLogin ?? rolesAllowed;\n if (!requiresAuth) {\n return true;\n }\n\n if (!state.user) {\n return false;\n }\n\n if (rolesAllowed) {\n const userRoles = config?.getRoles ? config.getRoles(state.user as TUser) : getDefaultRoles(state.user);\n return rolesAllowed.some((allowedRole) => userRoles.includes(allowedRole));\n }\n\n return true;\n }\n\n useEffect(() => {\n authenticate().catch(() => {\n // Do nothing\n });\n }, []);\n\n const auth = {\n state,\n login,\n logout,\n hasAccess,\n };\n\n return <AuthContext.Provider value={auth}>{children}</AuthContext.Provider>;\n}\n\nexport type AuthHook<TUser> = () => Authentication<TUser>;\n\n/**\n * The hook that can be used to authenticate the user.\n * It returns the state of the authentication and the functions\n * to authenticate and unauthenticate the user.\n */\nfunction useAuth<TUser>(): Authentication<TUser> {\n return useContext(AuthContext) as Authentication<TUser>;\n}\n\ninterface AuthModule<TUser> {\n AuthProvider: React.FC<React.PropsWithChildren>;\n useAuth: AuthHook<TUser>;\n}\n\nexport function configureAuth<TUser>(\n getAuthenticatedUser: GetUserFn<TUser>,\n config?: AuthConfig<TUser>,\n): AuthModule<TUser> {\n function PreconfiguredAuthProvider({ children }: React.PropsWithChildren) {\n return (\n <AuthProvider<TUser> getAuthenticatedUser={getAuthenticatedUser} config={config}>\n {children}\n </AuthProvider>\n );\n }\n\n return {\n AuthProvider: PreconfiguredAuthProvider,\n useAuth: useAuth as AuthHook<TUser>,\n };\n}\n"],"version":3}
1
+ {"mappings":"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","names":["dispatch: Dispatch<LoginActions>","getAuthenticatedUser: GetUserFn<TUser>","error: unknown","dispatch: Dispatch<LogoutAction>","initialState: AuthState<unknown>","state: AuthState<unknown>","action: LoginActions | LogoutAction","AuthContext: Context<Authentication<unknown>>","user: unknown","username: string","password: string","options?: LoginOptions","options?: LogoutOptions","config?: AuthConfig<TUser>"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/react-auth/src/useAuth.tsx"],"sourcesContent":["import {\n login as _login,\n type LoginOptions,\n type LoginResult,\n logout as _logout,\n type LogoutOptions,\n UnauthorizedResponseError,\n} from '@vaadin/hilla-frontend';\nimport { type Context, createContext, type Dispatch, useContext, useEffect, useReducer } from 'react';\n\ntype LoginFunction = (username: string, password: string, options?: LoginOptions) => Promise<LoginResult>;\ntype LogoutFunction = () => Promise<void>;\n\nconst LOGIN_FETCH = 'LOGIN_FETCH';\nconst LOGIN_SUCCESS = 'LOGIN_SUCCESS';\nconst LOGIN_FAILURE = 'LOGIN_FAILURE';\nconst LOGOUT = 'LOGOUT';\n\n/**\n * The type of the function that is used to get the authenticated user.\n */\nexport type GetUserFn<TUser> = () => Promise<TUser | undefined>;\n\ntype AuthState<TUser> = Readonly<{\n initializing: boolean;\n loading: boolean;\n user?: TUser;\n error?: string;\n getAuthenticatedUser?: GetUserFn<TUser>;\n}>;\n\ntype LoginFetchAction = Readonly<{\n type: typeof LOGIN_FETCH;\n}>;\n\ntype LoginSuccessAction = Readonly<{\n user: unknown;\n type: typeof LOGIN_SUCCESS;\n}>;\n\ntype LoginFailureAction = Readonly<{\n error: string;\n type: typeof LOGIN_FAILURE;\n}>;\n\ntype LoginActions = LoginFailureAction | LoginFetchAction | LoginSuccessAction;\n\ntype LogoutAction = Readonly<{\n type: typeof LOGOUT;\n}>;\n\nfunction createAuthenticateThunk<TUser>(dispatch: Dispatch<LoginActions>, getAuthenticatedUser: GetUserFn<TUser>) {\n async function authenticate() {\n dispatch({ type: LOGIN_FETCH });\n\n // Get user info from endpoint\n const user = await getAuthenticatedUser().catch((error: unknown) => {\n if (error instanceof UnauthorizedResponseError) {\n // 401 response: the user is not authenticated\n return undefined;\n }\n\n throw error;\n });\n\n if (user) {\n dispatch({\n user,\n type: LOGIN_SUCCESS,\n });\n } else {\n dispatch({\n error: 'Not authenticated',\n type: LOGIN_FAILURE,\n });\n }\n }\n\n return authenticate;\n}\n\nfunction createUnauthenticateThunk(dispatch: Dispatch<LogoutAction>) {\n return () => {\n dispatch({ type: LOGOUT });\n };\n}\n\nconst initialState: AuthState<unknown> = {\n initializing: true,\n loading: false,\n};\n\nfunction reducer(state: AuthState<unknown>, action: LoginActions | LogoutAction) {\n switch (action.type) {\n case LOGIN_FETCH:\n return {\n initializing: false,\n loading: true,\n };\n case LOGIN_SUCCESS:\n return {\n initializing: false,\n loading: false,\n user: action.user,\n };\n case LOGIN_FAILURE:\n return {\n initializing: false,\n loading: false,\n error: action.error,\n };\n case LOGOUT:\n return { initializing: false, loading: false };\n default:\n return state;\n }\n}\n\n/**\n * The properties that can be used to control access to a route.\n * They can be added to the route type handler as properties.\n */\nexport type AccessProps = Readonly<{\n /**\n * If true, the user must be logged in to access the route.\n */\n loginRequired?: boolean;\n /**\n * If true, the user must be logged in to access the route.\n *\n * @deprecated Use `loginRequired` instead.\n */\n requiresLogin?: boolean;\n /**\n * The list of roles that are allowed to access the route.\n */\n rolesAllowed?: readonly [string, ...string[]];\n}>;\n\n/**\n * The type of the authentication hook.\n */\nexport type Authentication<TUser> = Readonly<{\n state: AuthState<TUser>;\n login: LoginFunction;\n logout: LogoutFunction;\n hasAccess(accessProps: AccessProps): boolean;\n}>;\n\n/**\n * The hook that can be used to get the authentication state.\n * It returns the state of the authentication.\n */\nexport const AuthContext: Context<Authentication<unknown>> = createContext<Authentication<unknown>>({\n state: initialState,\n login() {\n throw new Error('AuthContext not initialized');\n },\n logout() {\n throw new Error('AuthContext not initialized');\n },\n hasAccess(): boolean {\n throw new Error('AuthContext not initialized');\n },\n});\n\ninterface AuthConfig<TUser> {\n getRoles?(user: TUser): readonly string[];\n}\n\ninterface AuthProviderProps<TUser> extends React.PropsWithChildren {\n getAuthenticatedUser: GetUserFn<TUser>;\n config?: AuthConfig<TUser>;\n}\n\ninterface UserWithRoles {\n roles?: any;\n}\n\nconst getDefaultRoles = (user: unknown) => {\n const userWithRoles = user as UserWithRoles;\n return Array.isArray(userWithRoles.roles) ? userWithRoles.roles : [];\n};\n\nfunction AuthProvider<TUser>({ children, getAuthenticatedUser, config }: AuthProviderProps<TUser>) {\n const [state, dispatch] = useReducer(reducer, initialState);\n const authenticate = createAuthenticateThunk(dispatch, getAuthenticatedUser);\n const unauthenticate = createUnauthenticateThunk(dispatch);\n\n async function login(username: string, password: string, options?: LoginOptions): Promise<LoginResult> {\n const result = await _login(username, password, options);\n\n if (!result.error) {\n await authenticate();\n }\n\n return result;\n }\n\n async function logout(options?: LogoutOptions): Promise<void> {\n await _logout(options);\n unauthenticate();\n }\n\n function hasAccess({ loginRequired, requiresLogin, rolesAllowed }: AccessProps): boolean {\n const requiresAuth = loginRequired ?? requiresLogin ?? rolesAllowed;\n if (!requiresAuth) {\n return true;\n }\n\n if (!state.user) {\n return false;\n }\n\n if (rolesAllowed) {\n const userRoles = config?.getRoles ? config.getRoles(state.user as TUser) : getDefaultRoles(state.user);\n return rolesAllowed.some((allowedRole) => userRoles.includes(allowedRole));\n }\n\n return true;\n }\n\n useEffect(() => {\n authenticate().catch(() => {\n // Do nothing\n });\n }, []);\n\n const auth = {\n state,\n login,\n logout,\n hasAccess,\n };\n\n return <AuthContext.Provider value={auth}>{children}</AuthContext.Provider>;\n}\n\nexport type AuthHook<TUser> = () => Authentication<TUser>;\n\n/**\n * The hook that can be used to authenticate the user.\n * It returns the state of the authentication and the functions\n * to authenticate and unauthenticate the user.\n */\nfunction useAuth<TUser>(): Authentication<TUser> {\n return useContext(AuthContext) as Authentication<TUser>;\n}\n\ninterface AuthModule<TUser> {\n AuthProvider: React.FC<React.PropsWithChildren>;\n useAuth: AuthHook<TUser>;\n}\n\nexport function configureAuth<TUser>(\n getAuthenticatedUser: GetUserFn<TUser>,\n config?: AuthConfig<TUser>,\n): AuthModule<TUser> {\n function PreconfiguredAuthProvider({ children }: React.PropsWithChildren) {\n return (\n <AuthProvider<TUser> getAuthenticatedUser={getAuthenticatedUser} config={config}>\n {children}\n </AuthProvider>\n );\n }\n\n return {\n AuthProvider: PreconfiguredAuthProvider,\n useAuth: useAuth as AuthHook<TUser>,\n };\n}\n"],"version":3}