vg-x07df 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/.azure-pipelines/publish-public.yml +37 -0
- package/.azure-pipelines/publish.yml +39 -0
- package/.changeset/README.md +8 -0
- package/.changeset/config.json +11 -0
- package/AUTO_JOIN_GUIDE.md +411 -0
- package/README.md +215 -0
- package/Screenshot 2025-09-24 at 14.34.48.png +0 -0
- package/Screenshot 2025-10-04 at 12.58.54.png +0 -0
- package/biome.json +48 -0
- package/examples/demo/.env.example +19 -0
- package/examples/demo/CHANGELOG.md +22 -0
- package/examples/demo/README.md +72 -0
- package/examples/demo/eslint.config.js +23 -0
- package/examples/demo/index.html +13 -0
- package/examples/demo/package.json +34 -0
- package/examples/demo/pnpm-lock.yaml +2098 -0
- package/examples/demo/pnpm-workspace.yaml +1 -0
- package/examples/demo/public/vite.svg +1 -0
- package/examples/demo/src/App.css +52 -0
- package/examples/demo/src/App.tsx +176 -0
- package/examples/demo/src/assets/react.svg +1 -0
- package/examples/demo/src/components/auth/LoginForm.css +144 -0
- package/examples/demo/src/components/auth/LoginForm.tsx +80 -0
- package/examples/demo/src/components/calling/AutoJoinSettings.tsx +213 -0
- package/examples/demo/src/components/calling/AutoJoinStatus.tsx +72 -0
- package/examples/demo/src/components/calling/CallInitiator.css +258 -0
- package/examples/demo/src/components/calling/CallInitiator.tsx +142 -0
- package/examples/demo/src/components/calling/CallNotifications.css +119 -0
- package/examples/demo/src/components/calling/CallNotifications.tsx +108 -0
- package/examples/demo/src/components/calling/IncomingCallModal.css +192 -0
- package/examples/demo/src/components/calling/IncomingCallModal.tsx +78 -0
- package/examples/demo/src/components/calling/MinimizedCall.css +156 -0
- package/examples/demo/src/components/calling/MinimizedCall.tsx +78 -0
- package/examples/demo/src/components/conference/ConferenceHeader.css +265 -0
- package/examples/demo/src/components/conference/ConferenceHeader.tsx +78 -0
- package/examples/demo/src/components/conference/EnhancedControlBar.css +356 -0
- package/examples/demo/src/components/conference/EnhancedControlBar.tsx +262 -0
- package/examples/demo/src/components/conference/PaginationControls.css +67 -0
- package/examples/demo/src/components/conference/PaginationControls.tsx +64 -0
- package/examples/demo/src/components/conference/ParticipantGrid.css +153 -0
- package/examples/demo/src/components/conference/ParticipantGrid.tsx +87 -0
- package/examples/demo/src/components/conference/ParticipantTile.css +210 -0
- package/examples/demo/src/components/conference/ParticipantTile.tsx +114 -0
- package/examples/demo/src/components/conference/VideoConference.css +214 -0
- package/examples/demo/src/components/conference/VideoConference.tsx +93 -0
- package/examples/demo/src/contexts/AuthContext.tsx +105 -0
- package/examples/demo/src/hooks/useAuth.ts +5 -0
- package/examples/demo/src/hooks/useCallTimer.ts +42 -0
- package/examples/demo/src/index.css +68 -0
- package/examples/demo/src/main.tsx +10 -0
- package/examples/demo/src/services/auth.service.ts +153 -0
- package/examples/demo/src/types/auth.types.ts +31 -0
- package/examples/demo/tsconfig.app.json +28 -0
- package/examples/demo/tsconfig.json +7 -0
- package/examples/demo/tsconfig.node.json +26 -0
- package/examples/demo/vite.config.ts +15 -0
- package/images/callpad-without-ai.png +0 -0
- package/package.json +28 -0
- package/packages/sdk/CHANGELOG.md +33 -0
- package/packages/sdk/LICENSE +21 -0
- package/packages/sdk/README.md +97 -0
- package/packages/sdk/documentation.md +1132 -0
- package/packages/sdk/openapi-ts.config.ts +7 -0
- package/packages/sdk/package.json +88 -0
- package/packages/sdk/src/core/auth.manager.ts +52 -0
- package/packages/sdk/src/core/events/event-bus.ts +301 -0
- package/packages/sdk/src/core/events/index.ts +8 -0
- package/packages/sdk/src/core/events/types.ts +165 -0
- package/packages/sdk/src/core/index.ts +3 -0
- package/packages/sdk/src/core/signal/api.config.ts +49 -0
- package/packages/sdk/src/core/signal/index.ts +16 -0
- package/packages/sdk/src/core/signal/signal.client.ts +101 -0
- package/packages/sdk/src/core/signal/types.ts +110 -0
- package/packages/sdk/src/core/socketio/handlers/base.handler.ts +212 -0
- package/packages/sdk/src/core/socketio/handlers/call-accepted.handler.ts +34 -0
- package/packages/sdk/src/core/socketio/handlers/call-canceled.handler.ts +34 -0
- package/packages/sdk/src/core/socketio/handlers/call-declined.handler.ts +29 -0
- package/packages/sdk/src/core/socketio/handlers/call-ended.handler.ts +40 -0
- package/packages/sdk/src/core/socketio/handlers/call-incoming.handler.ts +72 -0
- package/packages/sdk/src/core/socketio/handlers/call-join-info.handler.ts +181 -0
- package/packages/sdk/src/core/socketio/handlers/call-participant-joined.handler.ts +42 -0
- package/packages/sdk/src/core/socketio/handlers/call-participant-joining.handler.ts +42 -0
- package/packages/sdk/src/core/socketio/handlers/call-timeout.handler.ts +31 -0
- package/packages/sdk/src/core/socketio/handlers/handler.registry.ts +62 -0
- package/packages/sdk/src/core/socketio/handlers/index.ts +21 -0
- package/packages/sdk/src/core/socketio/handlers/participant-left.handler.ts +37 -0
- package/packages/sdk/src/core/socketio/handlers/schema.ts +130 -0
- package/packages/sdk/src/core/socketio/index.ts +5 -0
- package/packages/sdk/src/core/socketio/socket.manager.ts +187 -0
- package/packages/sdk/src/core/socketio/types.ts +14 -0
- package/packages/sdk/src/core/types.ts +23 -0
- package/packages/sdk/src/generated/api/core/ApiError.ts +21 -0
- package/packages/sdk/src/generated/api/core/ApiRequestOptions.ts +13 -0
- package/packages/sdk/src/generated/api/core/ApiResult.ts +7 -0
- package/packages/sdk/src/generated/api/core/CancelablePromise.ts +126 -0
- package/packages/sdk/src/generated/api/core/OpenAPI.ts +55 -0
- package/packages/sdk/src/generated/api/core/request.ts +339 -0
- package/packages/sdk/src/generated/api/index.ts +5 -0
- package/packages/sdk/src/generated/api/models.ts +219 -0
- package/packages/sdk/src/generated/api/services.ts +225 -0
- package/packages/sdk/src/hooks/index.ts +21 -0
- package/packages/sdk/src/hooks/useAutoJoin.ts +66 -0
- package/packages/sdk/src/hooks/useCallActions.ts +28 -0
- package/packages/sdk/src/hooks/useCallQuality.ts +416 -0
- package/packages/sdk/src/hooks/useCallState.ts +23 -0
- package/packages/sdk/src/hooks/useConnection.ts +15 -0
- package/packages/sdk/src/hooks/useDevices.ts +296 -0
- package/packages/sdk/src/hooks/useErrorRecovery.ts +299 -0
- package/packages/sdk/src/hooks/useErrors.ts +84 -0
- package/packages/sdk/src/hooks/useEvent.ts +188 -0
- package/packages/sdk/src/hooks/useMediaControls.ts +215 -0
- package/packages/sdk/src/hooks/useParticipantStatus.ts +318 -0
- package/packages/sdk/src/hooks/useParticipants.ts +111 -0
- package/packages/sdk/src/index.ts +66 -0
- package/packages/sdk/src/livekit/constants.ts +76 -0
- package/packages/sdk/src/livekit/device.manager.ts +172 -0
- package/packages/sdk/src/livekit/error-classifier.ts +155 -0
- package/packages/sdk/src/livekit/events/eventBridge.ts +371 -0
- package/packages/sdk/src/livekit/events/trackRegistry.ts +114 -0
- package/packages/sdk/src/livekit/index.ts +49 -0
- package/packages/sdk/src/livekit/livekit.service.ts +110 -0
- package/packages/sdk/src/livekit/media.controls.ts +315 -0
- package/packages/sdk/src/livekit/room.manager.ts +79 -0
- package/packages/sdk/src/livekit/track.utils.ts +230 -0
- package/packages/sdk/src/livekit/types.ts +135 -0
- package/packages/sdk/src/provider/RtcProvider.tsx +78 -0
- package/packages/sdk/src/services/call-actions.ts +260 -0
- package/packages/sdk/src/services/error-recovery.ts +461 -0
- package/packages/sdk/src/services/index.ts +2 -0
- package/packages/sdk/src/services/sdk-builder.ts +104 -0
- package/packages/sdk/src/state/errors.ts +163 -0
- package/packages/sdk/src/state/selectors.ts +28 -0
- package/packages/sdk/src/state/store.ts +36 -0
- package/packages/sdk/src/state/types.ts +151 -0
- package/packages/sdk/src/utils/logger.ts +183 -0
- package/packages/sdk/tsconfig.json +49 -0
- package/packages/sdk/tsup.config.ts +51 -0
- package/pnpm-workspace.yaml +4 -0
- package/tsconfig.base.json +19 -0
- package/turbo.json +34 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { createContext, useContext, useState, useEffect, useCallback } from 'react';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import { AuthService } from '../services/auth.service';
|
|
4
|
+
import type { AuthState, LoginCredentials } from '../types/auth.types';
|
|
5
|
+
|
|
6
|
+
interface AuthContextValue extends AuthState {
|
|
7
|
+
login: (credentials: LoginCredentials) => Promise<{ success: boolean; error?: string }>;
|
|
8
|
+
logout: () => void;
|
|
9
|
+
clearError: () => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const AuthContext = createContext<AuthContextValue | undefined>(undefined);
|
|
13
|
+
|
|
14
|
+
export function AuthProvider({ children }: { children: ReactNode }) {
|
|
15
|
+
const [authState, setAuthState] = useState<AuthState>({
|
|
16
|
+
isAuthenticated: false,
|
|
17
|
+
user: null,
|
|
18
|
+
token: null,
|
|
19
|
+
loading: true,
|
|
20
|
+
error: null,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// Initialize auth state on mount
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
const token = AuthService.getToken();
|
|
26
|
+
const user = AuthService.getUser();
|
|
27
|
+
const isAuthenticated = AuthService.isAuthenticated();
|
|
28
|
+
|
|
29
|
+
console.log('AuthProvider: Initializing auth state', { isAuthenticated, hasToken: !!token, hasUser: !!user });
|
|
30
|
+
|
|
31
|
+
setAuthState({
|
|
32
|
+
isAuthenticated,
|
|
33
|
+
user,
|
|
34
|
+
token,
|
|
35
|
+
loading: false,
|
|
36
|
+
error: null,
|
|
37
|
+
});
|
|
38
|
+
}, []);
|
|
39
|
+
|
|
40
|
+
const login = useCallback(async (credentials: LoginCredentials) => {
|
|
41
|
+
console.log('AuthProvider: Starting login');
|
|
42
|
+
setAuthState(prev => ({ ...prev, loading: true, error: null }));
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
const { token, user } = await AuthService.login(credentials);
|
|
46
|
+
|
|
47
|
+
console.log('AuthProvider: Login successful', { hasToken: !!token, user });
|
|
48
|
+
|
|
49
|
+
setAuthState({
|
|
50
|
+
isAuthenticated: true,
|
|
51
|
+
user,
|
|
52
|
+
token,
|
|
53
|
+
loading: false,
|
|
54
|
+
error: null,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return { success: true };
|
|
58
|
+
} catch (error) {
|
|
59
|
+
const errorMessage = error instanceof Error ? error.message : 'Login failed';
|
|
60
|
+
|
|
61
|
+
console.error('AuthProvider: Login failed', errorMessage);
|
|
62
|
+
|
|
63
|
+
setAuthState(prev => ({
|
|
64
|
+
...prev,
|
|
65
|
+
loading: false,
|
|
66
|
+
error: errorMessage,
|
|
67
|
+
}));
|
|
68
|
+
|
|
69
|
+
return { success: false, error: errorMessage };
|
|
70
|
+
}
|
|
71
|
+
}, []);
|
|
72
|
+
|
|
73
|
+
const logout = useCallback(() => {
|
|
74
|
+
console.log('AuthProvider: Logging out');
|
|
75
|
+
AuthService.logout();
|
|
76
|
+
setAuthState({
|
|
77
|
+
isAuthenticated: false,
|
|
78
|
+
user: null,
|
|
79
|
+
token: null,
|
|
80
|
+
loading: false,
|
|
81
|
+
error: null,
|
|
82
|
+
});
|
|
83
|
+
}, []);
|
|
84
|
+
|
|
85
|
+
const clearError = useCallback(() => {
|
|
86
|
+
setAuthState(prev => ({ ...prev, error: null }));
|
|
87
|
+
}, []);
|
|
88
|
+
|
|
89
|
+
const value: AuthContextValue = {
|
|
90
|
+
...authState,
|
|
91
|
+
login,
|
|
92
|
+
logout,
|
|
93
|
+
clearError,
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function useAuthContext() {
|
|
100
|
+
const context = useContext(AuthContext);
|
|
101
|
+
if (context === undefined) {
|
|
102
|
+
throw new Error('useAuthContext must be used within an AuthProvider');
|
|
103
|
+
}
|
|
104
|
+
return context;
|
|
105
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
import { useCallState } from 'vg-x07df';
|
|
3
|
+
|
|
4
|
+
export function useCallTimer() {
|
|
5
|
+
const [duration, setDuration] = useState(0);
|
|
6
|
+
const { status } = useCallState();
|
|
7
|
+
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (status !== 'ACTIVE') {
|
|
10
|
+
setDuration(0);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Start timer when call becomes active
|
|
15
|
+
const startTime = Date.now();
|
|
16
|
+
|
|
17
|
+
const interval = setInterval(() => {
|
|
18
|
+
const elapsed = Math.floor((Date.now() - startTime) / 1000);
|
|
19
|
+
setDuration(elapsed);
|
|
20
|
+
}, 1000);
|
|
21
|
+
|
|
22
|
+
return () => clearInterval(interval);
|
|
23
|
+
}, [status]);
|
|
24
|
+
|
|
25
|
+
const formatDuration = (seconds: number): string => {
|
|
26
|
+
const hours = Math.floor(seconds / 3600);
|
|
27
|
+
const minutes = Math.floor((seconds % 3600) / 60);
|
|
28
|
+
const secs = seconds % 60;
|
|
29
|
+
|
|
30
|
+
if (hours > 0) {
|
|
31
|
+
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return `${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
duration,
|
|
39
|
+
formattedDuration: formatDuration(duration),
|
|
40
|
+
isActive: status === 'ACTIVE',
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
3
|
+
line-height: 1.5;
|
|
4
|
+
font-weight: 400;
|
|
5
|
+
|
|
6
|
+
color-scheme: light dark;
|
|
7
|
+
color: rgba(255, 255, 255, 0.87);
|
|
8
|
+
background-color: #242424;
|
|
9
|
+
|
|
10
|
+
font-synthesis: none;
|
|
11
|
+
text-rendering: optimizeLegibility;
|
|
12
|
+
-webkit-font-smoothing: antialiased;
|
|
13
|
+
-moz-osx-font-smoothing: grayscale;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
a {
|
|
17
|
+
font-weight: 500;
|
|
18
|
+
color: #646cff;
|
|
19
|
+
text-decoration: inherit;
|
|
20
|
+
}
|
|
21
|
+
a:hover {
|
|
22
|
+
color: #535bf2;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
body {
|
|
26
|
+
margin: 0;
|
|
27
|
+
display: flex;
|
|
28
|
+
place-items: center;
|
|
29
|
+
min-width: 320px;
|
|
30
|
+
min-height: 100vh;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
h1 {
|
|
34
|
+
font-size: 3.2em;
|
|
35
|
+
line-height: 1.1;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
button {
|
|
39
|
+
border-radius: 8px;
|
|
40
|
+
border: 1px solid transparent;
|
|
41
|
+
padding: 0.6em 1.2em;
|
|
42
|
+
font-size: 1em;
|
|
43
|
+
font-weight: 500;
|
|
44
|
+
font-family: inherit;
|
|
45
|
+
background-color: #1a1a1a;
|
|
46
|
+
cursor: pointer;
|
|
47
|
+
transition: border-color 0.25s;
|
|
48
|
+
}
|
|
49
|
+
button:hover {
|
|
50
|
+
border-color: #646cff;
|
|
51
|
+
}
|
|
52
|
+
button:focus,
|
|
53
|
+
button:focus-visible {
|
|
54
|
+
outline: 4px auto -webkit-focus-ring-color;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@media (prefers-color-scheme: light) {
|
|
58
|
+
:root {
|
|
59
|
+
color: #213547;
|
|
60
|
+
background-color: #ffffff;
|
|
61
|
+
}
|
|
62
|
+
a:hover {
|
|
63
|
+
color: #747bff;
|
|
64
|
+
}
|
|
65
|
+
button {
|
|
66
|
+
background-color: #f9f9f9;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import type { LoginCredentials, AuthUser } from '../types/auth.types';
|
|
2
|
+
|
|
3
|
+
const AUTH_URL = 'https://gopaddibackend.vgtechdemo.com/api/v1/auth/login';
|
|
4
|
+
const TOKEN_STORAGE_KEY = 'callpad_demo_token';
|
|
5
|
+
const USER_STORAGE_KEY = 'callpad_demo_user';
|
|
6
|
+
|
|
7
|
+
// Function to decode JWT without verification (copied from get-token.ts)
|
|
8
|
+
function decodeJWT(token: string): any {
|
|
9
|
+
const parts = token.split('.');
|
|
10
|
+
if (parts.length !== 3) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
const decodedPayload = JSON.parse(
|
|
16
|
+
atob(parts[1].replace(/-/g, '+').replace(/_/g, '/'))
|
|
17
|
+
);
|
|
18
|
+
return decodedPayload;
|
|
19
|
+
} catch (e) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Extract user info from JWT token
|
|
25
|
+
function extractUserFromToken(token: string): AuthUser | null {
|
|
26
|
+
const decoded = decodeJWT(token);
|
|
27
|
+
if (!decoded) return null;
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
id: decoded.sub || decoded.userId || decoded.id,
|
|
31
|
+
email: decoded.email,
|
|
32
|
+
firstName: decoded.firstName || decoded.first_name,
|
|
33
|
+
lastName: decoded.lastName || decoded.last_name,
|
|
34
|
+
avatarUrl: decoded.avatarUrl || decoded.avatar_url,
|
|
35
|
+
exp: decoded.exp,
|
|
36
|
+
iat: decoded.iat,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export class AuthService {
|
|
41
|
+
// Login function using the same logic as fetchTokenSilent from get-token.ts
|
|
42
|
+
static async login(credentials: LoginCredentials): Promise<{ token: string; user: AuthUser }> {
|
|
43
|
+
const response = await fetch(AUTH_URL, {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
headers: {
|
|
46
|
+
'Content-Type': 'application/json',
|
|
47
|
+
'Accept': 'application/json',
|
|
48
|
+
},
|
|
49
|
+
body: JSON.stringify({
|
|
50
|
+
email: credentials.email,
|
|
51
|
+
password: credentials.password,
|
|
52
|
+
}),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
if (!response.ok) {
|
|
56
|
+
const errorText = await response.text();
|
|
57
|
+
let errorMessage = `Authentication failed: ${response.status} ${response.statusText}`;
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
const errorJson = JSON.parse(errorText);
|
|
61
|
+
errorMessage = errorJson.message || errorJson.error || errorMessage;
|
|
62
|
+
} catch {
|
|
63
|
+
if (errorText) {
|
|
64
|
+
errorMessage += ` - ${errorText}`;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
throw new Error(errorMessage);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const data = (await response.json()) as any;
|
|
72
|
+
|
|
73
|
+
// Debug: Log the actual response structure
|
|
74
|
+
console.log('Login response:', data);
|
|
75
|
+
|
|
76
|
+
// Extract token from response - try multiple possible locations
|
|
77
|
+
const token = data.token ||
|
|
78
|
+
data.access_token ||
|
|
79
|
+
data.jwt ||
|
|
80
|
+
data.data?.token ||
|
|
81
|
+
data.data?.access_token ||
|
|
82
|
+
data.data?.jwt ||
|
|
83
|
+
data.data?.user_details?.token ||
|
|
84
|
+
data.data?.user_details?.access_token;
|
|
85
|
+
|
|
86
|
+
console.log('Extracted token:', token ? 'Found token' : 'No token found');
|
|
87
|
+
|
|
88
|
+
if (!token) {
|
|
89
|
+
console.error('Full response structure:', JSON.stringify(data, null, 2));
|
|
90
|
+
throw new Error('No token found in response');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Extract user info from token
|
|
94
|
+
const user = extractUserFromToken(token);
|
|
95
|
+
if (!user) {
|
|
96
|
+
throw new Error('Invalid token format');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Store token and user info
|
|
100
|
+
localStorage.setItem(TOKEN_STORAGE_KEY, token);
|
|
101
|
+
localStorage.setItem(USER_STORAGE_KEY, JSON.stringify(user));
|
|
102
|
+
|
|
103
|
+
return { token, user };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Get stored token
|
|
107
|
+
static getToken(): string | null {
|
|
108
|
+
return localStorage.getItem(TOKEN_STORAGE_KEY);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Get stored user
|
|
112
|
+
static getUser(): AuthUser | null {
|
|
113
|
+
const userJson = localStorage.getItem(USER_STORAGE_KEY);
|
|
114
|
+
if (!userJson) return null;
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
return JSON.parse(userJson);
|
|
118
|
+
} catch {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Check if user is authenticated and token is valid
|
|
124
|
+
static isAuthenticated(): boolean {
|
|
125
|
+
const token = this.getToken();
|
|
126
|
+
const user = this.getUser();
|
|
127
|
+
|
|
128
|
+
if (!token || !user) return false;
|
|
129
|
+
|
|
130
|
+
// Check token expiration if available
|
|
131
|
+
if (user.exp) {
|
|
132
|
+
const now = Math.floor(Date.now() / 1000);
|
|
133
|
+
if (now >= user.exp) {
|
|
134
|
+
this.logout();
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Logout and clear storage
|
|
143
|
+
static logout(): void {
|
|
144
|
+
localStorage.removeItem(TOKEN_STORAGE_KEY);
|
|
145
|
+
localStorage.removeItem(USER_STORAGE_KEY);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Get authorization header for API calls
|
|
149
|
+
static getAuthHeader(): { Authorization: string } | {} {
|
|
150
|
+
const token = this.getToken();
|
|
151
|
+
return token ? { Authorization: `Bearer ${token}` } : {};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface LoginCredentials {
|
|
2
|
+
email: string;
|
|
3
|
+
password: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface AuthUser {
|
|
7
|
+
id: string;
|
|
8
|
+
email: string;
|
|
9
|
+
firstName?: string;
|
|
10
|
+
lastName?: string;
|
|
11
|
+
avatarUrl?: string;
|
|
12
|
+
exp?: number;
|
|
13
|
+
iat?: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface AuthState {
|
|
17
|
+
isAuthenticated: boolean;
|
|
18
|
+
user: AuthUser | null;
|
|
19
|
+
token: string | null;
|
|
20
|
+
loading: boolean;
|
|
21
|
+
error: string | null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface AuthResponse {
|
|
25
|
+
token?: string;
|
|
26
|
+
access_token?: string;
|
|
27
|
+
jwt?: string;
|
|
28
|
+
data?: {
|
|
29
|
+
token: string;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
4
|
+
"target": "ES2022",
|
|
5
|
+
"useDefineForClassFields": true,
|
|
6
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
7
|
+
"module": "ESNext",
|
|
8
|
+
"types": ["vite/client"],
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
|
|
11
|
+
/* Bundler mode */
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"verbatimModuleSyntax": true,
|
|
15
|
+
"moduleDetection": "force",
|
|
16
|
+
"noEmit": true,
|
|
17
|
+
"jsx": "react-jsx",
|
|
18
|
+
|
|
19
|
+
/* Linting */
|
|
20
|
+
"strict": true,
|
|
21
|
+
"noUnusedLocals": true,
|
|
22
|
+
"noUnusedParameters": true,
|
|
23
|
+
"erasableSyntaxOnly": true,
|
|
24
|
+
"noFallthroughCasesInSwitch": true,
|
|
25
|
+
"noUncheckedSideEffectImports": true
|
|
26
|
+
},
|
|
27
|
+
"include": ["src"]
|
|
28
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
|
4
|
+
"target": "ES2023",
|
|
5
|
+
"lib": ["ES2023"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"types": [],
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
|
|
10
|
+
/* Bundler mode */
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"allowImportingTsExtensions": true,
|
|
13
|
+
"verbatimModuleSyntax": true,
|
|
14
|
+
"moduleDetection": "force",
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
|
|
17
|
+
/* Linting */
|
|
18
|
+
"strict": true,
|
|
19
|
+
"noUnusedLocals": true,
|
|
20
|
+
"noUnusedParameters": true,
|
|
21
|
+
"erasableSyntaxOnly": true,
|
|
22
|
+
"noFallthroughCasesInSwitch": true,
|
|
23
|
+
"noUncheckedSideEffectImports": true
|
|
24
|
+
},
|
|
25
|
+
"include": ["vite.config.ts"]
|
|
26
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { defineConfig } from 'vite'
|
|
2
|
+
import react from '@vitejs/plugin-react'
|
|
3
|
+
|
|
4
|
+
// https://vite.dev/config/
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
plugins: [react()],
|
|
7
|
+
server: {
|
|
8
|
+
port: 3000,
|
|
9
|
+
host: true,
|
|
10
|
+
},
|
|
11
|
+
build: {
|
|
12
|
+
outDir: 'dist',
|
|
13
|
+
sourcemap: true,
|
|
14
|
+
},
|
|
15
|
+
})
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vg-x07df",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"scripts": {
|
|
5
|
+
"build": "turbo run build",
|
|
6
|
+
"dev": "turbo run dev",
|
|
7
|
+
"lint": "biome check .",
|
|
8
|
+
"format": "biome format --write .",
|
|
9
|
+
"lint:fix": "biome check --apply .",
|
|
10
|
+
"check": "biome check --fix --unsafe",
|
|
11
|
+
"check-types": "turbo run check-types",
|
|
12
|
+
"changeset": "changeset",
|
|
13
|
+
"version": "changeset version",
|
|
14
|
+
"publish:dev": "turbo run build check-types --filter=vg-x07df && dotenv -- changeset publish",
|
|
15
|
+
"publish:dry": "turbo run build check-types --filter=vg-x07df && dotenv -- changeset publish --dry-run"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@biomejs/biome": "^1.8.0",
|
|
19
|
+
"@changesets/cli": "^2.29.7",
|
|
20
|
+
"dotenv-cli": "^10.0.0",
|
|
21
|
+
"turbo": "^2.5.8",
|
|
22
|
+
"typescript": "5.9.2"
|
|
23
|
+
},
|
|
24
|
+
"packageManager": "pnpm@9.0.0",
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=18"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# vg-x07df
|
|
2
|
+
|
|
3
|
+
## 1.0.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Update README documentation
|
|
8
|
+
|
|
9
|
+
- Enhanced README with improved examples and API reference
|
|
10
|
+
- Updated hook descriptions to match actual implementation
|
|
11
|
+
- Corrected usage examples for better clarity
|
|
12
|
+
|
|
13
|
+
## 1.0.1
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Add comprehensive README and LICENSE files
|
|
18
|
+
|
|
19
|
+
- Added detailed README.md with installation, usage examples, and API reference
|
|
20
|
+
- Added MIT LICENSE file
|
|
21
|
+
- Fixed missing documentation on npm package page
|
|
22
|
+
|
|
23
|
+
## 1.0.0
|
|
24
|
+
|
|
25
|
+
### Major Changes
|
|
26
|
+
|
|
27
|
+
- Initial release of CallPad SDK
|
|
28
|
+
|
|
29
|
+
- Production-ready headless SDK for CallPad audio/video calls
|
|
30
|
+
- React hooks for managing call state, participants, media controls
|
|
31
|
+
- LiveKit integration for real-time communication
|
|
32
|
+
- Socket.io support for call signaling
|
|
33
|
+
- TypeScript support with full type definitions
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Voyatek Group
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# CallPad SDK
|
|
2
|
+
|
|
3
|
+
Production-ready headless SDK for CallPad audio/video calls with React integration.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install vg-x07df
|
|
9
|
+
# or
|
|
10
|
+
yarn add vg-x07df
|
|
11
|
+
# or
|
|
12
|
+
pnpm add vg-x07df
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { CallpadSdkProvider, useCallActions, useCallState } from 'vg-x07df';
|
|
19
|
+
|
|
20
|
+
function App() {
|
|
21
|
+
return (
|
|
22
|
+
<CallpadSdkProvider config={{ apiUrl: 'your-api-url' }}>
|
|
23
|
+
<CallInterface />
|
|
24
|
+
</CallpadSdkProvider>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function CallInterface() {
|
|
29
|
+
const { initiate, accept, end } = useCallActions();
|
|
30
|
+
const { status, participants } = useCallState();
|
|
31
|
+
|
|
32
|
+
const handleStartCall = () => {
|
|
33
|
+
initiate(['user@example.com'], 'VIDEO');
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<div>
|
|
38
|
+
<h1>Call Status: {status}</h1>
|
|
39
|
+
<button onClick={handleStartCall}>Start Video Call</button>
|
|
40
|
+
<div>Participants: {participants.length}</div>
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Features
|
|
47
|
+
|
|
48
|
+
- 🎥 **Audio & Video Calls** - High-quality real-time communication
|
|
49
|
+
- ⚡ **React Hooks** - Modern React integration with custom hooks
|
|
50
|
+
- 🔧 **Headless UI** - Bring your own UI components
|
|
51
|
+
- 📱 **Responsive** - Works across desktop and mobile
|
|
52
|
+
- 🔒 **Secure** - End-to-end encrypted communications
|
|
53
|
+
- 🎛️ **Media Controls** - Camera, microphone, and screen sharing
|
|
54
|
+
- 👥 **Multi-participant** - Support for group calls
|
|
55
|
+
- 📊 **Call Quality** - Real-time quality monitoring
|
|
56
|
+
- 🔔 **Event System** - Comprehensive call event handling
|
|
57
|
+
|
|
58
|
+
## API Reference
|
|
59
|
+
|
|
60
|
+
### Providers
|
|
61
|
+
|
|
62
|
+
- `CallpadSdkProvider` - Main provider component for SDK configuration
|
|
63
|
+
|
|
64
|
+
### Hooks
|
|
65
|
+
|
|
66
|
+
- `useCallActions()` - Actions for managing calls (initiate, accept, decline, end, cancel)
|
|
67
|
+
- `useCallState()` - Current call state and session information
|
|
68
|
+
- `useParticipants()` - Participant management and information
|
|
69
|
+
- `useMediaControls()` - Camera, microphone, and screen sharing controls
|
|
70
|
+
- `useDevices()` - Audio/video device selection
|
|
71
|
+
- `useEvent()` - SDK event subscriptions
|
|
72
|
+
- `useCallQuality()` - Real-time call quality metrics
|
|
73
|
+
- `useErrors()` - Error handling and management
|
|
74
|
+
|
|
75
|
+
### LiveKit Integration
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
import { LiveKitProvider, useTrack } from 'vg-x07df/livekit';
|
|
79
|
+
|
|
80
|
+
// Access LiveKit room and tracks directly
|
|
81
|
+
const track = useTrack();
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Requirements
|
|
85
|
+
|
|
86
|
+
- React ≥18.0.0
|
|
87
|
+
- React DOM ≥18.0.0
|
|
88
|
+
- LiveKit Client ≥2.8.0
|
|
89
|
+
- Socket.IO Client ≥4.7.0
|
|
90
|
+
|
|
91
|
+
## TypeScript Support
|
|
92
|
+
|
|
93
|
+
This package includes full TypeScript definitions. No additional @types packages needed.
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
import type { CallState, Participant, CallQuality } from 'vg-x07df';
|
|
97
|
+
```
|