@iblai/web-utils 0.2.1 → 1.0.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 (38) hide show
  1. package/README.md +504 -0
  2. package/dist/data-layer/src/features/chat-files/api-slice.d.ts +185 -0
  3. package/dist/data-layer/src/features/chat-files/types.d.ts +32 -0
  4. package/dist/data-layer/src/features/core/api-slice.d.ts +419 -61
  5. package/dist/data-layer/src/features/core/constants.d.ts +3 -0
  6. package/dist/data-layer/src/features/core/custom-api-slice.d.ts +50 -50
  7. package/dist/data-layer/src/features/core/custom-public-image-asset-api-slice.d.ts +333 -0
  8. package/dist/data-layer/src/features/core/types.d.ts +33 -0
  9. package/dist/data-layer/src/features/credentials/api-slice.d.ts +62 -39
  10. package/dist/data-layer/src/features/mentor/api-slice.d.ts +980 -188
  11. package/dist/data-layer/src/features/notifications/constants.d.ts +6 -0
  12. package/dist/data-layer/src/features/notifications/custom-api-slice.d.ts +43 -43
  13. package/dist/data-layer/src/features/notifications/types.d.ts +25 -2
  14. package/dist/data-layer/src/index.d.ts +3 -0
  15. package/dist/index.d.ts +425 -66
  16. package/dist/index.esm.js +999 -109
  17. package/dist/index.esm.js.map +1 -1
  18. package/dist/index.js +1030 -107
  19. package/dist/index.js.map +1 -1
  20. package/dist/package.json +4 -2
  21. package/dist/web-utils/src/constants/chat.d.ts +8 -0
  22. package/dist/web-utils/src/features/files/filesSlice.d.ts +20 -0
  23. package/dist/web-utils/src/features/index.d.ts +1 -0
  24. package/dist/web-utils/src/hooks/chat/use-advanced-chat.d.ts +6 -4
  25. package/dist/web-utils/src/hooks/chat/use-chat-v2.d.ts +11 -1
  26. package/dist/web-utils/src/index.d.ts +2 -0
  27. package/dist/web-utils/src/index.web.d.ts +14 -12
  28. package/dist/web-utils/src/providers/auth-provider.d.ts +9 -1
  29. package/dist/web-utils/src/providers/tenant-provider.d.ts +2 -1
  30. package/dist/web-utils/src/services/__tests__/file-upload.test.d.ts +1 -0
  31. package/dist/web-utils/src/services/file-upload.d.ts +60 -0
  32. package/dist/web-utils/src/services/index.d.ts +1 -0
  33. package/dist/web-utils/src/types/file-upload.d.ts +62 -0
  34. package/dist/web-utils/src/types/index.d.ts +1 -0
  35. package/dist/web-utils/src/utils/auth.d.ts +180 -0
  36. package/dist/web-utils/src/utils/index.d.ts +1 -0
  37. package/dist/web-utils/tsconfig.tsbuildinfo +1 -1
  38. package/package.json +3 -3
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iblai/web-utils",
3
- "version": "0.2.0",
3
+ "version": "1.0.0",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.esm.js",
6
6
  "types": "./dist/index.d.ts",
@@ -22,6 +22,7 @@
22
22
  "devDependencies": {
23
23
  "@eslint/js": "^9.39.1",
24
24
  "@rollup/plugin-commonjs": "^28.0.9",
25
+ "@rollup/plugin-json": "^6.1.0",
25
26
  "@rollup/plugin-node-resolve": "^16.0.3",
26
27
  "@rollup/plugin-typescript": "^12.3.0",
27
28
  "@testing-library/jest-dom": "6.6.3",
@@ -48,8 +49,9 @@
48
49
  "vitest": "^3.2.4"
49
50
  },
50
51
  "dependencies": {
51
- "@iblai/data-layer": "workspace:*",
52
+ "@iblai/data-layer": "1.0.0",
52
53
  "@reduxjs/toolkit": "^2.10.0",
54
+ "axios": "^1.13.1",
53
55
  "dayjs": "^1.11.19",
54
56
  "jwt-decode": "^4.0.0",
55
57
  "react-redux": "^9.2.0",
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Chat area size constants
3
+ */
4
+ export declare const CHAT_AREA_SIZE: {
5
+ readonly DEFAULT: 672;
6
+ readonly MIN: 672;
7
+ readonly MAX: 1024;
8
+ };
@@ -0,0 +1,20 @@
1
+ import { Slice } from "@reduxjs/toolkit";
2
+ export interface AttachedFile {
3
+ id: string;
4
+ fileName: string;
5
+ fileType: string;
6
+ fileSize: number;
7
+ uploadUrl: string;
8
+ uploadProgress: number;
9
+ uploadStatus: "pending" | "uploading" | "processing" | "success" | "error";
10
+ fileKey?: string;
11
+ fileId?: string;
12
+ retryCount?: number;
13
+ fileUrl?: string;
14
+ }
15
+ export interface FilesState {
16
+ attachedFiles: AttachedFile[];
17
+ }
18
+ export declare const filesSlice: Slice<FilesState>;
19
+ export declare const addFiles: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, removeFile: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, clearFiles: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, updateFileProgress: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, updateFileStatus: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, updateFileUrl: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, updateFileMetadata: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, updateFileRetryCount: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, updateFileUrlFromWebSocket: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>;
20
+ export declare const filesReducer: import("@reduxjs/toolkit").Reducer<FilesState>;
@@ -1,2 +1,3 @@
1
1
  export * from "./chat/slice";
2
2
  export * from "./tracking";
3
+ export * from "./files/filesSlice";
@@ -10,22 +10,24 @@ type Props = {
10
10
  username: string;
11
11
  token: string;
12
12
  wsUrl: string;
13
- redirectToAuthSpa: () => void;
13
+ redirectToAuthSpa: (redirectTo?: string, platformKey?: string, logout?: boolean) => void;
14
14
  stopGenerationWsUrl: string;
15
15
  sendMessageToParentWebsite?: (payload: unknown) => void;
16
16
  errorHandler?: (message: string, error?: any) => void;
17
17
  isPreviewMode?: boolean;
18
18
  mentorShareableToken?: string | null;
19
19
  on402Error?: (message: Record<string, unknown>) => void;
20
+ cachedSessionId?: string;
21
+ onStartNewChat?: (sessionId: string) => void;
20
22
  };
21
- export declare function useAdvancedChat({ tenantKey, mentorId, username, token, wsUrl, stopGenerationWsUrl, redirectToAuthSpa, errorHandler, sendMessageToParentWebsite, isPreviewMode, mentorShareableToken, on402Error, }: Props): {
23
+ export declare function useAdvancedChat({ tenantKey, mentorId, username, token, wsUrl, stopGenerationWsUrl, redirectToAuthSpa, errorHandler, sendMessageToParentWebsite, isPreviewMode, mentorShareableToken, on402Error, cachedSessionId, onStartNewChat, }: Props): {
22
24
  messages: Message[];
23
25
  isStreaming: boolean;
24
26
  status: ChatStatus;
25
27
  isPending: boolean;
26
28
  isStopped: boolean;
27
29
  isError: boolean;
28
- currentStreamingMessage: import("../../features/chat/slice").StreamingMessage;
30
+ currentStreamingMessage: import("../../features").StreamingMessage;
29
31
  activeTab: "chat" | "summarize" | "translate" | "expand";
30
32
  uniqueMentorId: string;
31
33
  mentorName: string;
@@ -41,7 +43,7 @@ export declare function useAdvancedChat({ tenantKey, mentorId, username, token,
41
43
  ws: React.MutableRefObject<WebSocket | null>;
42
44
  isConnected: React.MutableRefObject<boolean>;
43
45
  messageQueue: React.MutableRefObject<any[]>;
44
- sessionIds: import("../../features/chat/slice").SessionIds;
46
+ sessionIds: import("../../features").SessionIds;
45
47
  enableSafetyDisclaimer: any;
46
48
  resetConnection: () => void;
47
49
  };
@@ -1,11 +1,19 @@
1
1
  import type { AdvancedTab } from "../../utils/data/advanced-tab";
2
2
  import { ChatStatus } from "@web-utils/features";
3
+ import { FileReference } from "../../types/file-upload";
3
4
  type MessageActionTypes = "redirectToAuthSpaJoinTenant";
4
5
  export interface MessageAction {
5
6
  text: string;
6
7
  type: "primary" | "danger";
7
8
  actionType: MessageActionTypes;
8
9
  }
10
+ export interface FileAttachment {
11
+ fileName: string;
12
+ fileType: string;
13
+ fileSize: number;
14
+ uploadUrl?: string;
15
+ fileId?: string;
16
+ }
9
17
  export interface Message {
10
18
  id: string;
11
19
  role: "user" | "assistant" | "system";
@@ -16,9 +24,11 @@ export interface Message {
16
24
  contentType?: string;
17
25
  visible: boolean;
18
26
  actions?: MessageAction[];
27
+ fileAttachments?: FileAttachment[];
19
28
  }
20
29
  export type SendMessageOptions = {
21
30
  visible?: boolean;
31
+ fileReferences?: FileReference[];
22
32
  } | undefined;
23
33
  export interface UseChatProps {
24
34
  wsUrl: string;
@@ -36,7 +46,7 @@ export interface UseChatProps {
36
46
  hapticFeedback?: {
37
47
  impactAsync: (style: any) => Promise<void>;
38
48
  };
39
- redirectToAuthSpa: () => void;
49
+ redirectToAuthSpa: (redirectTo?: string, platformKey?: string, logout?: boolean) => void;
40
50
  store?: {
41
51
  sendMessage?: (text: string) => Promise<void>;
42
52
  };
@@ -3,3 +3,5 @@ export * from "./providers";
3
3
  export * from "./utils";
4
4
  export * from "./types";
5
5
  export * from "./features";
6
+ export * from "./constants/chat";
7
+ export * from "./services";
@@ -1,12 +1,14 @@
1
- export { useGetChatDetails } from './hooks/chat/use-get-chat-details';
2
- export { useAdvancedChat } from './hooks/chat/use-advanced-chat';
3
- export { useTimeTracker } from './features/tracking/use-time-tracker';
4
- export { useMentorSettings } from './hooks/use-mentor-settings';
5
- export type { ChatMode } from './types';
6
- export { advancedTabsProperties, ANONYMOUS_USERNAME } from './utils';
7
- export { isAlphaNumeric32 } from './utils';
8
- export { getTimeAgo } from './utils';
9
- export { getInitials } from './utils';
10
- export { chatActions, selectSessionId } from './features/chat/slice';
11
- export { AuthProvider, TenantProvider, MentorProvider } from './providers';
12
- export { useSearchParams, useParams, useRouter, usePathname } from 'next/navigation';
1
+ export { useGetChatDetails } from "./hooks/chat/use-get-chat-details";
2
+ export { useAdvancedChat } from "./hooks/chat/use-advanced-chat";
3
+ export { useTimeTracker } from "./features/tracking/use-time-tracker";
4
+ export { useMentorSettings } from "./hooks/use-mentor-settings";
5
+ export type { ChatMode } from "./types";
6
+ export { advancedTabsProperties, ANONYMOUS_USERNAME } from "./utils";
7
+ export { isAlphaNumeric32 } from "./utils";
8
+ export { getTimeAgo } from "./utils";
9
+ export { getInitials } from "./utils";
10
+ export { isInIframe, sendMessageToParentWebsite, deleteCookie, getDomainParts, deleteCookieOnAllDomains, getParentDomain, setCookieForAuth, clearCookies, isLoggedIn, getPlatformKey, redirectToAuthSpa, getAuthSpaJoinUrl, redirectToAuthSpaJoinTenant, handleLogout, } from "./utils/auth";
11
+ export type { RedirectToAuthSpaOptions, HandleLogoutOptions, } from "./utils/auth";
12
+ export { chatActions, selectSessionId } from "./features/chat/slice";
13
+ export { AuthProvider, TenantProvider, MentorProvider } from "./providers";
14
+ export { useSearchParams, useParams, useRouter, usePathname, } from "next/navigation";
@@ -40,6 +40,8 @@
40
40
  * - Polls for cookie changes every 2 seconds
41
41
  * - Refreshes the page when cross-SPA changes are detected
42
42
  * - Listens for storage events to update cookies when localStorage changes
43
+ * - Monitors logout timestamp cookie to trigger cross-SPA logout
44
+ * - Automatically logs out when another SPA initiates logout
43
45
  *
44
46
  * For React Native:
45
47
  * - Relies on AsyncStorage only (handled by StorageService)
@@ -54,6 +56,12 @@ import { StorageService } from "@iblai/data-layer";
54
56
  * On React Native, this is a no-op
55
57
  */
56
58
  export declare function syncAuthToCookies(storageService: StorageService): Promise<void>;
59
+ /**
60
+ * Clear current tenant cookie only (web only)
61
+ * Should be called before tenant switching
62
+ * On React Native, this is a no-op
63
+ */
64
+ export declare function clearCurrentTenantCookie(): void;
57
65
  /**
58
66
  * Clear all authentication cookies (web only)
59
67
  * Should be called on logout
@@ -96,7 +104,7 @@ type Props = {
96
104
  middleware?: Map<string | RegExp, () => Promise<boolean>>;
97
105
  onAuthSuccess?: () => void;
98
106
  onAuthFailure?: (reason: string) => void;
99
- redirectToAuthSpa: (redirectTo?: string, platformKey?: string, logout?: boolean) => void;
107
+ redirectToAuthSpa: (redirectTo?: string, platformKey?: string, logout?: boolean, saveRedirect?: boolean) => void;
100
108
  hasNonExpiredAuthToken: () => boolean;
101
109
  username: string;
102
110
  pathname: string;
@@ -53,6 +53,7 @@ type Props = {
53
53
  saveUserTokens?: (tokens: TokenResponse) => void;
54
54
  saveTenant?: (tenant: string) => void;
55
55
  onAutoJoinUserToTenant?: (platformName: string) => void;
56
+ redirectToAuthSpa?: (redirectTo?: string, platformKey?: string, logout?: boolean, saveRedirect?: boolean) => void;
56
57
  };
57
58
  /**
58
59
  * TenantProvider Component
@@ -64,5 +65,5 @@ type Props = {
64
65
  * 4. Handles tenant-specific domain redirects
65
66
  * 5. Maintains tenant access state
66
67
  */
67
- export declare function TenantProvider({ children, fallback, onAuthSuccess, onAuthFailure, currentTenant, requestedTenant, saveCurrentTenant, saveUserTenants, handleTenantSwitch, saveVisitingTenant, removeVisitingTenant, saveUserTokens, saveTenant, onAutoJoinUserToTenant, }: Props): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element | null | undefined;
68
+ export declare function TenantProvider({ children, fallback, onAuthSuccess, onAuthFailure, currentTenant, requestedTenant, saveCurrentTenant, saveUserTenants, handleTenantSwitch, saveVisitingTenant, removeVisitingTenant, saveUserTokens, saveTenant, onAutoJoinUserToTenant, redirectToAuthSpa, }: Props): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element | null | undefined;
68
69
  export {};
@@ -0,0 +1,60 @@
1
+ import type { FileInfo, FileReference, UploadProgressCallback } from "../types/file-upload";
2
+ import type { FileUploadURLResponse } from "@iblai/data-layer";
3
+ /**
4
+ * Extract file information from File object
5
+ */
6
+ export declare function getFileInfo(file: File): FileInfo;
7
+ /**
8
+ * Request presigned S3 URL from backend
9
+ * Note: This function should be called via the RTK Query mutation hook
10
+ * This is a helper to show the data flow
11
+ */
12
+ export declare function requestPresignedUrl(sessionId: string, file: File, getUploadUrlFn: (params: {
13
+ org: string;
14
+ userId: string;
15
+ requestBody: {
16
+ session_id: string;
17
+ file_name: string;
18
+ content_type: string;
19
+ file_size: number;
20
+ };
21
+ }) => Promise<FileUploadURLResponse>, org: string, userId: string): Promise<FileUploadURLResponse>;
22
+ /**
23
+ * Upload file directly to S3 using presigned URL
24
+ * Uses axios for cross-platform support (web + React Native)
25
+ */
26
+ export declare function uploadToS3(presignedUrl: string, file: File, contentType: string, onProgress?: UploadProgressCallback): Promise<void>;
27
+ /**
28
+ * Complete file upload flow:
29
+ * 1. Request presigned URL
30
+ * 2. Upload to S3
31
+ * 3. Return file reference
32
+ */
33
+ export declare function createFileReference(file: File, sessionId: string, getUploadUrlFn: (params: {
34
+ org: string;
35
+ userId: string;
36
+ requestBody: {
37
+ session_id: string;
38
+ file_name: string;
39
+ content_type: string;
40
+ file_size: number;
41
+ };
42
+ }) => Promise<FileUploadURLResponse>, org: string, userId: string, onProgress?: UploadProgressCallback): Promise<FileReference>;
43
+ /**
44
+ * Upload multiple files and return their references
45
+ */
46
+ export declare function createMultipleFileReferences(files: File[], sessionId: string, getUploadUrlFn: (params: {
47
+ org: string;
48
+ userId: string;
49
+ requestBody: {
50
+ session_id: string;
51
+ file_name: string;
52
+ content_type: string;
53
+ file_size: number;
54
+ };
55
+ }) => Promise<FileUploadURLResponse>, org: string, userId: string, onFileProgress?: (fileIndex: number, progress: number) => void): Promise<FileReference[]>;
56
+ /**
57
+ * Validate file before upload
58
+ * Returns error message if invalid, null if valid
59
+ */
60
+ export declare function validateFile(file: File, maxSizeBytes?: number, allowedTypes?: string[]): string | null;
@@ -0,0 +1 @@
1
+ export * from "./file-upload";
@@ -0,0 +1,62 @@
1
+ /**
2
+ * File reference sent via WebSocket to backend
3
+ * Backend uses this to retrieve file from S3
4
+ */
5
+ export interface FileReference {
6
+ /** Unique identifier for the ChatFile record */
7
+ file_id: string;
8
+ /** S3 object key for the uploaded file */
9
+ file_key: string;
10
+ /** Original filename */
11
+ file_name: string;
12
+ /** MIME type of the file */
13
+ content_type: string;
14
+ /** File size in bytes */
15
+ file_size: number;
16
+ /** Presigned URL for displaying the file (optional, for UI) */
17
+ upload_url?: string;
18
+ }
19
+ /**
20
+ * File upload state for UI tracking
21
+ */
22
+ export interface FileUploadState {
23
+ /** Original File object */
24
+ file: File;
25
+ /** Upload/processing status */
26
+ status: "pending" | "uploading" | "processing" | "success" | "error";
27
+ /** Upload progress (0-100) */
28
+ progress: number;
29
+ /** File reference after successful upload */
30
+ fileReference?: FileReference;
31
+ /** Error message if upload failed */
32
+ error?: string;
33
+ }
34
+ /**
35
+ * File processing event from WebSocket
36
+ */
37
+ export type FileProcessingEvent = {
38
+ type: "file_processing_progress";
39
+ file_name: string;
40
+ progress: string;
41
+ } | {
42
+ type: "file_processing_success";
43
+ file_name: string;
44
+ file_url: string;
45
+ } | {
46
+ type: "file_error";
47
+ file_name?: string;
48
+ error: string;
49
+ developer_error?: string;
50
+ };
51
+ /**
52
+ * Upload progress callback
53
+ */
54
+ export type UploadProgressCallback = (progress: number) => void;
55
+ /**
56
+ * File info extracted from File object
57
+ */
58
+ export interface FileInfo {
59
+ fileName: string;
60
+ contentType: string;
61
+ fileSize: number;
62
+ }
@@ -62,3 +62,4 @@ export interface Tenant {
62
62
  }
63
63
  export * from "./chat";
64
64
  export * from "./subscription";
65
+ export * from "./file-upload";
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Authentication and Authorization Utilities
3
+ *
4
+ * This module provides utility functions for handling authentication flows,
5
+ * including redirects to auth SPA, cookie management, and session handling.
6
+ */
7
+ /**
8
+ * Check if the current window is inside an iframe
9
+ * @returns {boolean} True if running in an iframe, false otherwise
10
+ */
11
+ export declare function isInIframe(): boolean;
12
+ /**
13
+ * Send a message to the parent website (when in iframe)
14
+ * @param payload - The data to send to parent window
15
+ */
16
+ export declare function sendMessageToParentWebsite(payload: unknown): void;
17
+ /**
18
+ * Delete a cookie with specific name, path, and domain
19
+ * @param name - Cookie name
20
+ * @param path - Cookie path
21
+ * @param domain - Cookie domain
22
+ */
23
+ export declare function deleteCookie(name: string, path: string, domain: string): void;
24
+ /**
25
+ * Get all possible domain parts for cookie deletion
26
+ * @param domain - The domain to split
27
+ * @returns Array of domain parts
28
+ * @example
29
+ * getDomainParts('app.example.com') // returns ['app.example.com', 'example.com', 'com']
30
+ */
31
+ export declare function getDomainParts(domain: string): string[];
32
+ /**
33
+ * Delete a cookie across all possible domain variations
34
+ * @param name - Cookie name to delete
35
+ * @param childDomain - The current domain
36
+ */
37
+ export declare function deleteCookieOnAllDomains(name: string, childDomain: string): void;
38
+ /**
39
+ * Get the parent domain from a given domain
40
+ * @param domain - The domain to process
41
+ * @returns The parent domain (e.g., 'app.example.com' → '.example.com')
42
+ */
43
+ export declare function getParentDomain(domain?: string): string;
44
+ /**
45
+ * Set a cookie for authentication with cross-domain support
46
+ * @param name - Cookie name
47
+ * @param value - Cookie value
48
+ * @param days - Number of days until expiration (default: 365)
49
+ */
50
+ export declare function setCookieForAuth(name: string, value: string, days?: number): void;
51
+ /**
52
+ * Clear all cookies for the current domain
53
+ */
54
+ export declare function clearCookies(): void;
55
+ /**
56
+ * Check if user is currently logged in
57
+ * @param tokenKey - The localStorage key for the auth token (default: 'axd_token')
58
+ * @returns True if logged in, false otherwise
59
+ */
60
+ export declare function isLoggedIn(tokenKey?: string): boolean;
61
+ /**
62
+ * Extract platform/tenant key from URL
63
+ * @param url - The URL to parse
64
+ * @param pattern - RegExp pattern to match platform key (default matches /platform/[key]/...)
65
+ * @returns The platform key or null if not found
66
+ */
67
+ export declare function getPlatformKey(url: string, pattern?: RegExp): string | null;
68
+ export interface RedirectToAuthSpaOptions {
69
+ /** URL to redirect to after auth (defaults to current path + search) */
70
+ redirectTo?: string;
71
+ /** Platform/tenant key */
72
+ platformKey?: string;
73
+ /** Whether this is a logout action */
74
+ logout?: boolean;
75
+ /** Whether to save redirect path to localStorage (default: true) */
76
+ saveRedirect?: boolean;
77
+ /** Auth SPA base URL */
78
+ authUrl: string;
79
+ /** Current app/platform identifier (e.g., 'mentor', 'skills') */
80
+ appName: string;
81
+ /** Query param names */
82
+ queryParams?: {
83
+ app?: string;
84
+ redirectTo?: string;
85
+ tenant?: string;
86
+ };
87
+ /** localStorage key for saving redirect path */
88
+ redirectPathStorageKey?: string;
89
+ /** Cookie names for cross-SPA sync */
90
+ cookieNames?: {
91
+ currentTenant?: string;
92
+ userData?: string;
93
+ tenant?: string;
94
+ logoutTimestamp?: string;
95
+ };
96
+ }
97
+ /**
98
+ * Redirect to authentication SPA for login/logout
99
+ *
100
+ * This function handles the complete authentication flow:
101
+ * - Clears localStorage and cookies on logout
102
+ * - Saves redirect path for post-auth return
103
+ * - Handles iframe scenarios
104
+ * - Syncs logout across multiple SPAs via cookies
105
+ *
106
+ * @param options - Configuration options for the redirect
107
+ *
108
+ * @example
109
+ * ```tsx
110
+ * // Basic usage
111
+ * redirectToAuthSpa({
112
+ * authUrl: 'https://auth.example.com',
113
+ * appName: 'mentor',
114
+ * });
115
+ *
116
+ * // With logout
117
+ * redirectToAuthSpa({
118
+ * authUrl: 'https://auth.example.com',
119
+ * appName: 'mentor',
120
+ * logout: true,
121
+ * platformKey: 'my-tenant',
122
+ * });
123
+ *
124
+ * // With custom redirect
125
+ * redirectToAuthSpa({
126
+ * authUrl: 'https://auth.example.com',
127
+ * appName: 'mentor',
128
+ * redirectTo: '/dashboard',
129
+ * platformKey: 'my-tenant',
130
+ * });
131
+ * ```
132
+ */
133
+ export declare function redirectToAuthSpa(options: RedirectToAuthSpaOptions): Promise<void>;
134
+ /**
135
+ * Get the URL for joining a tenant (sign up flow)
136
+ * @param authUrl - Auth SPA base URL
137
+ * @param tenantKey - Tenant to join
138
+ * @param redirectUrl - URL to redirect to after joining (defaults to current URL)
139
+ * @returns The join URL
140
+ */
141
+ export declare function getAuthSpaJoinUrl(authUrl: string, tenantKey?: string, redirectUrl?: string): string;
142
+ /**
143
+ * Redirect to auth SPA's join/signup page for a specific tenant
144
+ * @param authUrl - Auth SPA base URL
145
+ * @param tenantKey - Tenant to join
146
+ * @param redirectUrl - URL to redirect to after joining (defaults to current URL)
147
+ */
148
+ export declare function redirectToAuthSpaJoinTenant(authUrl: string, tenantKey?: string, redirectUrl?: string): void;
149
+ export interface HandleLogoutOptions {
150
+ /** URL to redirect to after logout (defaults to current origin) */
151
+ redirectUrl?: string;
152
+ /** Auth SPA base URL */
153
+ authUrl: string;
154
+ /** localStorage key for tenant */
155
+ tenantStorageKey?: string;
156
+ /** Cookie name for logout timestamp */
157
+ logoutTimestampCookie?: string;
158
+ /** Callback to execute before logout */
159
+ callback?: () => void;
160
+ }
161
+ /**
162
+ * Handle user logout
163
+ *
164
+ * This function:
165
+ * - Clears localStorage (preserving tenant)
166
+ * - Sets logout timestamp cookie for cross-SPA sync
167
+ * - Clears all cookies
168
+ * - Redirects to auth SPA logout endpoint
169
+ *
170
+ * @param options - Logout configuration options
171
+ *
172
+ * @example
173
+ * ```tsx
174
+ * handleLogout({
175
+ * authUrl: 'https://auth.example.com',
176
+ * redirectUrl: 'https://app.example.com',
177
+ * });
178
+ * ```
179
+ */
180
+ export declare function handleLogout(options: HandleLogoutOptions): void;
@@ -1,3 +1,4 @@
1
1
  export * from "./data/advanced-tab";
2
2
  export * from "./constants";
3
3
  export * from "./helpers";
4
+ export * from "./auth";