@k3-universe/react-kit 0.0.29 → 0.0.30
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 +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1013 -21
- package/dist/kit/builder/auth/components/Can.d.ts +13 -0
- package/dist/kit/builder/auth/components/Can.d.ts.map +1 -0
- package/dist/kit/builder/auth/components/RequireAuth.d.ts +45 -0
- package/dist/kit/builder/auth/components/RequireAuth.d.ts.map +1 -0
- package/dist/kit/builder/auth/components/ShowWhenAuthenticated.d.ts +8 -0
- package/dist/kit/builder/auth/components/ShowWhenAuthenticated.d.ts.map +1 -0
- package/dist/kit/builder/auth/components/ShowWhenError.d.ts +8 -0
- package/dist/kit/builder/auth/components/ShowWhenError.d.ts.map +1 -0
- package/dist/kit/builder/auth/components/ShowWhenLoading.d.ts +8 -0
- package/dist/kit/builder/auth/components/ShowWhenLoading.d.ts.map +1 -0
- package/dist/kit/builder/auth/components/ShowWhenUnauthenticated.d.ts +8 -0
- package/dist/kit/builder/auth/components/ShowWhenUnauthenticated.d.ts.map +1 -0
- package/dist/kit/builder/auth/components/withPermission.d.ts +7 -0
- package/dist/kit/builder/auth/components/withPermission.d.ts.map +1 -0
- package/dist/kit/builder/auth/hooks/action-hooks.d.ts +18 -0
- package/dist/kit/builder/auth/hooks/action-hooks.d.ts.map +1 -0
- package/dist/kit/builder/auth/hooks/core-hooks.d.ts +56 -0
- package/dist/kit/builder/auth/hooks/core-hooks.d.ts.map +1 -0
- package/dist/kit/builder/auth/hooks/index.d.ts +5 -0
- package/dist/kit/builder/auth/hooks/index.d.ts.map +1 -0
- package/dist/kit/builder/auth/hooks/permission-hooks.d.ts +18 -0
- package/dist/kit/builder/auth/hooks/permission-hooks.d.ts.map +1 -0
- package/dist/kit/builder/auth/hooks/token-hooks.d.ts +13 -0
- package/dist/kit/builder/auth/hooks/token-hooks.d.ts.map +1 -0
- package/dist/kit/builder/auth/index.d.ts +14 -8
- package/dist/kit/builder/auth/index.d.ts.map +1 -1
- package/dist/kit/builder/auth/{AuthProvider.d.ts → providers/AuthProvider.d.ts} +1 -1
- package/dist/kit/builder/auth/providers/AuthProvider.d.ts.map +1 -0
- package/dist/kit/builder/auth/types/adapter-config.d.ts +31 -0
- package/dist/kit/builder/auth/types/adapter-config.d.ts.map +1 -0
- package/dist/kit/builder/auth/types/adapter.d.ts +80 -0
- package/dist/kit/builder/auth/types/adapter.d.ts.map +1 -0
- package/dist/kit/builder/auth/types/core.d.ts +16 -0
- package/dist/kit/builder/auth/types/core.d.ts.map +1 -0
- package/dist/kit/builder/auth/types/index.d.ts +10 -0
- package/dist/kit/builder/auth/types/index.d.ts.map +1 -0
- package/dist/kit/builder/auth/types/middleware.d.ts +11 -0
- package/dist/kit/builder/auth/types/middleware.d.ts.map +1 -0
- package/dist/kit/builder/auth/types/permissions.d.ts +17 -0
- package/dist/kit/builder/auth/types/permissions.d.ts.map +1 -0
- package/dist/kit/builder/auth/types/state.d.ts +13 -0
- package/dist/kit/builder/auth/types/state.d.ts.map +1 -0
- package/dist/kit/builder/auth/types/storage.d.ts +20 -0
- package/dist/kit/builder/auth/types/storage.d.ts.map +1 -0
- package/dist/kit/builder/auth/types/token-manager.d.ts +7 -0
- package/dist/kit/builder/auth/types/token-manager.d.ts.map +1 -0
- package/dist/kit/builder/auth/types/utils.d.ts +7 -0
- package/dist/kit/builder/auth/types/utils.d.ts.map +1 -0
- package/dist/kit/builder/auth/{adapter.d.ts → utils/auth-adapter.d.ts} +2 -2
- package/dist/kit/builder/auth/utils/auth-adapter.d.ts.map +1 -0
- package/dist/kit/builder/auth/utils/client-adapters/apollo-link.d.ts +4 -0
- package/dist/kit/builder/auth/utils/client-adapters/apollo-link.d.ts.map +1 -0
- package/dist/kit/builder/auth/utils/client-adapters/axios.d.ts +6 -0
- package/dist/kit/builder/auth/utils/client-adapters/axios.d.ts.map +1 -0
- package/dist/kit/builder/auth/utils/client-adapters/fetch.d.ts +6 -0
- package/dist/kit/builder/auth/utils/client-adapters/fetch.d.ts.map +1 -0
- package/dist/kit/builder/auth/utils/client-adapters/graphql.d.ts +9 -0
- package/dist/kit/builder/auth/utils/client-adapters/graphql.d.ts.map +1 -0
- package/dist/kit/builder/auth/utils/client-adapters/index.d.ts +7 -0
- package/dist/kit/builder/auth/utils/client-adapters/index.d.ts.map +1 -0
- package/dist/kit/builder/auth/utils/client-adapters/rest.d.ts +9 -0
- package/dist/kit/builder/auth/utils/client-adapters/rest.d.ts.map +1 -0
- package/dist/kit/builder/auth/utils/client-adapters/urql-exchange.d.ts +14 -0
- package/dist/kit/builder/auth/utils/client-adapters/urql-exchange.d.ts.map +1 -0
- package/dist/kit/builder/auth/{permission-checker.d.ts → utils/permission-checker.d.ts} +1 -1
- package/dist/kit/builder/auth/utils/permission-checker.d.ts.map +1 -0
- package/dist/kit/builder/auth/utils/storage/browser.d.ts +11 -0
- package/dist/kit/builder/auth/utils/storage/browser.d.ts.map +1 -0
- package/dist/kit/builder/auth/utils/storage/cookie.d.ts +3 -0
- package/dist/kit/builder/auth/utils/storage/cookie.d.ts.map +1 -0
- package/dist/kit/builder/auth/utils/storage/encryption.d.ts +7 -0
- package/dist/kit/builder/auth/utils/storage/encryption.d.ts.map +1 -0
- package/dist/kit/builder/auth/utils/storage/env.d.ts +2 -0
- package/dist/kit/builder/auth/utils/storage/env.d.ts.map +1 -0
- package/dist/kit/builder/auth/utils/storage/factory.d.ts +6 -0
- package/dist/kit/builder/auth/utils/storage/factory.d.ts.map +1 -0
- package/dist/kit/builder/auth/utils/storage/index.d.ts +7 -0
- package/dist/kit/builder/auth/utils/storage/index.d.ts.map +1 -0
- package/dist/kit/builder/auth/utils/storage/memory.d.ts +3 -0
- package/dist/kit/builder/auth/utils/storage/memory.d.ts.map +1 -0
- package/dist/kit/builder/auth/{token-manager.d.ts → utils/token-manager.d.ts} +1 -1
- package/dist/kit/builder/auth/utils/token-manager.d.ts.map +1 -0
- package/dist/kit/components/login/Login.d.ts.map +1 -1
- package/dist/kit/layouts/admin/components/AdminLayout.d.ts +2 -1
- package/dist/kit/layouts/admin/components/AdminLayout.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/kit/builder/auth/components/Can.tsx +27 -0
- package/src/kit/builder/auth/components/RequireAuth.tsx +78 -0
- package/src/kit/builder/auth/components/ShowWhenAuthenticated.tsx +10 -0
- package/src/kit/builder/auth/components/ShowWhenError.tsx +10 -0
- package/src/kit/builder/auth/components/ShowWhenLoading.tsx +10 -0
- package/src/kit/builder/auth/components/ShowWhenUnauthenticated.tsx +10 -0
- package/src/kit/builder/auth/components/withPermission.tsx +23 -0
- package/src/kit/builder/auth/hooks/action-hooks.ts +34 -0
- package/src/kit/builder/auth/hooks/core-hooks.ts +65 -0
- package/src/kit/builder/auth/hooks/index.ts +4 -0
- package/src/kit/builder/auth/hooks/permission-hooks.ts +43 -0
- package/src/kit/builder/auth/hooks/token-hooks.ts +25 -0
- package/src/kit/builder/auth/index.ts +16 -18
- package/src/kit/builder/auth/{AuthProvider.tsx → providers/AuthProvider.tsx} +1 -1
- package/src/kit/builder/auth/types/adapter-config.ts +44 -0
- package/src/kit/builder/auth/types/adapter.ts +132 -0
- package/src/kit/builder/auth/types/core.ts +27 -0
- package/src/kit/builder/auth/types/index.ts +9 -0
- package/src/kit/builder/auth/types/middleware.ts +20 -0
- package/src/kit/builder/auth/types/permissions.ts +23 -0
- package/src/kit/builder/auth/types/state.ts +16 -0
- package/src/kit/builder/auth/types/storage.ts +21 -0
- package/src/kit/builder/auth/types/token-manager.ts +9 -0
- package/src/kit/builder/auth/types/utils.ts +55 -0
- package/src/kit/builder/auth/{adapter.ts → utils/auth-adapter.ts} +3 -2
- package/src/kit/builder/auth/utils/client-adapters/apollo-link.ts +30 -0
- package/src/kit/builder/auth/utils/client-adapters/axios.ts +61 -0
- package/src/kit/builder/auth/utils/client-adapters/fetch.ts +48 -0
- package/src/kit/builder/auth/utils/client-adapters/graphql.ts +60 -0
- package/src/kit/builder/auth/utils/client-adapters/index.ts +6 -0
- package/src/kit/builder/auth/utils/client-adapters/rest.ts +60 -0
- package/src/kit/builder/auth/utils/client-adapters/urql-exchange.ts +76 -0
- package/src/kit/builder/auth/{permission-checker.ts → utils/permission-checker.ts} +1 -1
- package/src/kit/builder/auth/utils/storage/browser.ts +99 -0
- package/src/kit/builder/auth/utils/storage/cookie.ts +116 -0
- package/src/kit/builder/auth/utils/storage/encryption.ts +80 -0
- package/src/kit/builder/auth/utils/storage/env.ts +2 -0
- package/src/kit/builder/auth/utils/storage/factory.ts +37 -0
- package/src/kit/builder/auth/utils/storage/index.ts +6 -0
- package/src/kit/builder/auth/utils/storage/memory.ts +15 -0
- package/src/kit/builder/auth/{token-manager.ts → utils/token-manager.ts} +1 -1
- package/src/kit/components/login/Login.tsx +9 -7
- package/src/kit/layouts/admin/components/AdminLayout.tsx +24 -17
- package/dist/kit/builder/auth/AuthProvider.d.ts.map +0 -1
- package/dist/kit/builder/auth/adapter.d.ts.map +0 -1
- package/dist/kit/builder/auth/client-adapters.d.ts +0 -149
- package/dist/kit/builder/auth/client-adapters.d.ts.map +0 -1
- package/dist/kit/builder/auth/components.d.ts +0 -119
- package/dist/kit/builder/auth/components.d.ts.map +0 -1
- package/dist/kit/builder/auth/hooks.d.ts +0 -158
- package/dist/kit/builder/auth/hooks.d.ts.map +0 -1
- package/dist/kit/builder/auth/permission-checker.d.ts.map +0 -1
- package/dist/kit/builder/auth/storage.d.ts +0 -17
- package/dist/kit/builder/auth/storage.d.ts.map +0 -1
- package/dist/kit/builder/auth/token-manager.d.ts.map +0 -1
- package/dist/kit/builder/auth/types.d.ts +0 -183
- package/dist/kit/builder/auth/types.d.ts.map +0 -1
- package/src/kit/builder/auth/client-adapters.ts +0 -398
- package/src/kit/builder/auth/components.tsx +0 -221
- package/src/kit/builder/auth/hooks.ts +0 -237
- package/src/kit/builder/auth/storage.ts +0 -366
- package/src/kit/builder/auth/types.ts +0 -393
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// Core
|
|
3
3
|
// ============================================================================
|
|
4
4
|
|
|
5
|
-
export { createAuthAdapter } from
|
|
6
|
-
export { AuthProvider, useAuthContext } from
|
|
5
|
+
export { createAuthAdapter } from "./utils/auth-adapter";
|
|
6
|
+
export { AuthProvider, useAuthContext } from "./providers/AuthProvider";
|
|
7
7
|
|
|
8
8
|
// ============================================================================
|
|
9
9
|
// Storage
|
|
@@ -14,20 +14,20 @@ export {
|
|
|
14
14
|
createMemoryStorage,
|
|
15
15
|
createBrowserStorage,
|
|
16
16
|
createCookieStorage,
|
|
17
|
-
} from
|
|
17
|
+
} from "./utils/storage";
|
|
18
18
|
|
|
19
19
|
// ============================================================================
|
|
20
20
|
// Utilities
|
|
21
21
|
// ============================================================================
|
|
22
22
|
|
|
23
|
-
export { createTokenManager } from
|
|
23
|
+
export { createTokenManager } from "./utils/token-manager";
|
|
24
24
|
export {
|
|
25
25
|
expandPermissions,
|
|
26
26
|
expandRoles,
|
|
27
27
|
checkPermissions,
|
|
28
28
|
checkRoles,
|
|
29
29
|
evaluatePermissionRule,
|
|
30
|
-
} from
|
|
30
|
+
} from "./utils/permission-checker";
|
|
31
31
|
|
|
32
32
|
// ============================================================================
|
|
33
33
|
// Client Adapters
|
|
@@ -39,12 +39,12 @@ export {
|
|
|
39
39
|
createAxiosAuthInterceptor,
|
|
40
40
|
createAuthFetch,
|
|
41
41
|
createApolloAuthLink,
|
|
42
|
-
} from
|
|
42
|
+
} from "./utils/client-adapters";
|
|
43
43
|
|
|
44
44
|
export type {
|
|
45
45
|
GraphQLClientAdapterOptions,
|
|
46
46
|
RESTClientAdapterOptions,
|
|
47
|
-
} from
|
|
47
|
+
} from "./utils/client-adapters";
|
|
48
48
|
|
|
49
49
|
// ============================================================================
|
|
50
50
|
// Hooks
|
|
@@ -69,21 +69,19 @@ export {
|
|
|
69
69
|
useLogout,
|
|
70
70
|
useRefresh,
|
|
71
71
|
useSetSession,
|
|
72
|
-
} from
|
|
72
|
+
} from "./hooks";
|
|
73
73
|
|
|
74
74
|
// ============================================================================
|
|
75
75
|
// Components
|
|
76
76
|
// ============================================================================
|
|
77
77
|
|
|
78
|
-
export {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
ShowWhenError,
|
|
86
|
-
} from './components';
|
|
78
|
+
export { RequireAuth } from "./components/RequireAuth";
|
|
79
|
+
export { Can } from "./components/Can";
|
|
80
|
+
export { withPermission } from "./components/withPermission";
|
|
81
|
+
export { ShowWhenAuthenticated } from "./components/ShowWhenAuthenticated";
|
|
82
|
+
export { ShowWhenUnauthenticated } from "./components/ShowWhenUnauthenticated";
|
|
83
|
+
export { ShowWhenLoading } from "./components/ShowWhenLoading";
|
|
84
|
+
export { ShowWhenError } from "./components/ShowWhenError";
|
|
87
85
|
|
|
88
86
|
// ============================================================================
|
|
89
87
|
// Types
|
|
@@ -131,4 +129,4 @@ export type {
|
|
|
131
129
|
InferRole,
|
|
132
130
|
InferPermission,
|
|
133
131
|
InferCredentials,
|
|
134
|
-
} from
|
|
132
|
+
} from "./types";
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
useSyncExternalStore,
|
|
7
7
|
} from 'react';
|
|
8
8
|
import type { ReactNode } from 'react';
|
|
9
|
-
import type { AuthAdapter, AuthContextValue, AuthSession } from '
|
|
9
|
+
import type { AuthAdapter, AuthContextValue, AuthSession } from '../types';
|
|
10
10
|
|
|
11
11
|
type AnyAuthContextValue = AuthContextValue<
|
|
12
12
|
unknown,
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { AuthSession, RefreshStrategy } from './core';
|
|
2
|
+
import type { PermissionHierarchy, RoleHierarchy } from './permissions';
|
|
3
|
+
import type { AuthAdapterState } from './state';
|
|
4
|
+
import type { AuthMiddleware } from './middleware';
|
|
5
|
+
import type { TokenManager } from './token-manager';
|
|
6
|
+
import type { AuthStorage } from './storage';
|
|
7
|
+
|
|
8
|
+
export type AuthAdapterConfig<
|
|
9
|
+
TUser = unknown,
|
|
10
|
+
TRole extends string = string,
|
|
11
|
+
TPermission extends string = string,
|
|
12
|
+
TSession extends AuthSession<TUser, TRole, TPermission> = AuthSession<
|
|
13
|
+
TUser,
|
|
14
|
+
TRole,
|
|
15
|
+
TPermission
|
|
16
|
+
>,
|
|
17
|
+
TCredentials = unknown,
|
|
18
|
+
> = {
|
|
19
|
+
storage?: AuthStorage<TSession>;
|
|
20
|
+
loadSession?: () => Promise<TSession | null>;
|
|
21
|
+
login?: (credentials: TCredentials) => Promise<TSession>;
|
|
22
|
+
logout?: (session: TSession | null) => Promise<void> | void;
|
|
23
|
+
refresh?: (session: TSession) => Promise<TSession>;
|
|
24
|
+
resolveUser?: (session: TSession | null) => TUser | null;
|
|
25
|
+
resolveRoles?: (session: TSession | null) => TRole[];
|
|
26
|
+
resolvePermissions?: (session: TSession | null) => TPermission[];
|
|
27
|
+
shouldRefresh?: (session: TSession) => boolean;
|
|
28
|
+
onStateChange?: (
|
|
29
|
+
state: AuthAdapterState<TSession, TUser, TRole, TPermission>,
|
|
30
|
+
) => void;
|
|
31
|
+
|
|
32
|
+
refreshStrategy?: RefreshStrategy;
|
|
33
|
+
refreshThreshold?: number;
|
|
34
|
+
autoRefresh?: boolean;
|
|
35
|
+
permissionHierarchy?: PermissionHierarchy<TPermission>;
|
|
36
|
+
roleHierarchy?: RoleHierarchy<TRole>;
|
|
37
|
+
middleware?: AuthMiddleware<TSession, TUser, TRole, TPermission>[];
|
|
38
|
+
tokenManager?: TokenManager;
|
|
39
|
+
retryConfig?: {
|
|
40
|
+
maxRetries?: number;
|
|
41
|
+
retryDelay?: number;
|
|
42
|
+
retryOn?: (error: unknown) => boolean;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import type { AuthSession } from './core';
|
|
2
|
+
import type { PermissionPolicy, PermissionRule } from './permissions';
|
|
3
|
+
import type { AuthAdapterState, AuthAdapterSubscriber } from './state';
|
|
4
|
+
|
|
5
|
+
export type AuthAdapter<
|
|
6
|
+
TUser = unknown,
|
|
7
|
+
TRole extends string = string,
|
|
8
|
+
TPermission extends string = string,
|
|
9
|
+
TSession extends AuthSession<TUser, TRole, TPermission> = AuthSession<
|
|
10
|
+
TUser,
|
|
11
|
+
TRole,
|
|
12
|
+
TPermission
|
|
13
|
+
>,
|
|
14
|
+
TCredentials = unknown,
|
|
15
|
+
> = {
|
|
16
|
+
getState: () => AuthAdapterState<TSession, TUser, TRole, TPermission>;
|
|
17
|
+
subscribe: (
|
|
18
|
+
listener: AuthAdapterSubscriber<TSession, TUser, TRole, TPermission>,
|
|
19
|
+
) => () => void;
|
|
20
|
+
sync: () => Promise<AuthAdapterState<TSession, TUser, TRole, TPermission>>;
|
|
21
|
+
login?: (
|
|
22
|
+
credentials: TCredentials,
|
|
23
|
+
) => Promise<AuthAdapterState<TSession, TUser, TRole, TPermission>>;
|
|
24
|
+
logout: () => Promise<void>;
|
|
25
|
+
refresh: () => Promise<AuthAdapterState<TSession, TUser, TRole, TPermission>>;
|
|
26
|
+
setSession: (
|
|
27
|
+
session: TSession | null,
|
|
28
|
+
) => Promise<AuthAdapterState<TSession, TUser, TRole, TPermission>>;
|
|
29
|
+
hasRole: (
|
|
30
|
+
target: TRole | TRole[],
|
|
31
|
+
options?: { requireAll?: boolean },
|
|
32
|
+
) => boolean;
|
|
33
|
+
hasPermission: (
|
|
34
|
+
target: TPermission | TPermission[] | PermissionPolicy<TPermission>,
|
|
35
|
+
options?: { requireAll?: boolean },
|
|
36
|
+
) => boolean;
|
|
37
|
+
can: (rule: PermissionRule<TRole, TPermission>) => boolean;
|
|
38
|
+
getToken: () => string | null;
|
|
39
|
+
isTokenExpired: () => boolean;
|
|
40
|
+
getTimeUntilExpiry: () => number;
|
|
41
|
+
scheduleAutoRefresh?: () => () => void;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export type AuthContextValue<
|
|
45
|
+
TUser = unknown,
|
|
46
|
+
TRole extends string = string,
|
|
47
|
+
TPermission extends string = string,
|
|
48
|
+
TSession extends AuthSession<TUser, TRole, TPermission> = AuthSession<
|
|
49
|
+
TUser,
|
|
50
|
+
TRole,
|
|
51
|
+
TPermission
|
|
52
|
+
>,
|
|
53
|
+
TCredentials = unknown,
|
|
54
|
+
> = {
|
|
55
|
+
state: AuthAdapterState<TSession, TUser, TRole, TPermission>;
|
|
56
|
+
status: AuthAdapterState<TSession, TUser, TRole, TPermission>['status'];
|
|
57
|
+
session: TSession | null;
|
|
58
|
+
user: TUser | null;
|
|
59
|
+
roles: TRole[];
|
|
60
|
+
permissions: TPermission[];
|
|
61
|
+
error?: unknown;
|
|
62
|
+
login?: (
|
|
63
|
+
credentials: TCredentials,
|
|
64
|
+
) => Promise<AuthAdapterState<TSession, TUser, TRole, TPermission>>;
|
|
65
|
+
logout: () => Promise<void>;
|
|
66
|
+
refresh: () => Promise<AuthAdapterState<TSession, TUser, TRole, TPermission>>;
|
|
67
|
+
setSession: (
|
|
68
|
+
session: TSession | null,
|
|
69
|
+
) => Promise<AuthAdapterState<TSession, TUser, TRole, TPermission>>;
|
|
70
|
+
hasRole: (
|
|
71
|
+
target: TRole | TRole[],
|
|
72
|
+
options?: { requireAll?: boolean },
|
|
73
|
+
) => boolean;
|
|
74
|
+
hasPermission: (
|
|
75
|
+
target: TPermission | TPermission[] | PermissionPolicy<TPermission>,
|
|
76
|
+
options?: { requireAll?: boolean },
|
|
77
|
+
) => boolean;
|
|
78
|
+
can: (rule: PermissionRule<TRole, TPermission>) => boolean;
|
|
79
|
+
getToken: () => string | null;
|
|
80
|
+
isTokenExpired: () => boolean;
|
|
81
|
+
getTimeUntilExpiry: () => number;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export type RequireAuthProps<
|
|
85
|
+
TRole extends string = string,
|
|
86
|
+
TPermission extends string = string,
|
|
87
|
+
> = {
|
|
88
|
+
children: React.ReactNode;
|
|
89
|
+
fallback?: React.ReactNode;
|
|
90
|
+
loadingFallback?: React.ReactNode;
|
|
91
|
+
roles?: TRole | TRole[];
|
|
92
|
+
permissions?: TPermission | TPermission[] | PermissionPolicy<TPermission>;
|
|
93
|
+
requireAll?: boolean;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export type CanProps<
|
|
97
|
+
TRole extends string = string,
|
|
98
|
+
TPermission extends string = string,
|
|
99
|
+
> = {
|
|
100
|
+
children: React.ReactNode;
|
|
101
|
+
fallback?: React.ReactNode;
|
|
102
|
+
roles?: TRole | TRole[];
|
|
103
|
+
permissions?: TPermission | TPermission[] | PermissionPolicy<TPermission>;
|
|
104
|
+
requireAll?: boolean;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export type WithPermissionOptions<
|
|
108
|
+
TRole extends string = string,
|
|
109
|
+
TPermission extends string = string,
|
|
110
|
+
> = {
|
|
111
|
+
roles?: TRole | TRole[];
|
|
112
|
+
permissions?: TPermission | TPermission[] | PermissionPolicy<TPermission>;
|
|
113
|
+
requireAll?: boolean;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export type GraphQLAuthClient<TSession = unknown, TCredentials = unknown> = {
|
|
117
|
+
login: (credentials: TCredentials) => Promise<TSession>;
|
|
118
|
+
logout?: () => Promise<void>;
|
|
119
|
+
refresh?: (refreshToken: string) => Promise<TSession>;
|
|
120
|
+
getCurrentUser?: () => Promise<TSession>;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export type RESTAuthClient<TSession = unknown, TCredentials = unknown> = {
|
|
124
|
+
login: (credentials: TCredentials) => Promise<TSession>;
|
|
125
|
+
logout?: () => Promise<void>;
|
|
126
|
+
refresh?: (refreshToken: string) => Promise<TSession>;
|
|
127
|
+
getCurrentUser?: () => Promise<TSession>;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export type ClientAdapter<TSession = unknown, TCredentials = unknown> =
|
|
131
|
+
| GraphQLAuthClient<TSession, TCredentials>
|
|
132
|
+
| RESTAuthClient<TSession, TCredentials>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type AuthStatus =
|
|
2
|
+
| 'idle'
|
|
3
|
+
| 'loading'
|
|
4
|
+
| 'authenticated'
|
|
5
|
+
| 'unauthenticated'
|
|
6
|
+
| 'error';
|
|
7
|
+
|
|
8
|
+
export type TokenType = 'bearer' | 'jwt' | 'custom';
|
|
9
|
+
|
|
10
|
+
export type RefreshStrategy = 'auto' | 'manual' | 'sliding';
|
|
11
|
+
|
|
12
|
+
export type AuthSession<
|
|
13
|
+
TUser = unknown,
|
|
14
|
+
TRole = string,
|
|
15
|
+
TPermission = string,
|
|
16
|
+
> = {
|
|
17
|
+
user?: TUser | null;
|
|
18
|
+
accessToken?: string | null;
|
|
19
|
+
refreshToken?: string | null;
|
|
20
|
+
tokenType?: TokenType;
|
|
21
|
+
roles?: TRole[] | null;
|
|
22
|
+
permissions?: TPermission[] | null;
|
|
23
|
+
expiresAt?: number | null;
|
|
24
|
+
refreshExpiresAt?: number | null;
|
|
25
|
+
issuedAt?: number | null;
|
|
26
|
+
meta?: Record<string, unknown> | null;
|
|
27
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './core';
|
|
2
|
+
export * from './permissions';
|
|
3
|
+
export * from './state';
|
|
4
|
+
export * from './storage';
|
|
5
|
+
export * from './middleware';
|
|
6
|
+
export * from './token-manager';
|
|
7
|
+
export * from './adapter-config';
|
|
8
|
+
export * from './adapter';
|
|
9
|
+
export * from './utils';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AuthAdapterState } from './state';
|
|
2
|
+
|
|
3
|
+
export type AuthMiddleware<
|
|
4
|
+
TSession = unknown,
|
|
5
|
+
TUser = unknown,
|
|
6
|
+
TRole extends string = string,
|
|
7
|
+
TPermission extends string = string,
|
|
8
|
+
> = {
|
|
9
|
+
onBeforeLogin?: (credentials: unknown) => Promise<void> | void;
|
|
10
|
+
onAfterLogin?: (
|
|
11
|
+
state: AuthAdapterState<TSession, TUser, TRole, TPermission>,
|
|
12
|
+
) => Promise<void> | void;
|
|
13
|
+
onBeforeLogout?: () => Promise<void> | void;
|
|
14
|
+
onAfterLogout?: () => Promise<void> | void;
|
|
15
|
+
onRefresh?: (
|
|
16
|
+
state: AuthAdapterState<TSession, TUser, TRole, TPermission>,
|
|
17
|
+
) => Promise<void> | void;
|
|
18
|
+
onError?: (error: unknown) => Promise<void> | void;
|
|
19
|
+
onSessionExpired?: () => Promise<void> | void;
|
|
20
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type PermissionOperator = 'AND' | 'OR';
|
|
2
|
+
|
|
3
|
+
export type PermissionPolicy<TPermission extends string = string> = {
|
|
4
|
+
operator?: PermissionOperator;
|
|
5
|
+
permissions: TPermission[];
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type PermissionRule<
|
|
9
|
+
TRole extends string = string,
|
|
10
|
+
TPermission extends string = string,
|
|
11
|
+
> = {
|
|
12
|
+
roles?: TRole | TRole[];
|
|
13
|
+
permissions?: TPermission | TPermission[] | PermissionPolicy<TPermission>;
|
|
14
|
+
requireAll?: boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type PermissionHierarchy<TPermission extends string = string> = {
|
|
18
|
+
[key in TPermission]?: TPermission[];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type RoleHierarchy<TRole extends string = string> = {
|
|
22
|
+
[key in TRole]?: TRole[];
|
|
23
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AuthStatus } from './core';
|
|
2
|
+
|
|
3
|
+
export type AuthAdapterState<TSession, TUser, TRole, TPermission> = {
|
|
4
|
+
status: AuthStatus;
|
|
5
|
+
session: TSession | null;
|
|
6
|
+
user: TUser | null;
|
|
7
|
+
roles: TRole[];
|
|
8
|
+
permissions: TPermission[];
|
|
9
|
+
error?: unknown;
|
|
10
|
+
lastRefresh?: number;
|
|
11
|
+
tokenExpiresIn?: number;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type AuthAdapterSubscriber<TSession, TUser, TRole, TPermission> = (
|
|
15
|
+
state: AuthAdapterState<TSession, TUser, TRole, TPermission>,
|
|
16
|
+
) => void;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type AuthStorage<TSession> = {
|
|
2
|
+
get: () => Promise<TSession | null> | TSession | null;
|
|
3
|
+
set: (value: TSession | null) => Promise<void> | void;
|
|
4
|
+
clear: () => Promise<void> | void;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export type StorageType = 'local' | 'session' | 'cookie' | 'memory';
|
|
8
|
+
|
|
9
|
+
export type StorageOptions = {
|
|
10
|
+
key?: string;
|
|
11
|
+
encrypt?: boolean;
|
|
12
|
+
encryptionKey?: string;
|
|
13
|
+
storage?: StorageType;
|
|
14
|
+
cookieOptions?: {
|
|
15
|
+
domain?: string;
|
|
16
|
+
path?: string;
|
|
17
|
+
secure?: boolean;
|
|
18
|
+
sameSite?: 'strict' | 'lax' | 'none';
|
|
19
|
+
maxAge?: number;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type TokenManager = {
|
|
2
|
+
isExpired: (expiresAt?: number | null) => boolean;
|
|
3
|
+
shouldRefresh: (expiresAt?: number | null, threshold?: number) => boolean;
|
|
4
|
+
getTimeUntilExpiry: (expiresAt?: number | null) => number;
|
|
5
|
+
scheduleRefresh?: (
|
|
6
|
+
callback: () => void,
|
|
7
|
+
expiresAt?: number | null,
|
|
8
|
+
) => () => void;
|
|
9
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Utility Types
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
import type { AuthAdapter } from "./adapter";
|
|
6
|
+
|
|
7
|
+
export type InferSession<T> = T extends AuthAdapter<
|
|
8
|
+
infer _User,
|
|
9
|
+
infer _Role extends string,
|
|
10
|
+
infer _Permission extends string,
|
|
11
|
+
infer TSession,
|
|
12
|
+
infer _Credentials
|
|
13
|
+
>
|
|
14
|
+
? TSession
|
|
15
|
+
: never;
|
|
16
|
+
|
|
17
|
+
export type InferUser<T> = T extends AuthAdapter<
|
|
18
|
+
infer TUser,
|
|
19
|
+
infer _Role extends string,
|
|
20
|
+
infer _Permission extends string,
|
|
21
|
+
infer _Session,
|
|
22
|
+
infer _Credentials
|
|
23
|
+
>
|
|
24
|
+
? TUser
|
|
25
|
+
: never;
|
|
26
|
+
|
|
27
|
+
export type InferRole<T> = T extends AuthAdapter<
|
|
28
|
+
infer _User,
|
|
29
|
+
infer TRole extends string,
|
|
30
|
+
infer _Permission extends string,
|
|
31
|
+
infer _Session,
|
|
32
|
+
infer _Credentials
|
|
33
|
+
>
|
|
34
|
+
? TRole
|
|
35
|
+
: never;
|
|
36
|
+
|
|
37
|
+
export type InferPermission<T> = T extends AuthAdapter<
|
|
38
|
+
infer _User,
|
|
39
|
+
infer _Role extends string,
|
|
40
|
+
infer TPermission extends string,
|
|
41
|
+
infer _Session,
|
|
42
|
+
infer _Credentials
|
|
43
|
+
>
|
|
44
|
+
? TPermission
|
|
45
|
+
: never;
|
|
46
|
+
|
|
47
|
+
export type InferCredentials<T> = T extends AuthAdapter<
|
|
48
|
+
infer _User,
|
|
49
|
+
infer _Role extends string,
|
|
50
|
+
infer _Permission extends string,
|
|
51
|
+
infer _Session,
|
|
52
|
+
infer TCredentials
|
|
53
|
+
>
|
|
54
|
+
? TCredentials
|
|
55
|
+
: never;
|
|
@@ -16,7 +16,7 @@ import type {
|
|
|
16
16
|
AuthStatus,
|
|
17
17
|
PermissionPolicy,
|
|
18
18
|
PermissionRule,
|
|
19
|
-
} from '
|
|
19
|
+
} from '../types';
|
|
20
20
|
|
|
21
21
|
const unique = <T>(values: T[]): T[] => {
|
|
22
22
|
return Array.from(new Set(values));
|
|
@@ -334,7 +334,8 @@ export function createAuthAdapter<
|
|
|
334
334
|
return nextState;
|
|
335
335
|
} catch (error) {
|
|
336
336
|
await executeMiddleware('onError', error);
|
|
337
|
-
|
|
337
|
+
await setSession(null, 'error', error);
|
|
338
|
+
throw error;
|
|
338
339
|
}
|
|
339
340
|
};
|
|
340
341
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export function createApolloAuthLink(
|
|
2
|
+
getToken: () => string | null,
|
|
3
|
+
options?: {
|
|
4
|
+
tokenType?: string
|
|
5
|
+
},
|
|
6
|
+
) {
|
|
7
|
+
const tokenType = options?.tokenType ?? 'Bearer'
|
|
8
|
+
|
|
9
|
+
// This requires @apollo/client to be installed
|
|
10
|
+
// We'll return a function that creates the link to avoid direct dependency
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
+
return (ApolloLink: any) => {
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
|
+
return new ApolloLink((operation: any, forward: any) => {
|
|
15
|
+
const token = getToken()
|
|
16
|
+
|
|
17
|
+
if (token) {
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
+
operation.setContext(({ headers = {} }: any) => ({
|
|
20
|
+
headers: {
|
|
21
|
+
...headers,
|
|
22
|
+
authorization: `${tokenType} ${token}`,
|
|
23
|
+
},
|
|
24
|
+
}))
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return forward(operation)
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export function createAxiosAuthInterceptor(
|
|
2
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3
|
+
axiosInstance: any,
|
|
4
|
+
getToken: () => string | null,
|
|
5
|
+
options?: {
|
|
6
|
+
tokenType?: string
|
|
7
|
+
onTokenExpired?: () => void
|
|
8
|
+
refreshToken?: () => Promise<void>
|
|
9
|
+
},
|
|
10
|
+
) {
|
|
11
|
+
const tokenType = options?.tokenType ?? 'Bearer'
|
|
12
|
+
|
|
13
|
+
// Request interceptor
|
|
14
|
+
axiosInstance.interceptors.request.use(
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
+
async (config: any) => {
|
|
17
|
+
const token = getToken()
|
|
18
|
+
if (token) {
|
|
19
|
+
config.headers.Authorization = `${tokenType} ${token}`
|
|
20
|
+
}
|
|
21
|
+
return config
|
|
22
|
+
},
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
24
|
+
(error: any) => Promise.reject(error),
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
// Response interceptor for token refresh
|
|
28
|
+
if (options?.refreshToken) {
|
|
29
|
+
axiosInstance.interceptors.response.use(
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
31
|
+
(response: any) => response,
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
33
|
+
async (error: any) => {
|
|
34
|
+
const originalRequest = error.config
|
|
35
|
+
|
|
36
|
+
// If token expired and we haven't retried yet
|
|
37
|
+
if (
|
|
38
|
+
error.response?.status === 401 &&
|
|
39
|
+
!originalRequest._retry &&
|
|
40
|
+
options.refreshToken
|
|
41
|
+
) {
|
|
42
|
+
originalRequest._retry = true
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
await options.refreshToken()
|
|
46
|
+
const token = getToken()
|
|
47
|
+
if (token) {
|
|
48
|
+
originalRequest.headers.Authorization = `${tokenType} ${token}`
|
|
49
|
+
}
|
|
50
|
+
return axiosInstance(originalRequest)
|
|
51
|
+
} catch (refreshError) {
|
|
52
|
+
options.onTokenExpired?.()
|
|
53
|
+
return Promise.reject(refreshError)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return Promise.reject(error)
|
|
58
|
+
},
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export function createAuthFetch(
|
|
2
|
+
getToken: () => string | null,
|
|
3
|
+
options?: {
|
|
4
|
+
tokenType?: string
|
|
5
|
+
onTokenExpired?: () => void
|
|
6
|
+
refreshToken?: () => Promise<void>
|
|
7
|
+
},
|
|
8
|
+
): typeof fetch {
|
|
9
|
+
const tokenType = options?.tokenType ?? 'Bearer'
|
|
10
|
+
|
|
11
|
+
return async (
|
|
12
|
+
input: RequestInfo | URL,
|
|
13
|
+
init?: RequestInit,
|
|
14
|
+
): Promise<Response> => {
|
|
15
|
+
const token = getToken()
|
|
16
|
+
const headers = new Headers(init?.headers)
|
|
17
|
+
|
|
18
|
+
if (token) {
|
|
19
|
+
headers.set('Authorization', `${tokenType} ${token}`)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const response = await fetch(input, {
|
|
23
|
+
...init,
|
|
24
|
+
headers,
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
// Handle token expiration
|
|
28
|
+
if (response.status === 401 && options?.refreshToken) {
|
|
29
|
+
try {
|
|
30
|
+
await options.refreshToken()
|
|
31
|
+
const newToken = getToken()
|
|
32
|
+
|
|
33
|
+
if (newToken) {
|
|
34
|
+
headers.set('Authorization', `${tokenType} ${newToken}`)
|
|
35
|
+
return await fetch(input, {
|
|
36
|
+
...init,
|
|
37
|
+
headers,
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
} catch (error) {
|
|
41
|
+
options.onTokenExpired?.()
|
|
42
|
+
throw error
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return response
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { AuthAdapterConfig, AuthSession, GraphQLAuthClient } from '../../types'
|
|
2
|
+
|
|
3
|
+
export type GraphQLClientAdapterOptions<
|
|
4
|
+
TUser = unknown,
|
|
5
|
+
TRole extends string = string,
|
|
6
|
+
TPermission extends string = string,
|
|
7
|
+
TSession extends AuthSession<TUser, TRole, TPermission> = AuthSession<
|
|
8
|
+
TUser,
|
|
9
|
+
TRole,
|
|
10
|
+
TPermission
|
|
11
|
+
>,
|
|
12
|
+
TCredentials = unknown,
|
|
13
|
+
> = {
|
|
14
|
+
client: GraphQLAuthClient<TSession, TCredentials>
|
|
15
|
+
resolveUser?: (session: TSession | null) => TUser | null
|
|
16
|
+
resolveRoles?: (session: TSession | null) => TRole[]
|
|
17
|
+
resolvePermissions?: (session: TSession | null) => TPermission[]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function createGraphQLAuthAdapter<
|
|
21
|
+
TUser = unknown,
|
|
22
|
+
TRole extends string = string,
|
|
23
|
+
TPermission extends string = string,
|
|
24
|
+
TSession extends AuthSession<TUser, TRole, TPermission> = AuthSession<
|
|
25
|
+
TUser,
|
|
26
|
+
TRole,
|
|
27
|
+
TPermission
|
|
28
|
+
>,
|
|
29
|
+
TCredentials = unknown,
|
|
30
|
+
>(
|
|
31
|
+
options: GraphQLClientAdapterOptions<
|
|
32
|
+
TUser,
|
|
33
|
+
TRole,
|
|
34
|
+
TPermission,
|
|
35
|
+
TSession,
|
|
36
|
+
TCredentials
|
|
37
|
+
>,
|
|
38
|
+
): Partial<
|
|
39
|
+
AuthAdapterConfig<TUser, TRole, TPermission, TSession, TCredentials>
|
|
40
|
+
> {
|
|
41
|
+
return {
|
|
42
|
+
login: options.client.login,
|
|
43
|
+
logout: options.client.logout,
|
|
44
|
+
refresh: options.client.refresh
|
|
45
|
+
? async (session: TSession) => {
|
|
46
|
+
if (!session.refreshToken) {
|
|
47
|
+
throw new Error('No refresh token available')
|
|
48
|
+
}
|
|
49
|
+
if (!options.client.refresh) {
|
|
50
|
+
throw new Error('Refresh function not provided')
|
|
51
|
+
}
|
|
52
|
+
return await options.client.refresh(session.refreshToken)
|
|
53
|
+
}
|
|
54
|
+
: undefined,
|
|
55
|
+
loadSession: options.client.getCurrentUser,
|
|
56
|
+
resolveUser: options.resolveUser,
|
|
57
|
+
resolveRoles: options.resolveRoles,
|
|
58
|
+
resolvePermissions: options.resolvePermissions,
|
|
59
|
+
}
|
|
60
|
+
}
|