@rkosafo/cai.components 0.0.26 → 0.0.28
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/builders/filters/FilterBuilder.svelte +5 -2
- 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.svelte.d.ts +32 -0
- package/dist/keycloak/keycloakService.svelte.js +142 -0
- package/dist/keycloak/types.d.ts +50 -0
- package/dist/keycloak/types.js +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/ui/datatable/Datatable.svelte.d.ts +1 -1
- package/package.json +2 -1
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
import { onMount } from 'svelte';
|
|
81
81
|
import { fade } from 'svelte/transition';
|
|
82
82
|
|
|
83
|
-
let { columns = [], filters = $bindable([]) }: FilterBuilderProps = $props();
|
|
83
|
+
let { columns = [], filters = $bindable([]), onRunQuery }: FilterBuilderProps = $props();
|
|
84
84
|
|
|
85
85
|
// Operator mappings for each type
|
|
86
86
|
const operatorsByType = {
|
|
@@ -543,7 +543,10 @@
|
|
|
543
543
|
<p class="text-sm text-gray-600">Live preview of your filter conditions</p>
|
|
544
544
|
</div>
|
|
545
545
|
<div class="flex items-center">
|
|
546
|
-
<Button
|
|
546
|
+
<Button
|
|
547
|
+
color="blue"
|
|
548
|
+
onclick={() => onRunQuery({ jsonBuild: jsonQuery, sqlBuild: sqlQuery })}>Run Query</Button
|
|
549
|
+
>
|
|
547
550
|
</div>
|
|
548
551
|
</div>
|
|
549
552
|
|
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 {};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -737,9 +737,14 @@ export interface FilterBuilderItem {
|
|
|
737
737
|
logicalOperator?: 'AND' | 'OR';
|
|
738
738
|
label?: string;
|
|
739
739
|
}
|
|
740
|
+
export interface FilterBuilderExport {
|
|
741
|
+
sqlBuild: string;
|
|
742
|
+
jsonBuild: any[];
|
|
743
|
+
}
|
|
740
744
|
export interface FilterBuilderProps {
|
|
741
745
|
columns?: FilterBuilderColumnConfig[];
|
|
742
746
|
filters?: FilterBuilderItem[];
|
|
747
|
+
onRunQuery?: (val: FilterBuilderExport) => void;
|
|
743
748
|
}
|
|
744
749
|
export interface ITab {
|
|
745
750
|
id: number | string;
|
|
@@ -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.28",
|
|
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",
|