@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.
@@ -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 color="blue">Run Query</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
@@ -43,4 +43,5 @@ export * from './builders/filters/index.js';
43
43
  export * from './types/index.js';
44
44
  export * from './utils/index.js';
45
45
  import 'iconify-icon';
46
+ export * from './keycloak/index.js';
46
47
  export { YouTube, BaseEditor };
package/dist/index.js CHANGED
@@ -44,4 +44,5 @@ export * from './builders/filters/index.js';
44
44
  export * from './types/index.js';
45
45
  export * from './utils/index.js';
46
46
  import 'iconify-icon';
47
+ export * from './keycloak/index.js';
47
48
  export { YouTube, BaseEditor };
@@ -0,0 +1,2 @@
1
+ export * from './types.js';
2
+ export * from './keycloakService.svelte.js';
@@ -0,0 +1,2 @@
1
+ export * from './types.js';
2
+ export * from './keycloakService.svelte.js';
@@ -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 {};
@@ -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>, {}, "query" | "read">;
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.26",
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",