@dudousxd/adonis-authkit-react 0.1.2 → 0.3.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.
Files changed (54) hide show
  1. package/README.md +26 -0
  2. package/build/index.d.ts +47 -0
  3. package/build/index.js +24 -0
  4. package/build/src/authkit_provider.d.ts +13 -0
  5. package/build/src/authkit_provider.js +11 -0
  6. package/build/src/components/authorized_apps.d.ts +8 -0
  7. package/build/src/components/authorized_apps.js +26 -0
  8. package/build/src/components/avatar.d.ts +22 -0
  9. package/build/src/components/avatar.js +15 -0
  10. package/build/src/components/organization_profile.d.ts +8 -0
  11. package/build/src/components/organization_profile.js +87 -0
  12. package/build/src/components/organization_switcher.d.ts +7 -0
  13. package/build/src/components/organization_switcher.js +57 -0
  14. package/build/src/components/password_strength_meter.d.ts +11 -0
  15. package/build/src/components/password_strength_meter.js +39 -0
  16. package/build/src/components/sign_in_button.d.ts +297 -0
  17. package/build/src/components/sign_in_button.js +16 -0
  18. package/build/src/components/sign_out_button.d.ts +296 -0
  19. package/build/src/components/sign_out_button.js +16 -0
  20. package/build/src/components/user_button.d.ts +8 -0
  21. package/build/src/components/user_button.js +31 -0
  22. package/build/src/components/user_profile.d.ts +6 -0
  23. package/build/src/components/user_profile.js +27 -0
  24. package/build/src/config.d.ts +27 -0
  25. package/build/src/config.js +40 -0
  26. package/build/src/hooks/use_authorized_apps.d.ts +16 -0
  27. package/build/src/hooks/use_authorized_apps.js +15 -0
  28. package/build/src/hooks/use_org_invitations.d.ts +19 -0
  29. package/build/src/hooks/use_org_invitations.js +20 -0
  30. package/build/src/hooks/use_organization.d.ts +23 -0
  31. package/build/src/hooks/use_organization.js +8 -0
  32. package/build/src/hooks/use_organizations.d.ts +18 -0
  33. package/build/src/hooks/use_organizations.js +14 -0
  34. package/build/src/hooks/use_password_strength.d.ts +11 -0
  35. package/build/src/hooks/use_password_strength.js +34 -0
  36. package/build/src/hooks/use_profile.d.ts +13 -0
  37. package/build/src/hooks/use_profile.js +28 -0
  38. package/build/src/hooks/use_resource.d.ts +11 -0
  39. package/build/src/hooks/use_resource.js +48 -0
  40. package/build/src/hooks/use_sessions.d.ts +16 -0
  41. package/build/src/hooks/use_sessions.js +15 -0
  42. package/build/src/hooks/use_sign_in.d.ts +6 -0
  43. package/build/src/hooks/use_sign_in.js +13 -0
  44. package/build/src/hooks/use_sign_out.d.ts +6 -0
  45. package/build/src/hooks/use_sign_out.js +11 -0
  46. package/build/src/hooks/use_switch_organization.d.ts +7 -0
  47. package/build/src/hooks/use_switch_organization.js +42 -0
  48. package/build/src/hooks/use_user.d.ts +6 -0
  49. package/build/src/hooks/use_user.js +5 -0
  50. package/build/src/use_auth.js +1 -1
  51. package/build/src/utils.d.ts +2 -0
  52. package/build/src/utils.js +18 -0
  53. package/package.json +9 -7
  54. package/styles.css +294 -0
@@ -0,0 +1,16 @@
1
+ import { createElement } from 'react';
2
+ import { useSignOut } from '../hooks/use_sign_out.js';
3
+ import { useAuth } from '../use_auth.js';
4
+ export function SignOutButton({ children = 'Sair', returnTo, className, ...rest }) {
5
+ const { signOut } = useSignOut();
6
+ const { isAuthenticated } = useAuth();
7
+ if (!isAuthenticated)
8
+ return null;
9
+ const opts = returnTo ? { returnTo } : undefined;
10
+ return createElement('button', {
11
+ type: 'button',
12
+ className: ['authkit-button', 'authkit-button--ghost', className].filter(Boolean).join(' '),
13
+ onClick: () => signOut(opts),
14
+ ...rest,
15
+ }, children);
16
+ }
@@ -0,0 +1,8 @@
1
+ export interface UserButtonProps {
2
+ profileLabel?: string;
3
+ signOutLabel?: string;
4
+ className?: string;
5
+ }
6
+ export declare function UserButton({ profileLabel, signOutLabel, className, }: UserButtonProps): import("react").DetailedReactHTMLElement<{
7
+ className: string;
8
+ }, HTMLElement> | null;
@@ -0,0 +1,31 @@
1
+ import { createElement, useState } from 'react';
2
+ import { useAuth } from '../use_auth.js';
3
+ import { useAuthkitConfig } from '../config.js';
4
+ import { useSignOut } from '../hooks/use_sign_out.js';
5
+ import { Avatar } from './avatar.js';
6
+ export function UserButton({ profileLabel = 'Perfil', signOutLabel = 'Sair', className, }) {
7
+ const { user, isAuthenticated } = useAuth();
8
+ const config = useAuthkitConfig();
9
+ const { signOut } = useSignOut();
10
+ const [open, setOpen] = useState(false);
11
+ if (!isAuthenticated || !user)
12
+ return null;
13
+ const trigger = createElement('button', {
14
+ type: 'button',
15
+ className: 'authkit-userbutton__trigger',
16
+ 'aria-haspopup': 'menu',
17
+ 'aria-expanded': open,
18
+ onClick: () => setOpen((v) => !v),
19
+ }, createElement(Avatar, { user }));
20
+ const menu = open
21
+ ? createElement('div', { className: 'authkit-userbutton__menu', role: 'menu' }, createElement('div', { className: 'authkit-userbutton__header' }, createElement('div', { className: 'authkit-userbutton__name' }, user.name ?? user.email), user.name
22
+ ? createElement('div', { className: 'authkit-userbutton__email' }, user.email)
23
+ : null), createElement('a', { className: 'authkit-userbutton__item', role: 'menuitem', href: config.profileUrl }, profileLabel), createElement('button', {
24
+ type: 'button',
25
+ className: 'authkit-userbutton__item',
26
+ role: 'menuitem',
27
+ onClick: () => signOut(),
28
+ }, signOutLabel))
29
+ : null;
30
+ return createElement('div', { className: ['authkit-userbutton', className].filter(Boolean).join(' ') }, trigger, menu);
31
+ }
@@ -0,0 +1,6 @@
1
+ export interface UserProfileProps {
2
+ className?: string;
3
+ }
4
+ export declare function UserProfile({ className }: UserProfileProps): import("react").DetailedReactHTMLElement<{
5
+ className: string;
6
+ }, HTMLElement> | null;
@@ -0,0 +1,27 @@
1
+ import { createElement, useState } from 'react';
2
+ import { useAuth } from '../use_auth.js';
3
+ import { useProfile } from '../hooks/use_profile.js';
4
+ import { Avatar } from './avatar.js';
5
+ export function UserProfile({ className }) {
6
+ const { user, isAuthenticated } = useAuth();
7
+ const { actions, loading, error } = useProfile();
8
+ const [name, setName] = useState(user?.name ?? '');
9
+ if (!isAuthenticated || !user)
10
+ return null;
11
+ const onSubmit = (e) => {
12
+ e.preventDefault();
13
+ void actions.update({ name });
14
+ };
15
+ return createElement('div', { className: ['authkit-card', 'authkit-profile', className].filter(Boolean).join(' ') }, createElement('div', { className: 'authkit-profile__header' }, createElement(Avatar, { user, size: 56 }), createElement('div', null, createElement('div', { className: 'authkit-profile__name' }, user.name ?? user.email), createElement('div', { className: 'authkit-profile__email' }, user.email))), createElement('form', { className: 'authkit-profile__form', onSubmit }, createElement('label', { className: 'authkit-label', htmlFor: 'authkit-profile-name' }, 'Nome'), createElement('input', {
16
+ id: 'authkit-profile-name',
17
+ className: 'authkit-input',
18
+ value: name,
19
+ onChange: (e) => setName(e.target.value),
20
+ }), error
21
+ ? createElement('p', { className: 'authkit-error', role: 'alert' }, error.message)
22
+ : null, createElement('button', {
23
+ type: 'submit',
24
+ className: 'authkit-button authkit-button--primary',
25
+ disabled: loading,
26
+ }, loading ? 'Salvando…' : 'Salvar')));
27
+ }
@@ -0,0 +1,27 @@
1
+ export interface AuthkitEndpoints {
2
+ profile: string;
3
+ sessions: string;
4
+ apps: string;
5
+ passkeys: string;
6
+ orgs: string;
7
+ orgInvitations: string;
8
+ }
9
+ export interface AuthkitConfig {
10
+ loginUrl?: string;
11
+ logoutUrl?: string;
12
+ profileUrl?: string;
13
+ endpoints?: Partial<AuthkitEndpoints>;
14
+ csrfToken?: string;
15
+ }
16
+ export interface ResolvedAuthkitConfig {
17
+ loginUrl: string;
18
+ logoutUrl: string;
19
+ profileUrl: string;
20
+ endpoints: AuthkitEndpoints;
21
+ csrfToken?: string;
22
+ }
23
+ export declare const DEFAULT_CONFIG: ResolvedAuthkitConfig;
24
+ export declare function resolveConfig(config?: AuthkitConfig): ResolvedAuthkitConfig;
25
+ export declare function buildAuthUrl(base: string, returnTo?: string): string;
26
+ export declare const AuthkitConfigContext: import("react").Context<ResolvedAuthkitConfig>;
27
+ export declare function useAuthkitConfig(): ResolvedAuthkitConfig;
@@ -0,0 +1,40 @@
1
+ import { createContext, useContext } from 'react';
2
+ export const DEFAULT_CONFIG = {
3
+ loginUrl: '/auth/login',
4
+ logoutUrl: '/account/logout',
5
+ profileUrl: '/account/security',
6
+ endpoints: {
7
+ profile: '/account/security/profile',
8
+ sessions: '/account/security',
9
+ apps: '/account/apps',
10
+ passkeys: '/account/mfa/passkeys',
11
+ orgs: '/account/orgs/json',
12
+ orgInvitations: '/account/orgs/invitations/json',
13
+ },
14
+ };
15
+ export function resolveConfig(config) {
16
+ return {
17
+ loginUrl: config?.loginUrl ?? DEFAULT_CONFIG.loginUrl,
18
+ logoutUrl: config?.logoutUrl ?? DEFAULT_CONFIG.logoutUrl,
19
+ profileUrl: config?.profileUrl ?? DEFAULT_CONFIG.profileUrl,
20
+ endpoints: {
21
+ profile: config?.endpoints?.profile ?? DEFAULT_CONFIG.endpoints.profile,
22
+ sessions: config?.endpoints?.sessions ?? DEFAULT_CONFIG.endpoints.sessions,
23
+ apps: config?.endpoints?.apps ?? DEFAULT_CONFIG.endpoints.apps,
24
+ passkeys: config?.endpoints?.passkeys ?? DEFAULT_CONFIG.endpoints.passkeys,
25
+ orgs: config?.endpoints?.orgs ?? DEFAULT_CONFIG.endpoints.orgs,
26
+ orgInvitations: config?.endpoints?.orgInvitations ?? DEFAULT_CONFIG.endpoints.orgInvitations,
27
+ },
28
+ csrfToken: config?.csrfToken,
29
+ };
30
+ }
31
+ export function buildAuthUrl(base, returnTo) {
32
+ if (!returnTo)
33
+ return base;
34
+ const sep = base.includes('?') ? '&' : '?';
35
+ return `${base}${sep}returnTo=${encodeURIComponent(returnTo)}`;
36
+ }
37
+ export const AuthkitConfigContext = createContext(DEFAULT_CONFIG);
38
+ export function useAuthkitConfig() {
39
+ return useContext(AuthkitConfigContext);
40
+ }
@@ -0,0 +1,16 @@
1
+ import { type ResourceState } from './use_resource.js';
2
+ export interface AuthorizedApp {
3
+ clientId: string;
4
+ name?: string;
5
+ logoUrl?: string;
6
+ scopes?: string[];
7
+ authorizedAt?: string;
8
+ [key: string]: unknown;
9
+ }
10
+ export interface UseAuthorizedAppsResult extends ResourceState<AuthorizedApp[]> {
11
+ actions: {
12
+ refetch(): Promise<void>;
13
+ revoke(clientId: string): Promise<void>;
14
+ };
15
+ }
16
+ export declare function useAuthorizedApps(): UseAuthorizedAppsResult;
@@ -0,0 +1,15 @@
1
+ import { useCallback } from 'react';
2
+ import { useAuthkitConfig } from '../config.js';
3
+ import { jsonRequest, useResource } from './use_resource.js';
4
+ export function useAuthorizedApps() {
5
+ const config = useAuthkitConfig();
6
+ const { data, loading, error, refetch } = useResource(config.endpoints.apps, config.csrfToken);
7
+ const revoke = useCallback(async (clientId) => {
8
+ await jsonRequest(`${config.endpoints.apps}/${encodeURIComponent(clientId)}/revoke`, {
9
+ method: 'POST',
10
+ csrfToken: config.csrfToken,
11
+ });
12
+ await refetch();
13
+ }, [config.endpoints.apps, config.csrfToken, refetch]);
14
+ return { data, loading, error, actions: { refetch, revoke } };
15
+ }
@@ -0,0 +1,19 @@
1
+ import { type ResourceState } from './use_resource.js';
2
+ export interface OrgInvitationEntry {
3
+ id: string;
4
+ organizationId: string;
5
+ orgName: string;
6
+ orgSlug: string;
7
+ email: string;
8
+ role: string;
9
+ expiresAt: string;
10
+ createdAt: string;
11
+ [key: string]: unknown;
12
+ }
13
+ export interface UseOrgInvitationsResult extends ResourceState<OrgInvitationEntry[]> {
14
+ actions: {
15
+ refetch(): Promise<void>;
16
+ accept(token: string): Promise<void>;
17
+ };
18
+ }
19
+ export declare function useOrgInvitations(): UseOrgInvitationsResult;
@@ -0,0 +1,20 @@
1
+ import { useCallback } from 'react';
2
+ import { useAuthkitConfig } from '../config.js';
3
+ import { jsonRequest, useResource } from './use_resource.js';
4
+ export function useOrgInvitations() {
5
+ const config = useAuthkitConfig();
6
+ const { data, loading, error, refetch } = useResource(config.endpoints.orgInvitations, config.csrfToken);
7
+ const accept = useCallback(async (token) => {
8
+ await jsonRequest(`/account/orgs/invitations/${encodeURIComponent(token)}/accept`, {
9
+ method: 'POST',
10
+ csrfToken: config.csrfToken,
11
+ });
12
+ await refetch();
13
+ }, [config.csrfToken, refetch]);
14
+ return {
15
+ data: data?.invitations ?? null,
16
+ loading,
17
+ error,
18
+ actions: { refetch, accept },
19
+ };
20
+ }
@@ -0,0 +1,23 @@
1
+ import { type ResourceState } from './use_resource.js';
2
+ export interface OrgMemberEntry {
3
+ accountId: string;
4
+ email: string | null;
5
+ role: string;
6
+ joinedAt: string;
7
+ }
8
+ export interface ActiveOrgDetail {
9
+ id: string;
10
+ name: string;
11
+ slug: string;
12
+ logoUrl: string | null;
13
+ role: string;
14
+ canManage: boolean;
15
+ members: OrgMemberEntry[];
16
+ [key: string]: unknown;
17
+ }
18
+ export interface UseOrganizationResult extends ResourceState<ActiveOrgDetail> {
19
+ actions: {
20
+ refetch(): Promise<void>;
21
+ };
22
+ }
23
+ export declare function useOrganization(orgId: string | null): UseOrganizationResult;
@@ -0,0 +1,8 @@
1
+ import { useAuthkitConfig } from '../config.js';
2
+ import { useResource } from './use_resource.js';
3
+ export function useOrganization(orgId) {
4
+ const config = useAuthkitConfig();
5
+ const url = orgId ? `${config.endpoints.orgs.replace('/json', '')}/${encodeURIComponent(orgId)}/json` : '';
6
+ const { data, loading, error, refetch } = useResource(url, config.csrfToken);
7
+ return { data, loading: url ? loading : false, error, actions: { refetch } };
8
+ }
@@ -0,0 +1,18 @@
1
+ import { type ResourceState } from './use_resource.js';
2
+ export interface OrgEntry {
3
+ id: string;
4
+ name: string;
5
+ slug: string;
6
+ logoUrl: string | null;
7
+ role: string;
8
+ isActive: boolean;
9
+ [key: string]: unknown;
10
+ }
11
+ export interface UseOrganizationsResult extends ResourceState<OrgEntry[]> {
12
+ activeOrgId: string | null;
13
+ supported: boolean;
14
+ actions: {
15
+ refetch(): Promise<void>;
16
+ };
17
+ }
18
+ export declare function useOrganizations(): UseOrganizationsResult;
@@ -0,0 +1,14 @@
1
+ import { useAuthkitConfig } from '../config.js';
2
+ import { useResource } from './use_resource.js';
3
+ export function useOrganizations() {
4
+ const config = useAuthkitConfig();
5
+ const { data, loading, error, refetch } = useResource(config.endpoints.orgs, config.csrfToken);
6
+ return {
7
+ data: data?.orgs ?? null,
8
+ loading,
9
+ error,
10
+ activeOrgId: data?.activeOrgId ?? null,
11
+ supported: data?.supported ?? true,
12
+ actions: { refetch },
13
+ };
14
+ }
@@ -0,0 +1,11 @@
1
+ export type PasswordStrengthScore = 0 | 1 | 2 | 3 | 4;
2
+ export interface PasswordStrengthResult {
3
+ score: PasswordStrengthScore;
4
+ feedback?: string[];
5
+ }
6
+ export type PasswordScorer = (password: string) => PasswordStrengthResult;
7
+ export interface UsePasswordStrengthOptions {
8
+ scorer?: PasswordScorer;
9
+ }
10
+ export declare function heuristicScorer(password: string): PasswordStrengthResult;
11
+ export declare function usePasswordStrength(password: string, options?: UsePasswordStrengthOptions): PasswordStrengthResult;
@@ -0,0 +1,34 @@
1
+ import { useMemo } from 'react';
2
+ export function heuristicScorer(password) {
3
+ if (!password)
4
+ return { score: 0, feedback: ['Enter a password.'] };
5
+ const feedback = [];
6
+ const classes = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^A-Za-z0-9]/];
7
+ const variety = classes.filter((re) => re.test(password)).length;
8
+ const length = password.length;
9
+ let points = 0;
10
+ if (length >= 8)
11
+ points += 1;
12
+ if (length >= 12)
13
+ points += 1;
14
+ if (length >= 16)
15
+ points += 1;
16
+ if (variety >= 2)
17
+ points += 1;
18
+ if (variety >= 3)
19
+ points += 1;
20
+ if (length < 12)
21
+ feedback.push('Use at least 12 characters.');
22
+ if (!/[A-Z]/.test(password))
23
+ feedback.push('Add an uppercase letter.');
24
+ if (!/[0-9]/.test(password))
25
+ feedback.push('Add a number.');
26
+ if (!/[^A-Za-z0-9]/.test(password))
27
+ feedback.push('Add a symbol.');
28
+ const score = Math.max(0, Math.min(4, points));
29
+ return { score, feedback: feedback.length ? feedback : undefined };
30
+ }
31
+ export function usePasswordStrength(password, options = {}) {
32
+ const scorer = options.scorer ?? heuristicScorer;
33
+ return useMemo(() => scorer(password), [password, scorer]);
34
+ }
@@ -0,0 +1,13 @@
1
+ import { type ResourceState } from './use_resource.js';
2
+ import type { AuthUser } from '../types.js';
3
+ export interface ProfileUpdate {
4
+ name?: string;
5
+ avatarUrl?: string;
6
+ [key: string]: unknown;
7
+ }
8
+ export interface UseProfileResult extends ResourceState<AuthUser> {
9
+ actions: {
10
+ update(data: ProfileUpdate): Promise<void>;
11
+ };
12
+ }
13
+ export declare function useProfile(): UseProfileResult;
@@ -0,0 +1,28 @@
1
+ import { useCallback, useState } from 'react';
2
+ import { useAuthkitConfig } from '../config.js';
3
+ import { useAuth } from '../use_auth.js';
4
+ import { jsonRequest } from './use_resource.js';
5
+ export function useProfile() {
6
+ const config = useAuthkitConfig();
7
+ const { user } = useAuth();
8
+ const [state, setState] = useState({
9
+ data: user,
10
+ loading: false,
11
+ error: null,
12
+ });
13
+ const update = useCallback(async (data) => {
14
+ setState((s) => ({ ...s, loading: true, error: null }));
15
+ try {
16
+ const updated = await jsonRequest(config.endpoints.profile, {
17
+ method: 'POST',
18
+ body: JSON.stringify(data),
19
+ csrfToken: config.csrfToken,
20
+ });
21
+ setState({ data: updated ?? { ...user, ...data }, loading: false, error: null });
22
+ }
23
+ catch (err) {
24
+ setState((s) => ({ ...s, loading: false, error: err }));
25
+ }
26
+ }, [config.endpoints.profile, config.csrfToken, user]);
27
+ return { ...state, actions: { update } };
28
+ }
@@ -0,0 +1,11 @@
1
+ export interface ResourceState<T> {
2
+ data: T | null;
3
+ loading: boolean;
4
+ error: Error | null;
5
+ }
6
+ export declare function jsonRequest<T>(url: string, init?: RequestInit & {
7
+ csrfToken?: string;
8
+ }): Promise<T>;
9
+ export declare function useResource<T>(url: string, csrfToken?: string): ResourceState<T> & {
10
+ refetch: () => Promise<void>;
11
+ };
@@ -0,0 +1,48 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ export async function jsonRequest(url, init = {}) {
3
+ const { csrfToken, headers, ...rest } = init;
4
+ const res = await fetch(url, {
5
+ credentials: 'same-origin',
6
+ headers: {
7
+ 'Accept': 'application/json',
8
+ ...(rest.body ? { 'Content-Type': 'application/json' } : {}),
9
+ ...(csrfToken ? { 'X-CSRF-TOKEN': csrfToken } : {}),
10
+ ...headers,
11
+ },
12
+ ...rest,
13
+ });
14
+ if (!res.ok) {
15
+ let message = `Request failed (${res.status})`;
16
+ try {
17
+ const body = await res.json();
18
+ if (body && typeof body.message === 'string')
19
+ message = body.message;
20
+ }
21
+ catch {
22
+ }
23
+ throw new Error(message);
24
+ }
25
+ const text = await res.text();
26
+ return (text ? JSON.parse(text) : null);
27
+ }
28
+ export function useResource(url, csrfToken) {
29
+ const [state, setState] = useState({
30
+ data: null,
31
+ loading: true,
32
+ error: null,
33
+ });
34
+ const refetch = useCallback(async () => {
35
+ setState((s) => ({ ...s, loading: true, error: null }));
36
+ try {
37
+ const data = await jsonRequest(url, { csrfToken });
38
+ setState({ data, loading: false, error: null });
39
+ }
40
+ catch (err) {
41
+ setState({ data: null, loading: false, error: err });
42
+ }
43
+ }, [url, csrfToken]);
44
+ useEffect(() => {
45
+ void refetch();
46
+ }, [refetch]);
47
+ return { ...state, refetch };
48
+ }
@@ -0,0 +1,16 @@
1
+ import { type ResourceState } from './use_resource.js';
2
+ export interface AuthSession {
3
+ id: string;
4
+ device?: string;
5
+ ip?: string;
6
+ lastSeenAt?: string;
7
+ current?: boolean;
8
+ [key: string]: unknown;
9
+ }
10
+ export interface UseSessionsResult extends ResourceState<AuthSession[]> {
11
+ actions: {
12
+ refetch(): Promise<void>;
13
+ revoke(id: string): Promise<void>;
14
+ };
15
+ }
16
+ export declare function useSessions(): UseSessionsResult;
@@ -0,0 +1,15 @@
1
+ import { useCallback } from 'react';
2
+ import { useAuthkitConfig } from '../config.js';
3
+ import { jsonRequest, useResource } from './use_resource.js';
4
+ export function useSessions() {
5
+ const config = useAuthkitConfig();
6
+ const { data, loading, error, refetch } = useResource(config.endpoints.sessions, config.csrfToken);
7
+ const revoke = useCallback(async (id) => {
8
+ await jsonRequest(`${config.endpoints.sessions}/${encodeURIComponent(id)}/revoke`, {
9
+ method: 'POST',
10
+ csrfToken: config.csrfToken,
11
+ });
12
+ await refetch();
13
+ }, [config.endpoints.sessions, config.csrfToken, refetch]);
14
+ return { data, loading, error, actions: { refetch, revoke } };
15
+ }
@@ -0,0 +1,6 @@
1
+ export interface SignInOptions {
2
+ returnTo?: string;
3
+ }
4
+ export declare function useSignIn(): {
5
+ signIn: (opts?: SignInOptions) => void;
6
+ };
@@ -0,0 +1,13 @@
1
+ import { useCallback } from 'react';
2
+ import { useAuthkitConfig, buildAuthUrl } from '../config.js';
3
+ import { currentUrl } from '../utils.js';
4
+ export function useSignIn() {
5
+ const config = useAuthkitConfig();
6
+ const signIn = useCallback((opts) => {
7
+ const returnTo = opts?.returnTo ?? currentUrl();
8
+ const url = buildAuthUrl(config.loginUrl, returnTo);
9
+ if (typeof window !== 'undefined')
10
+ window.location.assign(url);
11
+ }, [config.loginUrl]);
12
+ return { signIn };
13
+ }
@@ -0,0 +1,6 @@
1
+ export interface SignOutOptions {
2
+ returnTo?: string;
3
+ }
4
+ export declare function useSignOut(): {
5
+ signOut: (opts?: SignOutOptions) => void;
6
+ };
@@ -0,0 +1,11 @@
1
+ import { useCallback } from 'react';
2
+ import { useAuthkitConfig, buildAuthUrl } from '../config.js';
3
+ export function useSignOut() {
4
+ const config = useAuthkitConfig();
5
+ const signOut = useCallback((opts) => {
6
+ const url = buildAuthUrl(config.logoutUrl, opts?.returnTo);
7
+ if (typeof window !== 'undefined')
8
+ window.location.assign(url);
9
+ }, [config.logoutUrl]);
10
+ return { signOut };
11
+ }
@@ -0,0 +1,7 @@
1
+ export interface UseSwitchOrganizationResult {
2
+ loading: boolean;
3
+ error: Error | null;
4
+ activate(orgId: string): Promise<void>;
5
+ deactivate(): Promise<void>;
6
+ }
7
+ export declare function useSwitchOrganization(): UseSwitchOrganizationResult;
@@ -0,0 +1,42 @@
1
+ import { useCallback, useState } from 'react';
2
+ import { useAuthkitConfig } from '../config.js';
3
+ import { jsonRequest } from './use_resource.js';
4
+ export function useSwitchOrganization() {
5
+ const config = useAuthkitConfig();
6
+ const base = config.endpoints.orgs.replace('/json', '');
7
+ const [loading, setLoading] = useState(false);
8
+ const [error, setError] = useState(null);
9
+ const activate = useCallback(async (orgId) => {
10
+ setLoading(true);
11
+ setError(null);
12
+ try {
13
+ await jsonRequest(`${base}/${encodeURIComponent(orgId)}/activate`, {
14
+ method: 'POST',
15
+ csrfToken: config.csrfToken,
16
+ });
17
+ }
18
+ catch (err) {
19
+ setError(err);
20
+ }
21
+ finally {
22
+ setLoading(false);
23
+ }
24
+ }, [base, config.csrfToken]);
25
+ const deactivate = useCallback(async () => {
26
+ setLoading(true);
27
+ setError(null);
28
+ try {
29
+ await jsonRequest(`${base}/deactivate`, {
30
+ method: 'POST',
31
+ csrfToken: config.csrfToken,
32
+ });
33
+ }
34
+ catch (err) {
35
+ setError(err);
36
+ }
37
+ finally {
38
+ setLoading(false);
39
+ }
40
+ }, [base, config.csrfToken]);
41
+ return { loading, error, activate, deactivate };
42
+ }
@@ -0,0 +1,6 @@
1
+ import type { AuthUser } from '../types.js';
2
+ export interface UseUserResult {
3
+ user: AuthUser | null;
4
+ isAuthenticated: boolean;
5
+ }
6
+ export declare function useUser(): UseUserResult;
@@ -0,0 +1,5 @@
1
+ import { useAuth } from '../use_auth.js';
2
+ export function useUser() {
3
+ const { user, isAuthenticated } = useAuth();
4
+ return { user, isAuthenticated };
5
+ }
@@ -12,7 +12,7 @@ export function useAuth() {
12
12
  const pageProps = usePage().props;
13
13
  const resolved = contextValue ?? pageProps?.authkit;
14
14
  if (!resolved && typeof process !== 'undefined' && process.env.NODE_ENV !== 'production') {
15
- console.warn('[authkit] useAuth(): nenhum <AuthProvider> nem shared-prop `authkit` encontradoretornando estado não-autenticado.');
15
+ console.warn('[authkit] useAuth(): no <AuthProvider> nor shared-prop `authkit` foundreturning unauthenticated state.');
16
16
  }
17
17
  const authkit = resolved ?? UNAUTHENTICATED;
18
18
  return useMemo(() => {
@@ -0,0 +1,2 @@
1
+ export declare function deriveInitials(name?: string | null, email?: string | null): string;
2
+ export declare function currentUrl(): string;
@@ -0,0 +1,18 @@
1
+ export function deriveInitials(name, email) {
2
+ const source = (name ?? '').trim();
3
+ if (source) {
4
+ const parts = source.split(/\s+/).filter(Boolean);
5
+ if (parts.length === 1)
6
+ return parts[0].slice(0, 2).toUpperCase();
7
+ return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
8
+ }
9
+ const e = (email ?? '').trim();
10
+ if (e)
11
+ return e[0].toUpperCase();
12
+ return '?';
13
+ }
14
+ export function currentUrl() {
15
+ if (typeof window === 'undefined')
16
+ return '';
17
+ return window.location.pathname + window.location.search;
18
+ }