@lilaquadrat/chat 0.1.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.
- package/dist/studio-chat-module.js +1 -0
- package/dist/studio-chat-module.umd.cjs +1 -0
- package/dist/types/src/bot/botClient.d.ts +40 -0
- package/dist/types/src/bot/botManager.d.ts +3 -0
- package/dist/types/src/composables/useWebSocket.d.ts +11 -0
- package/dist/types/src/config/auth.d.ts +18 -0
- package/dist/types/src/config/bootstrap.d.ts +55 -0
- package/dist/types/src/config/users.d.ts +27 -0
- package/dist/types/src/helpers/date.d.ts +7 -0
- package/dist/types/src/helpers/handleMessages.d.ts +1 -0
- package/dist/types/src/helpers/loadComponents.d.ts +10 -0
- package/dist/types/src/helpers/participants.d.ts +21 -0
- package/dist/types/src/libs/StudioSDK.d.ts +108 -0
- package/dist/types/src/libs/resize.d.ts +52 -0
- package/dist/types/src/libs/websocketManager.d.ts +41 -0
- package/dist/types/src/locales/de.d.ts +31 -0
- package/dist/types/src/locales/en.d.ts +31 -0
- package/dist/types/src/main.d.ts +1 -0
- package/dist/types/src/mixins/groupMessages.d.ts +1 -0
- package/dist/types/src/mixins/hardCopy.d.ts +2 -0
- package/dist/types/src/mixins/logger.d.ts +8 -0
- package/dist/types/src/mixins/traceable.d.ts +11 -0
- package/dist/types/src/plugins/i18n.d.ts +40 -0
- package/dist/types/src/stores/bots.store.d.ts +69 -0
- package/dist/types/src/stores/calls.store.d.ts +14 -0
- package/dist/types/src/stores/contacts.store.d.ts +87 -0
- package/dist/types/src/stores/conversations.store.d.ts +129 -0
- package/dist/types/src/stores/main.store.d.ts +65 -0
- package/dist/types/src/stores/user.store.d.ts +8 -0
- package/dist/types/src/stores/usersCache.store.d.ts +31 -0
- package/dist/types/src/web-component.d.ts +9 -0
- package/dist/types/tsconfig.build.tsbuildinfo +1 -0
- package/dist/wc/lilaquadrat-studio-chat.js +17622 -0
- package/dist/wc/lilaquadrat-studio-chat.umd.cjs +43 -0
- package/package.json +77 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(n){"function"==typeof define&&define.amd?define(n):n()}(function(){});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** prefix on bot-sent replies so auto-reply bots don't ping-pong off each other */
|
|
2
|
+
export declare const BOT_PREFIX = "\uD83E\uDD16";
|
|
3
|
+
export type BotConnectionStatus = 'connecting' | 'connected' | 'disconnected';
|
|
4
|
+
export interface BotClientOptions {
|
|
5
|
+
userId: number;
|
|
6
|
+
url?: string;
|
|
7
|
+
apiUrl?: string;
|
|
8
|
+
getAutoReply?: () => boolean;
|
|
9
|
+
onStatus?: (_status: BotConnectionStatus) => void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* One independent websocket connection acting as a single user. Authenticates as its
|
|
13
|
+
* userId, learns the conversations it belongs to, auto-replies to others' messages, and
|
|
14
|
+
* proactively sends random messages on an interval — so it behaves like a live user for
|
|
15
|
+
* debugging multi-user flows.
|
|
16
|
+
*/
|
|
17
|
+
export declare class BotClient {
|
|
18
|
+
private socket;
|
|
19
|
+
private readonly userId;
|
|
20
|
+
private readonly url;
|
|
21
|
+
private readonly apiUrl;
|
|
22
|
+
private readonly getAutoReply;
|
|
23
|
+
private readonly onStatus?;
|
|
24
|
+
private conversations;
|
|
25
|
+
private chatterTimer;
|
|
26
|
+
private readonly replyTimers;
|
|
27
|
+
private readonly pace;
|
|
28
|
+
constructor(options: BotClientOptions);
|
|
29
|
+
connect(): void;
|
|
30
|
+
disconnect(): void;
|
|
31
|
+
sendMessage(conversation: string, message: string): void;
|
|
32
|
+
private handleClose;
|
|
33
|
+
/** fetch the conversations this bot is a participant of (raw fetch — SDK GET cache is shared across users) */
|
|
34
|
+
private loadConversations;
|
|
35
|
+
private scheduleChatter;
|
|
36
|
+
private clearTimers;
|
|
37
|
+
private sendRandom;
|
|
38
|
+
private send;
|
|
39
|
+
private handle;
|
|
40
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type UseWebSocketOptions } from '@/libs/websocketManager';
|
|
2
|
+
export declare function useWebSocket(): {
|
|
3
|
+
connect: (options: UseWebSocketOptions) => void;
|
|
4
|
+
disconnect: () => void;
|
|
5
|
+
reconnect: () => void;
|
|
6
|
+
conversationStart: (message: string, participants: string[], name: string | undefined, id: string, operationMode?: "chat" | "support") => boolean;
|
|
7
|
+
conversationLastRead: (conversation: string, lastReadId: number) => boolean;
|
|
8
|
+
messageAdd: (message: string, conversation: string) => boolean;
|
|
9
|
+
authenticate: (token: string) => boolean;
|
|
10
|
+
conversationTyping: (conversation: string, typing: boolean) => boolean;
|
|
11
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pluggable auth-token source.
|
|
3
|
+
*
|
|
4
|
+
* The chat module never owns the auth session. The host application provides a
|
|
5
|
+
* function that, whenever called, returns a currently-valid token (Auth0 JWT).
|
|
6
|
+
* Registered once via `createChatModule({ getToken })` (see main.ts) or
|
|
7
|
+
* `setGetToken()` directly. The module derives identity from the token's `sub`
|
|
8
|
+
* and sends it as the WS `authenticate` token + HTTP Bearer.
|
|
9
|
+
*
|
|
10
|
+
* The function is called on every (re)connect and may be async, so the host can
|
|
11
|
+
* refresh/rotate the token transparently — it must always resolve a proper token.
|
|
12
|
+
*/
|
|
13
|
+
export type GetTokenFn = () => string | Promise<string>;
|
|
14
|
+
/** register the host implementation. last call wins. */
|
|
15
|
+
export declare function setGetToken(fn: GetTokenFn): void;
|
|
16
|
+
export declare function hasGetToken(): boolean;
|
|
17
|
+
/** resolve a fresh token through the registered implementation. returns undefined if none was set. */
|
|
18
|
+
export declare function resolveToken(): Promise<string | undefined>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { App } from 'vue';
|
|
2
|
+
import type { Pinia } from 'pinia';
|
|
3
|
+
import { type Feature } from '@/stores/main.store';
|
|
4
|
+
import { type GetUsersFn } from '@/config/users';
|
|
5
|
+
import { type GetTokenFn } from '@/config/auth';
|
|
6
|
+
import type { ParticipantUser } from '@/helpers/participants';
|
|
7
|
+
export interface ChatModuleConfig {
|
|
8
|
+
/** how the host resolves users. Required for default mode; unused in support mode. */
|
|
9
|
+
getUsers?: GetUsersFn;
|
|
10
|
+
/**
|
|
11
|
+
* enabled features. Defaults to ['chat']. The two are orthogonal:
|
|
12
|
+
* ['chat'] = normal user↔user chats only
|
|
13
|
+
* ['support'] = support-only widget
|
|
14
|
+
* ['chat','support'] = normal chats + an on-demand support chat alongside them
|
|
15
|
+
*/
|
|
16
|
+
features?: Feature[];
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated legacy single-axis mode; use `features` instead.
|
|
19
|
+
* 'chat'|'default' → ['chat'], 'support' → ['support'], 'both' → ['chat','support'].
|
|
20
|
+
*/
|
|
21
|
+
mode?: 'chat' | 'support' | 'both' | 'default';
|
|
22
|
+
/** the current user id. Falls back to the ?user= query param (dev) when omitted. */
|
|
23
|
+
userId?: string;
|
|
24
|
+
/**
|
|
25
|
+
* the current user's own profile (prename/lastname/...). The backend enriches *other*
|
|
26
|
+
* participants but not the requesting user, so the host passes its own data here to
|
|
27
|
+
* resolve the current user's name. `id` defaults to `userId` when omitted.
|
|
28
|
+
*/
|
|
29
|
+
user?: ParticipantUser;
|
|
30
|
+
/** support mode: the support recipient(s) the customer talks to. */
|
|
31
|
+
support?: {
|
|
32
|
+
participants: string[];
|
|
33
|
+
};
|
|
34
|
+
/** websocket endpoint. Defaults to ws://localhost:3001 (dev). */
|
|
35
|
+
wsUrl?: string;
|
|
36
|
+
/** API endpoint. Defaults to http://localhost:3000 (dev). */
|
|
37
|
+
apiUrl?: string;
|
|
38
|
+
/** media endpoint. Defaults to http://localhost:3000 (dev). */
|
|
39
|
+
mediaUrl?: string;
|
|
40
|
+
/** the host's auth token (Auth0 JWT). Identity is derived from its `sub`; sent as Bearer + WS auth. */
|
|
41
|
+
token?: string;
|
|
42
|
+
/**
|
|
43
|
+
* host-provided token resolver. Called on every (re)connect; may be async and must always
|
|
44
|
+
* return a currently-valid token. Preferred over the static `token` — identity comes from its `sub`.
|
|
45
|
+
*/
|
|
46
|
+
getToken?: GetTokenFn;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Apply host configuration to the stores / providers. Shared by both bootstrap paths
|
|
50
|
+
* (createChatModule and the <lilaquadrat-studio-chat> custom element).
|
|
51
|
+
* Pass the pinia instance when calling outside an active-pinia context.
|
|
52
|
+
*/
|
|
53
|
+
export declare function applyConfig(config: ChatModuleConfig, pinia?: Pinia): void;
|
|
54
|
+
/** register the module's global components on a Vue app (or custom-element app). */
|
|
55
|
+
export declare function registerComponents(app: App): void;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pluggable user source.
|
|
3
|
+
*
|
|
4
|
+
* The chat module never hardcodes its users. The host application provides the
|
|
5
|
+
* implementation once, via `createChatModule({ getUsers })` (see main.ts) or by
|
|
6
|
+
* calling `setGetUsers()` directly before the contacts UI is used. This lets every
|
|
7
|
+
* host plug in its own backend (REST, Auth0, in-memory, ...).
|
|
8
|
+
*/
|
|
9
|
+
export interface ChatUser {
|
|
10
|
+
id: string;
|
|
11
|
+
prename?: string;
|
|
12
|
+
lastname?: string;
|
|
13
|
+
name?: string;
|
|
14
|
+
status?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface GetUsersOptions {
|
|
17
|
+
/** restrict to specific user ids (e.g. to resolve participant names) */
|
|
18
|
+
ids?: string[];
|
|
19
|
+
/** free-text search/filter */
|
|
20
|
+
query?: string;
|
|
21
|
+
}
|
|
22
|
+
export type GetUsersFn = (_options?: GetUsersOptions) => Promise<ChatUser[]> | ChatUser[];
|
|
23
|
+
/** register the host implementation. last call wins. */
|
|
24
|
+
export declare function setGetUsers(fn: GetUsersFn): void;
|
|
25
|
+
export declare function hasGetUsers(): boolean;
|
|
26
|
+
/** resolve users through the registered implementation. returns [] (with a warning) if none was set. */
|
|
27
|
+
export declare function getUsers(options?: GetUsersOptions): Promise<ChatUser[]>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import dayjs from 'dayjs';
|
|
2
|
+
import 'dayjs/locale/de';
|
|
3
|
+
import 'dayjs/locale/en';
|
|
4
|
+
declare function date(date: string | Date | dayjs.Dayjs, format?: string): string;
|
|
5
|
+
declare function time(date: string | Date | dayjs.Dayjs, format?: string): string;
|
|
6
|
+
declare function dateRelative(date: string | Date | dayjs.Dayjs): string;
|
|
7
|
+
export { date, time, dateRelative, dayjs };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function handleMessages(message: Record<string, any>): void;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type App, type Component, type AsyncComponentLoader } from 'vue';
|
|
2
|
+
declare function loadViaDeclaration(components: {
|
|
3
|
+
name: string;
|
|
4
|
+
component: AsyncComponentLoader<Component>;
|
|
5
|
+
}[], namespace: string | undefined, type: 'module' | 'partial', app: App<Element>): void;
|
|
6
|
+
declare function loadViaDeclarationSync(components: {
|
|
7
|
+
name: string;
|
|
8
|
+
component: Component;
|
|
9
|
+
}[], namespace: string | undefined, type: 'module' | 'partial', app: App<Element>): void;
|
|
10
|
+
export { loadViaDeclaration, loadViaDeclarationSync, };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Participants arrive in two shapes: backend-enriched objects ({ id, prename, ... })
|
|
3
|
+
* on real conversations, and bare id strings on local drafts (and on the write path
|
|
4
|
+
* we send back to the server). These helpers normalize both so comparisons, keys and
|
|
5
|
+
* display work regardless of shape.
|
|
6
|
+
*/
|
|
7
|
+
export interface ParticipantUser {
|
|
8
|
+
id: string;
|
|
9
|
+
prename?: string;
|
|
10
|
+
lastname?: string;
|
|
11
|
+
email?: string;
|
|
12
|
+
/** host-provided contact name (see @/config/users ChatUser) */
|
|
13
|
+
name?: string;
|
|
14
|
+
}
|
|
15
|
+
export type Participant = string | ParticipantUser;
|
|
16
|
+
/** the user id of a participant, whether it's a bare id or an object */
|
|
17
|
+
export declare function participantId(participant: Participant): string;
|
|
18
|
+
/** map a participant list to its ids (e.g. before sending to the backend) */
|
|
19
|
+
export declare function participantIds(participants?: Participant[]): string[];
|
|
20
|
+
/** human-readable name: prename+lastname, else host name, else the raw id */
|
|
21
|
+
export declare function participantName(participant: Participant): string;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { type AxiosResponse, type AxiosRequestConfig } from 'axios';
|
|
2
|
+
type HttpStatusCode = number;
|
|
3
|
+
export type SDKResponse<T> = {
|
|
4
|
+
data: T;
|
|
5
|
+
status: HttpStatusCode;
|
|
6
|
+
cacheLifetime?: number;
|
|
7
|
+
cacheTime?: number;
|
|
8
|
+
isCache?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export type SDKCache = {
|
|
11
|
+
group?: string;
|
|
12
|
+
action?: string;
|
|
13
|
+
id?: string;
|
|
14
|
+
cacheLifetime?: number;
|
|
15
|
+
cacheTime?: number;
|
|
16
|
+
};
|
|
17
|
+
export type SDKCallOptions = {
|
|
18
|
+
/**
|
|
19
|
+
* ignore the cache and always execute the call
|
|
20
|
+
*/
|
|
21
|
+
bypassCache?: boolean;
|
|
22
|
+
group?: string;
|
|
23
|
+
action?: string;
|
|
24
|
+
/**
|
|
25
|
+
* if a id is given, use it as key for atomic cache flushing
|
|
26
|
+
*
|
|
27
|
+
* e.g. ``flushId(id)``
|
|
28
|
+
*
|
|
29
|
+
* instead of the whole action category
|
|
30
|
+
*
|
|
31
|
+
* e.g. ``flushCache(group, action)``
|
|
32
|
+
*
|
|
33
|
+
*/
|
|
34
|
+
id?: string;
|
|
35
|
+
/**
|
|
36
|
+
* in milliseconds
|
|
37
|
+
*/
|
|
38
|
+
cacheLifetime?: number;
|
|
39
|
+
};
|
|
40
|
+
export default class StudioSDK {
|
|
41
|
+
readonly endpoints: {
|
|
42
|
+
live: {
|
|
43
|
+
api: string;
|
|
44
|
+
media: string;
|
|
45
|
+
};
|
|
46
|
+
next: {
|
|
47
|
+
api: string;
|
|
48
|
+
media: string;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
customEndpoints: {
|
|
52
|
+
api: string;
|
|
53
|
+
media: string;
|
|
54
|
+
};
|
|
55
|
+
authToken: string;
|
|
56
|
+
mode: 'live' | 'next' | 'custom';
|
|
57
|
+
company: string;
|
|
58
|
+
project: string;
|
|
59
|
+
app: string;
|
|
60
|
+
universalModel: string;
|
|
61
|
+
options: {
|
|
62
|
+
company?: string;
|
|
63
|
+
project?: string;
|
|
64
|
+
authToken?: string;
|
|
65
|
+
mode?: StudioSDK['mode'];
|
|
66
|
+
customEndpoints?: {
|
|
67
|
+
api: string;
|
|
68
|
+
media: string;
|
|
69
|
+
};
|
|
70
|
+
universalModel?: string;
|
|
71
|
+
};
|
|
72
|
+
constructor(app: string, options: StudioSDK['options']);
|
|
73
|
+
private getUrl;
|
|
74
|
+
private getHeaders;
|
|
75
|
+
static getCacheKeyMock(url: string): string;
|
|
76
|
+
static getCacheKey(url: string): string;
|
|
77
|
+
static getCache(): Record<string, SDKResponse<any> & SDKCache>;
|
|
78
|
+
static handleCall<T, D = any>(call: AxiosRequestConfig<D>, options?: SDKCallOptions): Promise<SDKResponse<T>>;
|
|
79
|
+
static cache<T>(url: string, response?: AxiosResponse<T>, options?: SDKCallOptions): SDKResponse<any> & SDKCache;
|
|
80
|
+
static flushCache(group?: string, action?: string): void;
|
|
81
|
+
static flushId(id: string): void;
|
|
82
|
+
conversations: {
|
|
83
|
+
list: () => Promise<SDKResponse<any>>;
|
|
84
|
+
activate: () => Promise<SDKResponse<any>>;
|
|
85
|
+
create: (data: {
|
|
86
|
+
participants: string[];
|
|
87
|
+
}) => Promise<SDKResponse<any>>;
|
|
88
|
+
rename: (conversationId: string, name: string) => Promise<SDKResponse<any>>;
|
|
89
|
+
participants: (conversationId: string, add: string[], remove: string[]) => Promise<SDKResponse<any>>;
|
|
90
|
+
leave: (conversationId: string) => Promise<SDKResponse<any>>;
|
|
91
|
+
listParticipants: (conversationId: string) => Promise<SDKResponse<any>>;
|
|
92
|
+
rights: (conversationId: string, user: string, rights: string[]) => Promise<SDKResponse<any>>;
|
|
93
|
+
block: (conversationId: string, user: string, block: boolean) => Promise<SDKResponse<any>>;
|
|
94
|
+
};
|
|
95
|
+
contacts: {
|
|
96
|
+
list: (search?: string) => Promise<SDKResponse<any>>;
|
|
97
|
+
single: (contactId: string) => Promise<SDKResponse<any>>;
|
|
98
|
+
block: (contactId: string) => Promise<SDKResponse<any>>;
|
|
99
|
+
unblock: (contactId: string) => Promise<SDKResponse<any>>;
|
|
100
|
+
};
|
|
101
|
+
messages: {
|
|
102
|
+
list: (conversation: string, beforeId?: number) => Promise<SDKResponse<any>>;
|
|
103
|
+
};
|
|
104
|
+
health: {
|
|
105
|
+
health: () => Promise<SDKResponse<void>>;
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
declare class Resize {
|
|
2
|
+
timeout: ReturnType<typeof setTimeout> | undefined;
|
|
3
|
+
debounceTime: number;
|
|
4
|
+
resizedEvent: Event;
|
|
5
|
+
mediaEvent: Event;
|
|
6
|
+
media: import("vue").Ref<string, string>;
|
|
7
|
+
resized: import("vue").Ref<number, number>;
|
|
8
|
+
/** timestamp bumped only when the tracked width actually changed */
|
|
9
|
+
widthChanged: import("vue").Ref<number, number>;
|
|
10
|
+
realHeight: import("vue").Ref<number, number>;
|
|
11
|
+
realWidth: import("vue").Ref<number, number>;
|
|
12
|
+
/**
|
|
13
|
+
* if true we fire an inital resized event to indicate that resizing has started without waiting for the debounce
|
|
14
|
+
*/
|
|
15
|
+
triggerStart: import("vue").Ref<boolean, boolean>;
|
|
16
|
+
private installed;
|
|
17
|
+
private mediaQueries;
|
|
18
|
+
/** element realWidth is measured against; null = fall back to window.innerWidth */
|
|
19
|
+
private widthTarget;
|
|
20
|
+
private resizeObserver;
|
|
21
|
+
/** bound handler kept so removeEventListener can detach it */
|
|
22
|
+
private onResize;
|
|
23
|
+
private get safeWindow();
|
|
24
|
+
/**
|
|
25
|
+
* attach listeners and run initial detection. idempotent.
|
|
26
|
+
* @param selector optional CSS selector; when given realWidth tracks that element's width instead of window.innerWidth
|
|
27
|
+
*/
|
|
28
|
+
init(selector?: string): void;
|
|
29
|
+
/** detach listeners. call on teardown/HMR dispose to avoid leaks. */
|
|
30
|
+
destroy(): void;
|
|
31
|
+
private measureWidth;
|
|
32
|
+
private now;
|
|
33
|
+
trigger(isStart?: boolean): void;
|
|
34
|
+
getMediaQuery(): void;
|
|
35
|
+
debounce(): void;
|
|
36
|
+
}
|
|
37
|
+
declare const resize: Resize;
|
|
38
|
+
declare const plugin: {
|
|
39
|
+
install: (_app: unknown, options?: {
|
|
40
|
+
selector?: string;
|
|
41
|
+
}) => void;
|
|
42
|
+
};
|
|
43
|
+
declare function useResize(): {
|
|
44
|
+
realHeight: import("vue").Ref<number, number>;
|
|
45
|
+
realWidth: import("vue").Ref<number, number>;
|
|
46
|
+
media: import("vue").Ref<string, string>;
|
|
47
|
+
resized: import("vue").Ref<number, number>;
|
|
48
|
+
widthChanged: import("vue").Ref<number, number>;
|
|
49
|
+
plugin: Resize;
|
|
50
|
+
};
|
|
51
|
+
export default plugin;
|
|
52
|
+
export { useResize, resize };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface UseWebSocketOptions {
|
|
2
|
+
url: string;
|
|
3
|
+
maxRetries: number;
|
|
4
|
+
maxRetryDelay: number;
|
|
5
|
+
onMessage?: (_data: string) => void;
|
|
6
|
+
onOpen?: () => void;
|
|
7
|
+
onClose?: (ev?: CloseEvent) => void;
|
|
8
|
+
onError?: (_error: Event) => void;
|
|
9
|
+
heartbeatIntervalMs?: number;
|
|
10
|
+
inactivityTimeoutMs?: number;
|
|
11
|
+
buildPingMessage?: () => object;
|
|
12
|
+
}
|
|
13
|
+
export declare class WebSocketManager {
|
|
14
|
+
private static instance;
|
|
15
|
+
private socket;
|
|
16
|
+
private currentOptions;
|
|
17
|
+
private retryCount;
|
|
18
|
+
private retryDelay;
|
|
19
|
+
private retryTimeoutId;
|
|
20
|
+
private refCount;
|
|
21
|
+
onConnectionChange?: (_isConnected: boolean) => void;
|
|
22
|
+
private heartbeatIntervalId;
|
|
23
|
+
private lastActivity;
|
|
24
|
+
private constructor();
|
|
25
|
+
static getInstance(): WebSocketManager;
|
|
26
|
+
get isConnected(): boolean;
|
|
27
|
+
get options(): UseWebSocketOptions;
|
|
28
|
+
/** Acquire a reference. Must be paired with release(). */
|
|
29
|
+
acquire(): void;
|
|
30
|
+
/** Release a reference; only close when nobody is using the socket. */
|
|
31
|
+
release(): void;
|
|
32
|
+
connect(options: UseWebSocketOptions): void;
|
|
33
|
+
private startHeartbeat;
|
|
34
|
+
private stopHeartbeat;
|
|
35
|
+
private attemptReconnect;
|
|
36
|
+
private calculateRetryDelay;
|
|
37
|
+
reconnect(): void;
|
|
38
|
+
disconnect(): void;
|
|
39
|
+
private _teardownSocket;
|
|
40
|
+
send(message: object): boolean;
|
|
41
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
status: {
|
|
3
|
+
connected: string;
|
|
4
|
+
disconnected: string;
|
|
5
|
+
};
|
|
6
|
+
actions: {
|
|
7
|
+
retry: string;
|
|
8
|
+
};
|
|
9
|
+
'new chat': string;
|
|
10
|
+
conversations: string;
|
|
11
|
+
'contact support': string;
|
|
12
|
+
support: string;
|
|
13
|
+
options: string;
|
|
14
|
+
mute: string;
|
|
15
|
+
delete: string;
|
|
16
|
+
leave: string;
|
|
17
|
+
'leave now': string;
|
|
18
|
+
'select contacts': string;
|
|
19
|
+
'conversation options': string;
|
|
20
|
+
system: {
|
|
21
|
+
renamed: string;
|
|
22
|
+
created: string;
|
|
23
|
+
left: string;
|
|
24
|
+
participants: {
|
|
25
|
+
addedAndRemoved: string;
|
|
26
|
+
added: string;
|
|
27
|
+
removed: string;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
export default _default;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
status: {
|
|
3
|
+
connected: string;
|
|
4
|
+
disconnected: string;
|
|
5
|
+
};
|
|
6
|
+
actions: {
|
|
7
|
+
retry: string;
|
|
8
|
+
};
|
|
9
|
+
'new chat': string;
|
|
10
|
+
conversations: string;
|
|
11
|
+
'contact support': string;
|
|
12
|
+
support: string;
|
|
13
|
+
options: string;
|
|
14
|
+
mute: string;
|
|
15
|
+
delete: string;
|
|
16
|
+
leave: string;
|
|
17
|
+
'leave now': string;
|
|
18
|
+
'select contacts': string;
|
|
19
|
+
'conversation options': string;
|
|
20
|
+
system: {
|
|
21
|
+
renamed: string;
|
|
22
|
+
created: string;
|
|
23
|
+
left: string;
|
|
24
|
+
participants: {
|
|
25
|
+
addedAndRemoved: string;
|
|
26
|
+
added: string;
|
|
27
|
+
removed: string;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
export default _default;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function groupMessages(messages: any, user: string): unknown[];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Ref } from 'vue';
|
|
2
|
+
declare const plugin: {
|
|
3
|
+
install: () => void;
|
|
4
|
+
};
|
|
5
|
+
declare const useTraceable: () => {
|
|
6
|
+
traceable: <T>(promise: Promise<T>, traceId?: Ref<string | undefined>, options?: {
|
|
7
|
+
time: number;
|
|
8
|
+
}) => Promise<T>;
|
|
9
|
+
};
|
|
10
|
+
export default plugin;
|
|
11
|
+
export { useTraceable };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export declare const DEFAULT_LOCALE = "en";
|
|
2
|
+
export declare const SUPPORTED_LOCALES: readonly ["en", "de"];
|
|
3
|
+
export type AppLocale = typeof SUPPORTED_LOCALES[number];
|
|
4
|
+
declare const i18n: import("vue-i18n").I18n<{
|
|
5
|
+
en: {
|
|
6
|
+
status: {
|
|
7
|
+
connected: string;
|
|
8
|
+
disconnected: string;
|
|
9
|
+
};
|
|
10
|
+
actions: {
|
|
11
|
+
retry: string;
|
|
12
|
+
};
|
|
13
|
+
'new chat': string;
|
|
14
|
+
conversations: string;
|
|
15
|
+
'contact support': string;
|
|
16
|
+
support: string;
|
|
17
|
+
options: string;
|
|
18
|
+
mute: string;
|
|
19
|
+
delete: string;
|
|
20
|
+
leave: string;
|
|
21
|
+
'leave now': string;
|
|
22
|
+
'select contacts': string;
|
|
23
|
+
'conversation options': string;
|
|
24
|
+
system: {
|
|
25
|
+
renamed: string;
|
|
26
|
+
created: string;
|
|
27
|
+
left: string;
|
|
28
|
+
participants: {
|
|
29
|
+
addedAndRemoved: string;
|
|
30
|
+
added: string;
|
|
31
|
+
removed: string;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
}, {}, {}, "en" | "de", false>;
|
|
36
|
+
/**
|
|
37
|
+
* Lazy load locale messages and switch locale.
|
|
38
|
+
*/
|
|
39
|
+
export declare function loadLocale(locale: AppLocale): Promise<AppLocale>;
|
|
40
|
+
export default i18n;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { type ChatUser } from '@/config/users';
|
|
2
|
+
export type BotStatus = 'idle' | 'connecting' | 'connected' | 'disconnected';
|
|
3
|
+
export interface Bot {
|
|
4
|
+
id: string;
|
|
5
|
+
userId: number;
|
|
6
|
+
name: string;
|
|
7
|
+
status: BotStatus;
|
|
8
|
+
autoReply: boolean;
|
|
9
|
+
}
|
|
10
|
+
/** the persisted bots exposed as chat users, so they can be picked as conversation participants */
|
|
11
|
+
export declare function botUsers(): ChatUser[];
|
|
12
|
+
/**
|
|
13
|
+
* Debugging bots — each behaves like a separate user of the chat. The roster is
|
|
14
|
+
* persisted to localStorage so it survives reloads; wiring a bot to actually
|
|
15
|
+
* connect/send comes later.
|
|
16
|
+
*/
|
|
17
|
+
export declare const useBotsStore: import("pinia").StoreDefinition<"bots", Pick<{
|
|
18
|
+
bots: import("vue").Ref<{
|
|
19
|
+
id: string;
|
|
20
|
+
userId: number;
|
|
21
|
+
name: string;
|
|
22
|
+
status: BotStatus;
|
|
23
|
+
autoReply: boolean;
|
|
24
|
+
}[], Bot[] | {
|
|
25
|
+
id: string;
|
|
26
|
+
userId: number;
|
|
27
|
+
name: string;
|
|
28
|
+
status: BotStatus;
|
|
29
|
+
autoReply: boolean;
|
|
30
|
+
}[]>;
|
|
31
|
+
addBot: () => string;
|
|
32
|
+
removeBot: (id: string) => void;
|
|
33
|
+
setStatus: (id: string, status: BotStatus) => void;
|
|
34
|
+
}, "bots">, Pick<{
|
|
35
|
+
bots: import("vue").Ref<{
|
|
36
|
+
id: string;
|
|
37
|
+
userId: number;
|
|
38
|
+
name: string;
|
|
39
|
+
status: BotStatus;
|
|
40
|
+
autoReply: boolean;
|
|
41
|
+
}[], Bot[] | {
|
|
42
|
+
id: string;
|
|
43
|
+
userId: number;
|
|
44
|
+
name: string;
|
|
45
|
+
status: BotStatus;
|
|
46
|
+
autoReply: boolean;
|
|
47
|
+
}[]>;
|
|
48
|
+
addBot: () => string;
|
|
49
|
+
removeBot: (id: string) => void;
|
|
50
|
+
setStatus: (id: string, status: BotStatus) => void;
|
|
51
|
+
}, never>, Pick<{
|
|
52
|
+
bots: import("vue").Ref<{
|
|
53
|
+
id: string;
|
|
54
|
+
userId: number;
|
|
55
|
+
name: string;
|
|
56
|
+
status: BotStatus;
|
|
57
|
+
autoReply: boolean;
|
|
58
|
+
}[], Bot[] | {
|
|
59
|
+
id: string;
|
|
60
|
+
userId: number;
|
|
61
|
+
name: string;
|
|
62
|
+
status: BotStatus;
|
|
63
|
+
autoReply: boolean;
|
|
64
|
+
}[]>;
|
|
65
|
+
addBot: () => string;
|
|
66
|
+
removeBot: (id: string) => void;
|
|
67
|
+
setStatus: (id: string, status: BotStatus) => void;
|
|
68
|
+
}, "addBot" | "removeBot" | "setStatus">>;
|
|
69
|
+
export default useBotsStore;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const useCallStore: import("pinia").StoreDefinition<"calls", Pick<{
|
|
2
|
+
calls: import("vue").Ref<Record<string, "rejected" | "pending" | "resolved">, Record<string, "rejected" | "pending" | "resolved">>;
|
|
3
|
+
addCall: () => string;
|
|
4
|
+
updateCall: (id: string, state: "pending" | "resolved" | "rejected") => void;
|
|
5
|
+
}, "calls">, Pick<{
|
|
6
|
+
calls: import("vue").Ref<Record<string, "rejected" | "pending" | "resolved">, Record<string, "rejected" | "pending" | "resolved">>;
|
|
7
|
+
addCall: () => string;
|
|
8
|
+
updateCall: (id: string, state: "pending" | "resolved" | "rejected") => void;
|
|
9
|
+
}, never>, Pick<{
|
|
10
|
+
calls: import("vue").Ref<Record<string, "rejected" | "pending" | "resolved">, Record<string, "rejected" | "pending" | "resolved">>;
|
|
11
|
+
addCall: () => string;
|
|
12
|
+
updateCall: (id: string, state: "pending" | "resolved" | "rejected") => void;
|
|
13
|
+
}, "addCall" | "updateCall">>;
|
|
14
|
+
export default useCallStore;
|