@rkosafo/cai.components 0.0.26 → 0.0.27
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.js +1 -0
- package/dist/keycloak/index.d.ts +2 -0
- package/dist/keycloak/index.js +2 -0
- package/dist/keycloak/keycloakService.d.ts +32 -0
- package/dist/keycloak/keycloakService.js +142 -0
- package/dist/keycloak/types.d.ts +50 -0
- package/dist/keycloak/types.js +1 -0
- package/dist/ui/datatable/Datatable.svelte.d.ts +1 -1
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { AuthUserInfo, FetchAuthUserInfoFn, KeycloakConfig } from './index.js';
|
|
2
|
+
export declare function createAuthStore(): {
|
|
3
|
+
isLoading: boolean;
|
|
4
|
+
isAuthenticated: boolean;
|
|
5
|
+
accessToken: string;
|
|
6
|
+
idToken: string;
|
|
7
|
+
userInfo: AuthUserInfo | null;
|
|
8
|
+
authError: string;
|
|
9
|
+
userIsFound: boolean;
|
|
10
|
+
};
|
|
11
|
+
export type AuthStoreType = ReturnType<typeof createAuthStore>;
|
|
12
|
+
export declare class KeycloakService {
|
|
13
|
+
private keycloak;
|
|
14
|
+
private initialized;
|
|
15
|
+
private store;
|
|
16
|
+
private fetchUserInfo;
|
|
17
|
+
private onAuthenticated?;
|
|
18
|
+
private onLogout?;
|
|
19
|
+
private onError?;
|
|
20
|
+
constructor(store: AuthStoreType, fetchUserInfo: FetchAuthUserInfoFn, callbacks?: {
|
|
21
|
+
onAuthenticated?: (userInfo: AuthUserInfo) => void;
|
|
22
|
+
onLogout?: () => void;
|
|
23
|
+
onError?: (error: string) => void;
|
|
24
|
+
});
|
|
25
|
+
init(config: KeycloakConfig, initOptions?: any): Promise<void>;
|
|
26
|
+
private setTokenDetails;
|
|
27
|
+
login(): void;
|
|
28
|
+
refreshToken(): Promise<void>;
|
|
29
|
+
logout(): void;
|
|
30
|
+
getKeycloakInstance(): any;
|
|
31
|
+
isInitialized(): boolean;
|
|
32
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import Keycloak from 'keycloak-js';
|
|
2
|
+
export function createAuthStore() {
|
|
3
|
+
return {
|
|
4
|
+
isLoading: $state(true),
|
|
5
|
+
isAuthenticated: $state(false),
|
|
6
|
+
accessToken: $state(''),
|
|
7
|
+
idToken: $state(''),
|
|
8
|
+
userInfo: $state(null),
|
|
9
|
+
authError: $state(''),
|
|
10
|
+
userIsFound: $state(false)
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export class KeycloakService {
|
|
14
|
+
keycloak = null;
|
|
15
|
+
initialized = false;
|
|
16
|
+
store;
|
|
17
|
+
fetchUserInfo;
|
|
18
|
+
onAuthenticated;
|
|
19
|
+
onLogout;
|
|
20
|
+
onError;
|
|
21
|
+
constructor(store, fetchUserInfo, callbacks) {
|
|
22
|
+
this.store = store;
|
|
23
|
+
this.fetchUserInfo = fetchUserInfo;
|
|
24
|
+
this.onAuthenticated = callbacks?.onAuthenticated;
|
|
25
|
+
this.onLogout = callbacks?.onLogout;
|
|
26
|
+
this.onError = callbacks?.onError;
|
|
27
|
+
}
|
|
28
|
+
async init(config, initOptions = { onLoad: 'login-required', checkLoginIframe: false }) {
|
|
29
|
+
try {
|
|
30
|
+
this.keycloak = new Keycloak(config);
|
|
31
|
+
const authenticated = await this.keycloak.init(initOptions);
|
|
32
|
+
if (authenticated) {
|
|
33
|
+
await this.setTokenDetails(this.keycloak.idTokenParsed);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
this.setTokenDetails(null);
|
|
37
|
+
}
|
|
38
|
+
this.initialized = true;
|
|
39
|
+
this.store.isLoading = false;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
this.initialized = false;
|
|
43
|
+
const errorMessage = error instanceof Error ? error.message : 'Initialization failed';
|
|
44
|
+
this.store.authError = errorMessage;
|
|
45
|
+
this.onError?.(errorMessage);
|
|
46
|
+
this.store.isLoading = false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async setTokenDetails(details) {
|
|
50
|
+
if (!details) {
|
|
51
|
+
this.store.isAuthenticated = false;
|
|
52
|
+
this.store.accessToken = '';
|
|
53
|
+
this.store.idToken = '';
|
|
54
|
+
this.store.userInfo = null;
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
this.store.isAuthenticated = true;
|
|
59
|
+
this.store.accessToken = this.keycloak.token;
|
|
60
|
+
this.store.idToken = this.keycloak.idToken;
|
|
61
|
+
this.store.authError = '';
|
|
62
|
+
// Fetch user info using provided function
|
|
63
|
+
const meRet = await this.fetchUserInfo(this.keycloak.token);
|
|
64
|
+
let extras = {};
|
|
65
|
+
if (meRet.success) {
|
|
66
|
+
extras = meRet.data;
|
|
67
|
+
this.store.userIsFound = true;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
this.store.authError = meRet.message || 'Failed to fetch user info';
|
|
71
|
+
this.store.userIsFound = meRet.code === 402;
|
|
72
|
+
}
|
|
73
|
+
const userInfo = {
|
|
74
|
+
id: extras.id,
|
|
75
|
+
email: details.email,
|
|
76
|
+
firstName: details.given_name,
|
|
77
|
+
lastName: details.family_name,
|
|
78
|
+
otherNames: '',
|
|
79
|
+
name: details.name,
|
|
80
|
+
username: details.preferred_username,
|
|
81
|
+
initials: details.name
|
|
82
|
+
?.split(' ')
|
|
83
|
+
.filter((x) => x.length > 1)
|
|
84
|
+
.map((x) => x[0])
|
|
85
|
+
.join('') || '',
|
|
86
|
+
department: extras?.department || '',
|
|
87
|
+
departmentId: extras?.departmentId,
|
|
88
|
+
role: extras?.role,
|
|
89
|
+
roleId: extras?.roleId,
|
|
90
|
+
tags: extras?.tags ?? [],
|
|
91
|
+
permissions: extras?.permissions ?? [],
|
|
92
|
+
type: extras?.type,
|
|
93
|
+
activeDashboardId: extras?.activeDashboardId,
|
|
94
|
+
district: extras?.district,
|
|
95
|
+
phoneNumber: extras?.phoneNumber || '',
|
|
96
|
+
profileImage: extras?.profileImage || '',
|
|
97
|
+
status: extras?.status || ''
|
|
98
|
+
};
|
|
99
|
+
this.store.userInfo = userInfo;
|
|
100
|
+
this.onAuthenticated?.(userInfo);
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
const errorMessage = error instanceof Error ? error.message : 'Failed to set token details';
|
|
104
|
+
this.store.authError = errorMessage;
|
|
105
|
+
this.onError?.(errorMessage);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
login() {
|
|
109
|
+
if (this.initialized && this.keycloak) {
|
|
110
|
+
this.keycloak.login();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async refreshToken() {
|
|
114
|
+
if (!this.initialized || !this.keycloak)
|
|
115
|
+
return;
|
|
116
|
+
try {
|
|
117
|
+
const refreshed = await this.keycloak.updateToken(30);
|
|
118
|
+
if (refreshed) {
|
|
119
|
+
await this.setTokenDetails(this.keycloak.idTokenParsed);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
const errorMessage = error instanceof Error ? error.message : 'Token refresh failed';
|
|
124
|
+
this.store.authError = errorMessage;
|
|
125
|
+
this.onError?.(errorMessage);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
logout() {
|
|
129
|
+
if (!this.initialized || !this.keycloak)
|
|
130
|
+
return;
|
|
131
|
+
this.keycloak.logout();
|
|
132
|
+
this.store.userInfo = null;
|
|
133
|
+
this.store.isAuthenticated = false;
|
|
134
|
+
this.onLogout?.();
|
|
135
|
+
}
|
|
136
|
+
getKeycloakInstance() {
|
|
137
|
+
return this.keycloak;
|
|
138
|
+
}
|
|
139
|
+
isInitialized() {
|
|
140
|
+
return this.initialized;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export interface AuthUserInfo {
|
|
2
|
+
id: string;
|
|
3
|
+
email: string;
|
|
4
|
+
firstName: string;
|
|
5
|
+
lastName: string;
|
|
6
|
+
otherNames: string;
|
|
7
|
+
name: string;
|
|
8
|
+
username: string;
|
|
9
|
+
initials: string;
|
|
10
|
+
profileImage: string;
|
|
11
|
+
role: string;
|
|
12
|
+
roleId: number;
|
|
13
|
+
permissions: string[];
|
|
14
|
+
status: string;
|
|
15
|
+
department?: string;
|
|
16
|
+
departmentId?: number;
|
|
17
|
+
tags?: string[];
|
|
18
|
+
type?: string;
|
|
19
|
+
activeDashboardId?: number;
|
|
20
|
+
district?: string;
|
|
21
|
+
phoneNumber?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface AuthStore {
|
|
24
|
+
isLoading: boolean;
|
|
25
|
+
isAuthenticated: boolean;
|
|
26
|
+
accessToken: string;
|
|
27
|
+
idToken: string;
|
|
28
|
+
userInfo: AuthUserInfo | null;
|
|
29
|
+
authError: string;
|
|
30
|
+
userIsFound: boolean;
|
|
31
|
+
}
|
|
32
|
+
export interface KeycloakConfig {
|
|
33
|
+
url: string;
|
|
34
|
+
realm: string;
|
|
35
|
+
clientId: string;
|
|
36
|
+
}
|
|
37
|
+
export interface FetchAuthUserInfoFn {
|
|
38
|
+
(token?: string): Promise<{
|
|
39
|
+
success: boolean;
|
|
40
|
+
data?: any;
|
|
41
|
+
message?: string;
|
|
42
|
+
code?: number;
|
|
43
|
+
}>;
|
|
44
|
+
}
|
|
45
|
+
export interface FetchAuthDashboardsFn {
|
|
46
|
+
(): Promise<{
|
|
47
|
+
success: boolean;
|
|
48
|
+
data?: any;
|
|
49
|
+
}>;
|
|
50
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare function refetchDatatable(params?: TableFilter): void;
|
|
2
2
|
import { type DatatableProps, type TableFilter } from '../../index.js';
|
|
3
|
-
declare const Datatable: import("svelte").Component<DatatableProps<any>, {}, "
|
|
3
|
+
declare const Datatable: import("svelte").Component<DatatableProps<any>, {}, "read" | "query">;
|
|
4
4
|
type Datatable = ReturnType<typeof Datatable>;
|
|
5
5
|
export default Datatable;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rkosafo/cai.components",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.27",
|
|
4
4
|
"files": [
|
|
5
5
|
"dist",
|
|
6
6
|
"!dist/**/*.test.*",
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
"date-fns": "^4.1.0",
|
|
59
59
|
"felte": "^1.3.0",
|
|
60
60
|
"iconify-icon": "^3.0.0",
|
|
61
|
+
"keycloak-js": "^26.2.0",
|
|
61
62
|
"lodash": "^4.17.21",
|
|
62
63
|
"mdsvex": "^0.12.6",
|
|
63
64
|
"nanoid": "^5.1.5",
|