nervoscan-js-sdk 1.0.4-0 → 1.0.4
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/README.md +298 -73
- package/dist/nervoscan-js-sdk.js +2 -2
- package/dist/nervoscan-js-sdk.mjs +36 -32
- package/dist/nervoscan-js-sdk.umd.js +84 -84
- package/package.json +1 -1
- package/src/api/Client.ts +45 -40
package/README.md
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|

|
|
2
2
|
|
|
3
|
+
# NervoScan JS SDK
|
|
4
|
+
|
|
3
5
|
[](https://www.npmjs.com/package/nervoscan-js-sdk)
|
|
6
|
+
[](https://opensource.org/licenses/ISC)
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
4
8
|
|
|
5
9
|
## Overview
|
|
6
10
|
|
|
7
|
-
The **NervoScan JS SDK** is a
|
|
8
|
-
|
|
9
|
-
It provides a singleton `Client` interface and a full suite of custom error classes for advanced control and debugging.
|
|
11
|
+
The **NervoScan JS SDK** is a comprehensive JavaScript/TypeScript library that enables seamless integration with the NervoScan contactless health analysis platform. This SDK provides real-time video streaming capabilities, live health metric results, and robust error handling for building sophisticated health monitoring applications.
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
### Key Features
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
15
|
+
- 🎥 **Real-time Video Streaming** - Stream video directly from webcam using WebRTC
|
|
16
|
+
- 📊 **Live Results** - Receive health metrics in real-time via Firebase
|
|
17
|
+
- 🔄 **Dual Processing Modes** - Support for both batch video upload and live streaming
|
|
18
|
+
- 🏗️ **Multiple Backend Types** - Server and serverless deployment options
|
|
19
|
+
- 🛡️ **Type-Safe** - Full TypeScript support with comprehensive type definitions
|
|
20
|
+
- 🎯 **Smart Error Handling** - Detailed error classes for face positioning and scan quality
|
|
21
|
+
- ⚡ **Framework Agnostic** - Works with React, Vue, Angular, or vanilla JS
|
|
22
|
+
- 📦 **Multiple Module Formats** - ESM, CommonJS, and UMD builds included
|
|
21
23
|
|
|
22
24
|
---
|
|
23
25
|
|
|
@@ -27,35 +29,71 @@ It provides a singleton `Client` interface and a full suite of custom error clas
|
|
|
27
29
|
npm install nervoscan-js-sdk
|
|
28
30
|
```
|
|
29
31
|
|
|
32
|
+
Or with yarn:
|
|
33
|
+
```bash
|
|
34
|
+
yarn add nervoscan-js-sdk
|
|
35
|
+
```
|
|
36
|
+
|
|
30
37
|
---
|
|
31
38
|
|
|
32
|
-
##
|
|
39
|
+
## Quick Start
|
|
33
40
|
|
|
34
|
-
|
|
35
|
-
|
|
41
|
+
### Basic Video Upload
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { Client } from 'nervoscan-js-sdk';
|
|
36
45
|
|
|
37
|
-
// Get the singleton instance
|
|
38
46
|
const client = Client.getInstance();
|
|
39
47
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
48
|
+
// Initialize with credentials
|
|
49
|
+
await client.initialize('username', 'password');
|
|
50
|
+
|
|
51
|
+
// Upload a video file
|
|
52
|
+
const videoBlob = new Blob([videoData], { type: 'video/mp4' });
|
|
53
|
+
const jobId = await client.uploadVideo(videoBlob);
|
|
54
|
+
|
|
55
|
+
console.log('Video uploaded! Job ID:', jobId);
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Real-time Streaming with Live Results
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import { Client } from 'nervoscan-js-sdk';
|
|
62
|
+
|
|
63
|
+
const client = Client.getInstance();
|
|
64
|
+
|
|
65
|
+
async function startHealthMonitoring() {
|
|
66
|
+
// Initialize client
|
|
67
|
+
await client.initialize('username', 'password');
|
|
68
|
+
|
|
69
|
+
// Set up result callbacks
|
|
70
|
+
client.setOnWindowResults((results) => {
|
|
71
|
+
console.log('New window results:', results);
|
|
72
|
+
// Update UI with real-time metrics
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
client.setOnFinalResults((results) => {
|
|
76
|
+
console.log('Final averaged results:', results);
|
|
77
|
+
// Display final health report
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
client.setOnError((error) => {
|
|
81
|
+
console.error('Scan error:', error);
|
|
82
|
+
// Handle scanning errors
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Get webcam stream
|
|
86
|
+
const stream = await navigator.mediaDevices.getUserMedia({
|
|
87
|
+
video: { width: 1280, height: 720 }
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Initialize streaming
|
|
91
|
+
const videoElement = document.getElementById('video') as HTMLVideoElement;
|
|
92
|
+
client.initializeStreaming(stream, videoElement);
|
|
93
|
+
|
|
94
|
+
// Start streaming
|
|
95
|
+
const jobId = await client.startStreaming();
|
|
96
|
+
console.log('Streaming started! Job ID:', jobId);
|
|
59
97
|
}
|
|
60
98
|
```
|
|
61
99
|
|
|
@@ -63,73 +101,260 @@ async function submitScan(videoBlob: Blob) {
|
|
|
63
101
|
|
|
64
102
|
## API Reference
|
|
65
103
|
|
|
66
|
-
###
|
|
104
|
+
### Client Class
|
|
105
|
+
|
|
106
|
+
The `Client` class follows a singleton pattern to ensure consistent state management across your application.
|
|
67
107
|
|
|
68
|
-
####
|
|
69
|
-
|
|
70
|
-
|
|
108
|
+
#### Getting the Instance
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
const client = Client.getInstance();
|
|
71
112
|
```
|
|
72
|
-
Returns the singleton instance of the Client class.
|
|
73
113
|
|
|
74
|
-
#### Methods
|
|
114
|
+
#### Core Methods
|
|
115
|
+
|
|
116
|
+
##### `initialize(username: string, password: string, serverType?: string): void`
|
|
117
|
+
Initializes the client with authentication credentials.
|
|
118
|
+
|
|
119
|
+
- `username` - Your NervoScan account username
|
|
120
|
+
- `password` - Your NervoScan account password
|
|
121
|
+
- `serverType` - Backend type: `'server'` (default) or `'serverless'`
|
|
122
|
+
|
|
123
|
+
##### `uploadVideo(videoBlob: Blob): Promise<string>`
|
|
124
|
+
Uploads a video for processing and returns the job ID.
|
|
125
|
+
|
|
126
|
+
- `videoBlob` - Video file as a Blob object
|
|
127
|
+
- Returns: Promise resolving to the job ID string
|
|
128
|
+
|
|
129
|
+
##### `initializeStreaming(videoStream: MediaStream, videoElement: HTMLVideoElement): void`
|
|
130
|
+
Sets up real-time video streaming.
|
|
131
|
+
|
|
132
|
+
- `videoStream` - MediaStream from getUserMedia
|
|
133
|
+
- `videoElement` - HTML video element for preview
|
|
134
|
+
|
|
135
|
+
##### `startStreaming(): Promise<string>`
|
|
136
|
+
Begins streaming video to the server for real-time analysis.
|
|
137
|
+
|
|
138
|
+
- Returns: Promise resolving to the job ID string
|
|
139
|
+
|
|
140
|
+
##### `stopStreaming(): void`
|
|
141
|
+
Stops the active streaming session.
|
|
142
|
+
|
|
143
|
+
#### Callback Methods
|
|
75
144
|
|
|
76
|
-
|
|
77
|
-
|
|
145
|
+
##### `setOnWindowResults(callback: (results: any) => void): void`
|
|
146
|
+
Sets callback for receiving real-time window-based results.
|
|
78
147
|
|
|
79
|
-
|
|
80
|
-
|
|
148
|
+
##### `setOnFinalResults(callback: (results: any) => void): void`
|
|
149
|
+
Sets callback for receiving final averaged results.
|
|
81
150
|
|
|
82
|
-
|
|
83
|
-
|
|
151
|
+
##### `setOnError(callback: (error: any) => void): void`
|
|
152
|
+
Sets callback for handling scan errors.
|
|
84
153
|
|
|
85
|
-
|
|
86
|
-
|
|
154
|
+
##### `setOnDisconnection(callback: () => void): void`
|
|
155
|
+
Sets callback for handling connection loss.
|
|
156
|
+
|
|
157
|
+
#### Deprecated Methods
|
|
158
|
+
|
|
159
|
+
⚠️ The following methods are deprecated and will be removed in future versions:
|
|
160
|
+
|
|
161
|
+
- `checkResults(jobID: string)` - Use callback methods instead
|
|
162
|
+
- `getResults(jobID: string)` - Use callback methods instead
|
|
87
163
|
|
|
88
164
|
---
|
|
89
165
|
|
|
90
166
|
## Error Handling
|
|
91
167
|
|
|
92
|
-
The SDK provides
|
|
93
|
-
|
|
94
|
-
```ts
|
|
95
|
-
import { Errors } from 'nervoscan-js-sdk';
|
|
168
|
+
The SDK provides comprehensive error classes for granular error control:
|
|
96
169
|
|
|
170
|
+
### Authentication Errors
|
|
171
|
+
```typescript
|
|
97
172
|
try {
|
|
98
173
|
await client.initialize('username', 'password');
|
|
99
|
-
} catch (
|
|
100
|
-
if (
|
|
101
|
-
console.error('
|
|
174
|
+
} catch (error) {
|
|
175
|
+
if (error instanceof Errors.InvalidUsernameError) {
|
|
176
|
+
console.error('Invalid username');
|
|
177
|
+
} else if (error instanceof Errors.InvalidPasswordError) {
|
|
178
|
+
console.error('Invalid password');
|
|
102
179
|
}
|
|
103
180
|
}
|
|
104
181
|
```
|
|
105
182
|
|
|
106
|
-
###
|
|
183
|
+
### Scan Quality Errors
|
|
184
|
+
```typescript
|
|
185
|
+
client.setOnError((error) => {
|
|
186
|
+
if (error instanceof Errors.FaceTooFarError) {
|
|
187
|
+
showMessage('Please move closer to the camera');
|
|
188
|
+
} else if (error instanceof Errors.FaceTooCloseError) {
|
|
189
|
+
showMessage('Please move further from the camera');
|
|
190
|
+
} else if (error instanceof Errors.FaceNotCenteredError) {
|
|
191
|
+
showMessage('Please center your face in the frame');
|
|
192
|
+
} else if (error instanceof Errors.LowFPSError) {
|
|
193
|
+
showMessage('Poor video quality - check your lighting');
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
```
|
|
107
197
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
198
|
+
### Complete Error Reference
|
|
199
|
+
|
|
200
|
+
| Error Class | Description |
|
|
201
|
+
|-------------|-------------|
|
|
202
|
+
| `NotInitializedError` | Client not initialized |
|
|
203
|
+
| `EmptyVideoError` | Video blob is empty |
|
|
204
|
+
| `VideoTypeError` | Invalid video type |
|
|
205
|
+
| `InvalidUsernameError` | Invalid username |
|
|
206
|
+
| `InvalidPasswordError` | Invalid password |
|
|
207
|
+
| `InvalidAccessTokenError` | Invalid or expired token |
|
|
208
|
+
| `NoScansAvailableError` | No scans left in plan |
|
|
209
|
+
| `NoScanDataError` | No data for job ID |
|
|
210
|
+
| `InvalidServerTypeError` | Invalid server type |
|
|
211
|
+
| `LowFPSError` | Video FPS too low |
|
|
212
|
+
| `FaceNotCenteredError` | Face not centered |
|
|
213
|
+
| `FaceTooFarError` | Face too far away |
|
|
214
|
+
| `FaceTooCloseError` | Face too close |
|
|
215
|
+
| `FaceLookingLeftError` | Face turned left |
|
|
216
|
+
| `FaceLookingRightError` | Face turned right |
|
|
217
|
+
| `UnhandledScanError` | Other scan errors |
|
|
116
218
|
|
|
117
219
|
---
|
|
118
220
|
|
|
119
|
-
##
|
|
221
|
+
## Real-World Examples
|
|
222
|
+
|
|
223
|
+
### React Component with Live Monitoring
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
227
|
+
import { Client, Errors } from 'nervoscan-js-sdk';
|
|
228
|
+
|
|
229
|
+
function HealthMonitor() {
|
|
230
|
+
const videoRef = useRef<HTMLVideoElement>(null);
|
|
231
|
+
const [isScanning, setIsScanning] = useState(false);
|
|
232
|
+
const [heartRate, setHeartRate] = useState<number | null>(null);
|
|
233
|
+
const [message, setMessage] = useState('');
|
|
234
|
+
|
|
235
|
+
const client = Client.getInstance();
|
|
236
|
+
|
|
237
|
+
useEffect(() => {
|
|
238
|
+
// Setup callbacks
|
|
239
|
+
client.setOnWindowResults((results) => {
|
|
240
|
+
setHeartRate(results.heartRate);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
client.setOnError((error) => {
|
|
244
|
+
if (error instanceof Errors.FaceNotCenteredError) {
|
|
245
|
+
setMessage('Center your face in the frame');
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
return () => {
|
|
250
|
+
client.stopStreaming();
|
|
251
|
+
};
|
|
252
|
+
}, []);
|
|
253
|
+
|
|
254
|
+
const startScan = async () => {
|
|
255
|
+
try {
|
|
256
|
+
await client.initialize('user@example.com', 'password');
|
|
257
|
+
|
|
258
|
+
const stream = await navigator.mediaDevices.getUserMedia({
|
|
259
|
+
video: { facingMode: 'user' }
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
if (videoRef.current) {
|
|
263
|
+
client.initializeStreaming(stream, videoRef.current);
|
|
264
|
+
await client.startStreaming();
|
|
265
|
+
setIsScanning(true);
|
|
266
|
+
}
|
|
267
|
+
} catch (error) {
|
|
268
|
+
console.error('Failed to start scan:', error);
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
return (
|
|
273
|
+
<div>
|
|
274
|
+
<video ref={videoRef} autoPlay playsInline />
|
|
275
|
+
{heartRate && <p>Heart Rate: {heartRate} BPM</p>}
|
|
276
|
+
<p>{message}</p>
|
|
277
|
+
<button onClick={startScan} disabled={isScanning}>
|
|
278
|
+
{isScanning ? 'Scanning...' : 'Start Scan'}
|
|
279
|
+
</button>
|
|
280
|
+
</div>
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Vue 3 Composition API Example
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
<template>
|
|
289
|
+
<div>
|
|
290
|
+
<video ref="videoEl" autoplay playsinline></video>
|
|
291
|
+
<div v-if="metrics">
|
|
292
|
+
<p>Heart Rate: {{ metrics.heartRate }} BPM</p>
|
|
293
|
+
<p>Stress Level: {{ metrics.stressLevel }}</p>
|
|
294
|
+
</div>
|
|
295
|
+
</div>
|
|
296
|
+
</template>
|
|
120
297
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
298
|
+
<script setup lang="ts">
|
|
299
|
+
import { ref, onMounted, onUnmounted } from 'vue';
|
|
300
|
+
import { Client } from 'nervoscan-js-sdk';
|
|
301
|
+
|
|
302
|
+
const videoEl = ref<HTMLVideoElement>();
|
|
303
|
+
const metrics = ref(null);
|
|
304
|
+
|
|
305
|
+
const client = Client.getInstance();
|
|
306
|
+
|
|
307
|
+
onMounted(async () => {
|
|
308
|
+
await client.initialize(import.meta.env.VITE_NERVO_USER,
|
|
309
|
+
import.meta.env.VITE_NERVO_PASS);
|
|
310
|
+
|
|
311
|
+
client.setOnFinalResults((results) => {
|
|
312
|
+
metrics.value = results;
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
|
|
316
|
+
if (videoEl.value) {
|
|
317
|
+
client.initializeStreaming(stream, videoEl.value);
|
|
318
|
+
await client.startStreaming();
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
onUnmounted(() => {
|
|
323
|
+
client.stopStreaming();
|
|
324
|
+
});
|
|
325
|
+
</script>
|
|
326
|
+
```
|
|
124
327
|
|
|
125
328
|
---
|
|
126
329
|
|
|
127
|
-
##
|
|
330
|
+
## Requirements
|
|
128
331
|
|
|
129
|
-
|
|
332
|
+
- **Node.js**: v14 or higher
|
|
333
|
+
- **Browser Support**: Chrome 80+, Safari 14+, Firefox 78+, Edge 80+
|
|
334
|
+
- **Network**: Stable internet connection for streaming
|
|
335
|
+
- **Camera**: HD webcam (720p or higher recommended)
|
|
336
|
+
- **NervoScan Account**: Valid credentials with active subscription
|
|
130
337
|
|
|
131
338
|
---
|
|
132
339
|
|
|
133
|
-
##
|
|
340
|
+
## TypeScript Support
|
|
341
|
+
|
|
342
|
+
The SDK is written in TypeScript and includes comprehensive type definitions:
|
|
343
|
+
|
|
344
|
+
```typescript
|
|
345
|
+
import { Client, Errors, NervoscanError } from 'nervoscan-js-sdk';
|
|
346
|
+
|
|
347
|
+
// All methods are fully typed
|
|
348
|
+
const client: Client = Client.getInstance();
|
|
349
|
+
|
|
350
|
+
// Error types are available
|
|
351
|
+
function handleError(error: unknown) {
|
|
352
|
+
if (error instanceof NervoscanError) {
|
|
353
|
+
// Handle NervoScan specific errors
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
---
|
|
134
359
|
|
|
135
|
-
Built and maintained by the NervoScan
|
|
360
|
+
Built and maintained by the NervoScan team
|
package/dist/nervoscan-js-sdk.js
CHANGED
|
@@ -1581,7 +1581,7 @@ FIREBASE: `))}restoreState_(){this.tryAuth(),this.tryAppCheck();for(const e of t
|
|
|
1581
1581
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
1582
1582
|
* See the License for the specific language governing permissions and
|
|
1583
1583
|
* limitations under the License.
|
|
1584
|
-
*/function R_(n){Ed(ad),rn(new yt("database",(e,{instanceIdentifier:t})=>{const s=e.getProvider("app").getImmediate(),r=e.getProvider("auth-internal"),i=e.getProvider("app-check-internal");return v_(s,r,i,t)},"PUBLIC").setMultipleInstances(!0)),$e(Qr,Jr,n),$e(Qr,Jr,"esm2017")}fe.prototype.simpleListen=function(n,e){this.sendRequest("q",{p:n},e)};fe.prototype.echo=function(n,e){this.sendRequest("echo",{d:n},e)};R_();const Mn=n=>n==="server"?"https://backend.nervoscan.com":"https://backendv2-dev.nervoscan.com",Ne=class Ne{constructor(){k(this,"socket");k(this,"backendUrl",Mn("server"));k(this,"videoStream");k(this,"videoElement");k(this,"isConnected",!1);k(this,"isStreaming",!1);k(this,"jobId");k(this,"onDisconnection");k(this,"playHandler",()=>{if(!this.videoElement)return;const e=document.createElement("canvas");e.width=this.videoElement.videoWidth,e.height=this.videoElement.videoHeight,this.captureAndSendFrame(e,this.videoElement)});k(this,"stopStreaming",()=>{this.isStreaming=!1,this.removePlayEventListener()})}static getInstance(){return Ne.instance||(Ne.instance=new Ne),Ne.instance}setupWebSocketConnection(){this.socket||(this.socket=Gt(this.backendUrl,{transports:["websocket","polling"]}),this.socket.on("connect",()=>{this.isConnected=!0}),this.socket.on("connect_error",e=>this.handleSocketError(e)),this.socket.on("disconnect",e=>this.handleSocketDisconnection(e)))}handleSocketError(e){console.error("Connection error:",e)}handleSocketDisconnection(e){console.warn("Disconnected from WebSocket server:",e)}initializeStreaming(e,t){this.setupWebSocketConnection(),this.videoStream=e,this.videoElement=t,this.videoElement.srcObject=e}startStreaming(e){var t;this.jobId=e,(t=this.socket)==null||t.emit("register",e),this.sendInitialRequest(e),this.isStreaming=!0,this.startVideoStream(),this.addDisconnectionListener()}async sendInitialRequest(e){await I.post(`${this.backendUrl}/react`,{username:e,uuid:e,device_id:"1234567",face_detector:"BlazefaceFacemesh",motion_tracking:!0,skin_segmentor:"HSVandYCrCbSkinSegmentation",extreme_pixel_removal:!1,gamma_value:1,eularian_color_magnification:!1},{headers:{"Content-Type":"application/json"}})}startVideoStream(){this.videoElement?(this.videoElement.addEventListener("play",this.playHandler),!this.videoElement.paused&&!this.videoElement.ended&&this.playHandler(),this.videoElement.play().then(()=>{}).catch(e=>console.error("Error starting video stream:",e))):console.error("Video stream not found when trying to start streaming")}captureAndSendFrame(e,t){const s=e.getContext("2d");if(!s)return;const r=()=>{this.isStreaming&&(!t.paused&&!t.ended&&(s.drawImage(t,0,0,640,480),this.sendFrameToBackend(e)),setTimeout(r,33))};r()}sendFrameToBackend(e){e.toBlob(t=>{if(!t)return;const s=new FileReader;s.onloadend=()=>{var r;if(this.isConnected&&this.isStreaming){const i=s.result;(r=this.socket)==null||r.emit("frame",i)}},s.readAsArrayBuffer(t)},"image/jpeg",.7)}removePlayEventListener(){this.videoElement&&this.videoElement.removeEventListener("play",this.playHandler)}setOnDisconnection(e){this.onDisconnection=e}addDisconnectionListener(){const e=Jt(),t=Qt(e,`${this.jobId}/disconnect`),s=ks(t,r=>{r.val()!=null&&(this.stopStreaming(),this.onDisconnection&&this.onDisconnection(),s())})}};k(Ne,"instance");let En=Ne;class uc{constructor(e,t){k(this,"backendUrl",Mn("server"));k(this,"username");k(this,"password");k(this,"streamingManager",En.getInstance());this.username=e,this.password=t}}class I_ extends uc{constructor(t,s){super(t,s);k(this,"streamingManager",En.getInstance());this.backendUrl=Mn("server")}async getToken(){try{return(await I.post(this.backendUrl.concat("/clientlogin"),{username:this.username,password:this.password})).data.access_token}catch(t){T.handleErrorResponse(t)}}async getAPIKey(t){t||T.throwKnownError(R.InvalidAccessTokenError);try{return(await I.post(this.backendUrl.concat("/clientgeturl"),{host_name:"www.nervoscan.com"},{headers:{Authorization:`Bearer ${t}`}})).data.url.split("?api_key=")[1]}catch(s){T.handleErrorResponse(s)}}async uploadVideoToServer(t,s,r){(!s||!r)&&T.throwKnownError(R.InvalidAccessTokenError);try{const i=new FormData;return i.append("file",t,"recording.webm"),i.append("data",JSON.stringify({uuid:r,meta_data:{}})),(await I.post(this.backendUrl.concat("/submitscan"),i,{headers:{"Content-Type":"multipart/form-data",Authorization:`Bearer ${s}`}})).data}catch(i){throw console.error("Error uploading video:",i),i.response?(console.error("Error response:",i.response.data),console.error("Error status:",i.response.status),console.error("Error headers:",i.response.headers)):i.request?console.error("Error request:",i.request):console.error("Error message:",i.message),i}}async getResults(t,s){var r;s||T.throwKnownError(R.InvalidAccessTokenError);try{const i=await I.post(this.backendUrl.concat("/getcustomerinfo"),{mode:"selection",api_keys:[t]},{headers:{Authorization:`Bearer ${s}`}});return((r=i.data)==null?void 0:r.success)===!1&&T.throwKnownError(R.NoScanDataError),i.data}catch(i){console.error("Error getting results:",i),T.handleErrorResponse(i)}}async checkResults(t,s){try{s||T.throwKnownError(R.InvalidAccessTokenError);const o=(await I.post(this.backendUrl.concat("/check"),{api_key:t},{headers:{Authorization:`Bearer ${s}`}})).data.job_status;return o==="Completed"||o==="Failed"?o:"Pending"}catch(r){T.handleErrorResponse(r)}}}class N_ extends uc{constructor(e,t){super(e,t),this.backendUrl=Mn("serverless")}async getToken(){try{const e=await I.post(this.backendUrl.concat("/user/login"),{username:this.username,password:this.password});if(e.data.success===!1)T.throwKnownError(R.InvalidUsernameError);else return JSON.parse(e.data.body).idToken}catch(e){console.error("error printed in serverless repository",e),T.handleErrorResponse(e)}}async getAPIKey(e){e||T.throwKnownError(R.InvalidAccessTokenError);try{return(await I.post(this.backendUrl.concat("/get-redirection-url"),{host_name:"www.nervoscan.com",username:this.username},{headers:{Authorization:`Bearer ${e}`}})).data.url.split("?api_key=")[1]}catch(t){T.handleErrorResponse(t)}}async uploadVideoToServer(e,t,s){(!t||!s)&&T.throwKnownError(R.InvalidAccessTokenError);try{const r=await this.generatePreSignedUrl(s);return r||T.throwKnownError(R.InvalidAccessTokenError),await this.uploadVideoToS3(e,r)}catch(r){throw console.error("Error uploading video:",r),r.response?(console.error("Error response:",r.response.data),console.error("Error status:",r.response.status),console.error("Error headers:",r.response.headers)):r.request?console.error("Error request:",r.request):console.error("Error message:",r.message),r}}getResults(e,t){return console.log("not implemented"),Promise.resolve(void 0)}async checkResults(e,t){try{t||T.throwKnownError(R.InvalidAccessTokenError);const i=(await I.post(this.backendUrl.concat("/check"),{api_key:e},{headers:{Authorization:`Bearer ${t}`}})).data.job_status;return i==="Completed"||i==="Failed"?i:"Pending"}catch(s){T.handleErrorResponse(s)}}async generatePreSignedUrl(e){try{return(await I.get(this.backendUrl.concat("/generate-presigned-url?job_id="+e))).data.upload_url}catch(t){T.handleErrorResponse(t)}}async uploadVideoToS3(e,t){try{return(await I.put(t,e,{headers:{"Content-Type":"video/mp4"}})).data}catch(s){T.handleErrorResponse(s)}}}var A_="firebase",k_="11.6.1";/**
|
|
1584
|
+
*/function R_(n){Ed(ad),rn(new yt("database",(e,{instanceIdentifier:t})=>{const s=e.getProvider("app").getImmediate(),r=e.getProvider("auth-internal"),i=e.getProvider("app-check-internal");return v_(s,r,i,t)},"PUBLIC").setMultipleInstances(!0)),$e(Qr,Jr,n),$e(Qr,Jr,"esm2017")}fe.prototype.simpleListen=function(n,e){this.sendRequest("q",{p:n},e)};fe.prototype.echo=function(n,e){this.sendRequest("echo",{d:n},e)};R_();const Mn=n=>n==="server"?"https://backend.nervoscan.com":"https://backendv2-dev.nervoscan.com",Ne=class Ne{constructor(){k(this,"socket");k(this,"backendUrl",Mn("server"));k(this,"videoStream");k(this,"videoElement");k(this,"isConnected",!1);k(this,"isStreaming",!1);k(this,"jobId");k(this,"onDisconnection");k(this,"playHandler",()=>{if(!this.videoElement)return;const e=document.createElement("canvas");e.width=this.videoElement.videoWidth,e.height=this.videoElement.videoHeight,this.captureAndSendFrame(e,this.videoElement)});k(this,"stopStreaming",()=>{this.isStreaming=!1,this.removePlayEventListener()})}static getInstance(){return Ne.instance||(Ne.instance=new Ne),Ne.instance}setupWebSocketConnection(){this.socket||(console.log("Setting up WebSocket connection:",this.backendUrl),this.socket=Gt(this.backendUrl,{transports:["websocket","polling"]}),this.socket.on("connect",()=>{this.isConnected=!0}),this.socket.on("connect_error",e=>this.handleSocketError(e)),this.socket.on("disconnect",e=>this.handleSocketDisconnection(e)))}handleSocketError(e){console.error("Connection error:",e)}handleSocketDisconnection(e){console.warn("Disconnected from WebSocket server:",e)}initializeStreaming(e,t){console.log("Initializing streaming"),this.setupWebSocketConnection(),this.videoStream=e,this.videoElement=t,this.videoElement.srcObject=e}startStreaming(e){var t;this.jobId=e,(t=this.socket)==null||t.emit("register",e),this.sendInitialRequest(e),this.isStreaming=!0,this.startVideoStream(),this.addDisconnectionListener()}async sendInitialRequest(e){await I.post(`${this.backendUrl}/react`,{username:e,uuid:e,device_id:"1234567",face_detector:"BlazefaceFacemesh",motion_tracking:!0,skin_segmentor:"HSVandYCrCbSkinSegmentation",extreme_pixel_removal:!1,gamma_value:1,eularian_color_magnification:!1},{headers:{"Content-Type":"application/json"}})}startVideoStream(){this.videoElement?(this.videoElement.addEventListener("play",this.playHandler),!this.videoElement.paused&&!this.videoElement.ended&&this.playHandler(),this.videoElement.play().then(()=>{}).catch(e=>console.error("Error starting video stream:",e))):console.error("Video stream not found when trying to start streaming")}captureAndSendFrame(e,t){const s=e.getContext("2d");if(!s)return;const r=()=>{this.isStreaming&&(!t.paused&&!t.ended&&(s.drawImage(t,0,0,640,480),this.sendFrameToBackend(e)),setTimeout(r,33))};r()}sendFrameToBackend(e){e.toBlob(t=>{if(!t)return;const s=new FileReader;s.onloadend=()=>{var r;if(this.isConnected&&this.isStreaming){const i=s.result;(r=this.socket)==null||r.emit("frame",i)}},s.readAsArrayBuffer(t)},"image/jpeg",.7)}removePlayEventListener(){this.videoElement&&this.videoElement.removeEventListener("play",this.playHandler)}setOnDisconnection(e){this.onDisconnection=e}addDisconnectionListener(){const e=Jt(),t=Qt(e,`${this.jobId}/disconnect`),s=ks(t,r=>{r.val()!=null&&(this.stopStreaming(),this.onDisconnection&&this.onDisconnection(),s())})}};k(Ne,"instance");let En=Ne;class uc{constructor(e,t){k(this,"backendUrl",Mn("server"));k(this,"username");k(this,"password");k(this,"streamingManager",En.getInstance());this.username=e,this.password=t}}class I_ extends uc{constructor(t,s){super(t,s);k(this,"streamingManager",En.getInstance());this.backendUrl=Mn("server")}async getToken(){try{return(await I.post(this.backendUrl.concat("/clientlogin"),{username:this.username,password:this.password})).data.access_token}catch(t){T.handleErrorResponse(t)}}async getAPIKey(t){t||T.throwKnownError(R.InvalidAccessTokenError);try{return(await I.post(this.backendUrl.concat("/clientgeturl"),{host_name:"www.nervoscan.com"},{headers:{Authorization:`Bearer ${t}`}})).data.url.split("?api_key=")[1]}catch(s){T.handleErrorResponse(s)}}async uploadVideoToServer(t,s,r){(!s||!r)&&T.throwKnownError(R.InvalidAccessTokenError);try{const i=new FormData;return i.append("file",t,"recording.webm"),i.append("data",JSON.stringify({uuid:r,meta_data:{}})),(await I.post(this.backendUrl.concat("/submitscan"),i,{headers:{"Content-Type":"multipart/form-data",Authorization:`Bearer ${s}`}})).data}catch(i){throw console.error("Error uploading video:",i),i.response?(console.error("Error response:",i.response.data),console.error("Error status:",i.response.status),console.error("Error headers:",i.response.headers)):i.request?console.error("Error request:",i.request):console.error("Error message:",i.message),i}}async getResults(t,s){var r;s||T.throwKnownError(R.InvalidAccessTokenError);try{const i=await I.post(this.backendUrl.concat("/getcustomerinfo"),{mode:"selection",api_keys:[t]},{headers:{Authorization:`Bearer ${s}`}});return((r=i.data)==null?void 0:r.success)===!1&&T.throwKnownError(R.NoScanDataError),i.data}catch(i){console.error("Error getting results:",i),T.handleErrorResponse(i)}}async checkResults(t,s){try{s||T.throwKnownError(R.InvalidAccessTokenError);const o=(await I.post(this.backendUrl.concat("/check"),{api_key:t},{headers:{Authorization:`Bearer ${s}`}})).data.job_status;return o==="Completed"||o==="Failed"?o:"Pending"}catch(r){T.handleErrorResponse(r)}}}class N_ extends uc{constructor(e,t){super(e,t),this.backendUrl=Mn("serverless")}async getToken(){try{const e=await I.post(this.backendUrl.concat("/user/login"),{username:this.username,password:this.password});if(e.data.success===!1)T.throwKnownError(R.InvalidUsernameError);else return JSON.parse(e.data.body).idToken}catch(e){console.error("error printed in serverless repository",e),T.handleErrorResponse(e)}}async getAPIKey(e){e||T.throwKnownError(R.InvalidAccessTokenError);try{return(await I.post(this.backendUrl.concat("/get-redirection-url"),{host_name:"www.nervoscan.com",username:this.username},{headers:{Authorization:`Bearer ${e}`}})).data.url.split("?api_key=")[1]}catch(t){T.handleErrorResponse(t)}}async uploadVideoToServer(e,t,s){(!t||!s)&&T.throwKnownError(R.InvalidAccessTokenError);try{const r=await this.generatePreSignedUrl(s);return r||T.throwKnownError(R.InvalidAccessTokenError),await this.uploadVideoToS3(e,r)}catch(r){throw console.error("Error uploading video:",r),r.response?(console.error("Error response:",r.response.data),console.error("Error status:",r.response.status),console.error("Error headers:",r.response.headers)):r.request?console.error("Error request:",r.request):console.error("Error message:",r.message),r}}getResults(e,t){return console.log("not implemented"),Promise.resolve(void 0)}async checkResults(e,t){try{t||T.throwKnownError(R.InvalidAccessTokenError);const i=(await I.post(this.backendUrl.concat("/check"),{api_key:e},{headers:{Authorization:`Bearer ${t}`}})).data.job_status;return i==="Completed"||i==="Failed"?i:"Pending"}catch(s){T.handleErrorResponse(s)}}async generatePreSignedUrl(e){try{return(await I.get(this.backendUrl.concat("/generate-presigned-url?job_id="+e))).data.upload_url}catch(t){T.handleErrorResponse(t)}}async uploadVideoToS3(e,t){try{return(await I.put(t,e,{headers:{"Content-Type":"video/mp4"}})).data}catch(s){T.handleErrorResponse(s)}}}var A_="firebase",k_="11.6.1";/**
|
|
1585
1585
|
* @license
|
|
1586
1586
|
* Copyright 2020 Google LLC
|
|
1587
1587
|
*
|
|
@@ -1596,4 +1596,4 @@ FIREBASE: `))}restoreState_(){this.tryAuth(),this.tryAppCheck();for(const e of t
|
|
|
1596
1596
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
1597
1597
|
* See the License for the specific language governing permissions and
|
|
1598
1598
|
* limitations under the License.
|
|
1599
|
-
*/$e(A_,k_,"app");const Ae=class Ae{constructor(){k(this,"initialized",!1);k(this,"accessToken");k(this,"backendRepository");k(this,"onWindowResults");k(this,"onFinalResults");k(this,"onError");k(this,"firebaseHandlers",[]);zo({apiKey:"AIzaSyAoOpQqLrc6wQLJI5KRE2Vt7QV1cplsZv8",authDomain:"nervowebreact.firebaseapp.com",databaseURL:"https://nervowebreact-default-rtdb.asia-southeast1.firebasedatabase.app",projectId:"nervowebreact",storageBucket:"nervowebreact.firebasestorage.app",messagingSenderId:"1025695568936",appId:"1:1025695568936:web:36f269a1eb74e1fdda511d",measurementId:"G-L3105FG92S"})}static getInstance(){return Ae.instance||(Ae.instance=new Ae),Ae.instance}initialize(e,t,s="server"){this.initialized=!0,s==="server"?this.backendRepository=new I_(e,t):s==="serverless"?this.backendRepository=new N_(e,t):T.throwKnownError(R.InvalidServerTypeError)}async uploadVideo(e){var r,i,o;this.initialized||T.throwKnownError(R.NotInitializedError),e instanceof Blob||T.throwKnownError(R.VideoTypeError),(e===null||e.size===0)&&T.throwKnownError(R.EmptyVideoError);const t=await((r=this.backendRepository)==null?void 0:r.getToken()),s=await((i=this.backendRepository)==null?void 0:i.getAPIKey(t));return(o=this.backendRepository)==null||o.uploadVideoToServer(e,t,s),s&&this.addfirebaseListeners(s),s}async checkResults(e){var t,s;console.warn("Warning: checkResults() is deprecated and will be removed in a future version. Use setOnWindowResults() and setOnFinalResults() instead!"),this.initialized||T.throwKnownError(R.NotInitializedError);try{return this.accessToken||(this.accessToken=await((t=this.backendRepository)==null?void 0:t.getToken())),await((s=this.backendRepository)==null?void 0:s.checkResults(e,this.accessToken))}catch(r){T.handleErrorResponse(r)}}async getResults(e){var s,r;return console.warn("Warning: getResults() is deprecated and will be removed in a future version. Use setOnWindowResults() and setOnFinalResults() instead!"),this.initialized||T.throwKnownError(R.NotInitializedError),this.accessToken||(this.accessToken=await((s=this.backendRepository)==null?void 0:s.getToken())),await((r=this.backendRepository)==null?void 0:r.getResults(e,this.accessToken))}setOnWindowResults(e){this.onWindowResults=e}setOnFinalResults(e){this.onFinalResults=e}setOnError(e){this.onError=e}setOnDisconnection(e){var t;(t=this.backendRepository)==null||t.streamingManager.setOnDisconnection(e)}async addfirebaseListeners(e){this.addWindowListener(e),this.addFinalListener(e),this.addErrorListener(e)}addWindowListener(e){const t=Jt(),s=Qt(t,`${e}`),r=g_(s,i=>{i.val()!==null&&i.key&&/^\d+$/.test(i.key)&&this.onWindowResults&&this.onWindowResults(i.val())});this.firebaseHandlers.push(r)}removefirebaseListeners(){this.firebaseHandlers.forEach(e=>{e()}),this.firebaseHandlers=[]}addFinalListener(e){const t=Jt(),s=Qt(t,`/${e}/averaged_results/`),r=ks(s,i=>{i.val()!==null&&(this.onFinalResults&&this.onFinalResults(i.val()),this.removefirebaseListeners())});this.firebaseHandlers.push(r)}addErrorListener(e){const t=Jt(),s=Qt(t,`/${e}/error/`),r=ks(s,i=>{if(i.val()===null)return;const o=T.handleScanError(i.val());this.onError?this.onError(o):T.throwKnownError(R.ErrorCallbackNotSetError),this.removefirebaseListeners()});this.firebaseHandlers.push(r)}
|
|
1599
|
+
*/$e(A_,k_,"app");const Ae=class Ae{constructor(){k(this,"initialized",!1);k(this,"accessToken");k(this,"backendRepository");k(this,"onWindowResults");k(this,"onFinalResults");k(this,"onError");k(this,"firebaseHandlers",[]);console.log("Initializing Client"),zo({apiKey:"AIzaSyAoOpQqLrc6wQLJI5KRE2Vt7QV1cplsZv8",authDomain:"nervowebreact.firebaseapp.com",databaseURL:"https://nervowebreact-default-rtdb.asia-southeast1.firebasedatabase.app",projectId:"nervowebreact",storageBucket:"nervowebreact.firebasestorage.app",messagingSenderId:"1025695568936",appId:"1:1025695568936:web:36f269a1eb74e1fdda511d",measurementId:"G-L3105FG92S"})}static getInstance(){return Ae.instance||(Ae.instance=new Ae),Ae.instance}initialize(e,t,s="server"){this.initialized=!0,s==="server"?this.backendRepository=new I_(e,t):s==="serverless"?this.backendRepository=new N_(e,t):T.throwKnownError(R.InvalidServerTypeError)}async uploadVideo(e){var r,i,o;this.initialized||T.throwKnownError(R.NotInitializedError),e instanceof Blob||T.throwKnownError(R.VideoTypeError),(e===null||e.size===0)&&T.throwKnownError(R.EmptyVideoError);const t=await((r=this.backendRepository)==null?void 0:r.getToken()),s=await((i=this.backendRepository)==null?void 0:i.getAPIKey(t));return(o=this.backendRepository)==null||o.uploadVideoToServer(e,t,s),s&&this.addfirebaseListeners(s),s}async checkResults(e){var t,s;console.warn("Warning: checkResults() is deprecated and will be removed in a future version. Use setOnWindowResults() and setOnFinalResults() instead!"),this.initialized||T.throwKnownError(R.NotInitializedError);try{return this.accessToken||(this.accessToken=await((t=this.backendRepository)==null?void 0:t.getToken())),await((s=this.backendRepository)==null?void 0:s.checkResults(e,this.accessToken))}catch(r){T.handleErrorResponse(r)}}async getResults(e){var s,r;return console.warn("Warning: getResults() is deprecated and will be removed in a future version. Use setOnWindowResults() and setOnFinalResults() instead!"),this.initialized||T.throwKnownError(R.NotInitializedError),this.accessToken||(this.accessToken=await((s=this.backendRepository)==null?void 0:s.getToken())),await((r=this.backendRepository)==null?void 0:r.getResults(e,this.accessToken))}setOnWindowResults(e){this.onWindowResults=e}setOnFinalResults(e){this.onFinalResults=e}setOnError(e){this.onError=e}setOnDisconnection(e){var t;(t=this.backendRepository)==null||t.streamingManager.setOnDisconnection(e)}initializeStreaming(e,t){var s;(s=this.backendRepository)==null||s.streamingManager.initializeStreaming(e,t)}async startStreaming(){var s,r,i;this.initialized||T.throwKnownError(R.NotInitializedError);const e=await((s=this.backendRepository)==null?void 0:s.getToken()),t=await((r=this.backendRepository)==null?void 0:r.getAPIKey(e));if(t)return(i=this.backendRepository)==null||i.streamingManager.startStreaming(t),this.addfirebaseListeners(t),t;T.throwKnownError(R.InvalidAccessTokenError)}stopStreaming(){var e;(e=this.backendRepository)==null||e.streamingManager.stopStreaming()}async addfirebaseListeners(e){this.addWindowListener(e),this.addFinalListener(e),this.addErrorListener(e)}addWindowListener(e){const t=Jt(),s=Qt(t,`${e}`),r=g_(s,i=>{i.val()!==null&&i.key&&/^\d+$/.test(i.key)&&this.onWindowResults&&this.onWindowResults(i.val())});this.firebaseHandlers.push(r)}removefirebaseListeners(){this.firebaseHandlers.forEach(e=>{e()}),this.firebaseHandlers=[]}addFinalListener(e){const t=Jt(),s=Qt(t,`/${e}/averaged_results/`),r=ks(s,i=>{i.val()!==null&&(this.onFinalResults&&this.onFinalResults(i.val()),this.removefirebaseListeners())});this.firebaseHandlers.push(r)}addErrorListener(e){const t=Jt(),s=Qt(t,`/${e}/error/`),r=ks(s,i=>{if(i.val()===null)return;const o=T.handleScanError(i.val());this.onError?this.onError(o):T.throwKnownError(R.ErrorCallbackNotSetError),this.removefirebaseListeners()});this.firebaseHandlers.push(r)}};k(Ae,"instance");let xs=Ae;exports.Client=xs;exports.EmptyVideoError=Oi;exports.ErrorCallbackNotSetError=Ki;exports.Errors=q;exports.FPSCalculationError=Wi;exports.FaceLookingLeftError=zi;exports.FaceLookingRightError=ji;exports.FaceNotCenteredError=Hi;exports.FaceTooCloseError=$i;exports.FaceTooFarError=Vi;exports.InvalidAccessTokenError=Fi;exports.InvalidPasswordError=Di;exports.InvalidServerTypeError=Bi;exports.InvalidUsernameError=Pi;exports.LowFPSError=qi;exports.NervoscanError=U;exports.NoScanDataError=Mi;exports.NoScansAvailableError=Li;exports.NotImplementedError=Ui;exports.NotInitializedError=ki;exports.UnhandledScanError=Ps;exports.VideoTypeError=xi;
|
|
@@ -12710,7 +12710,7 @@ const Mn = (n) => n === "server" ? "https://backend.nervoscan.com" : "https://ba
|
|
|
12710
12710
|
return Ne.instance || (Ne.instance = new Ne()), Ne.instance;
|
|
12711
12711
|
}
|
|
12712
12712
|
setupWebSocketConnection() {
|
|
12713
|
-
this.socket || (this.socket = Gt(this.backendUrl, { transports: ["websocket", "polling"] }), this.socket.on("connect", () => {
|
|
12713
|
+
this.socket || (console.log("Setting up WebSocket connection:", this.backendUrl), this.socket = Gt(this.backendUrl, { transports: ["websocket", "polling"] }), this.socket.on("connect", () => {
|
|
12714
12714
|
this.isConnected = !0;
|
|
12715
12715
|
}), this.socket.on("connect_error", (e) => this.handleSocketError(e)), this.socket.on("disconnect", (e) => this.handleSocketDisconnection(e)));
|
|
12716
12716
|
}
|
|
@@ -12721,7 +12721,7 @@ const Mn = (n) => n === "server" ? "https://backend.nervoscan.com" : "https://ba
|
|
|
12721
12721
|
console.warn("Disconnected from WebSocket server:", e);
|
|
12722
12722
|
}
|
|
12723
12723
|
initializeStreaming(e, t) {
|
|
12724
|
-
this.setupWebSocketConnection(), this.videoStream = e, this.videoElement = t, this.videoElement.srcObject = e;
|
|
12724
|
+
console.log("Initializing streaming"), this.setupWebSocketConnection(), this.videoStream = e, this.videoElement = t, this.videoElement.srcObject = e;
|
|
12725
12725
|
}
|
|
12726
12726
|
startStreaming(e) {
|
|
12727
12727
|
var t;
|
|
@@ -12971,7 +12971,7 @@ const Ae = class Ae {
|
|
|
12971
12971
|
k(this, "onFinalResults");
|
|
12972
12972
|
k(this, "onError");
|
|
12973
12973
|
k(this, "firebaseHandlers", []);
|
|
12974
|
-
Io({
|
|
12974
|
+
console.log("Initializing Client"), Io({
|
|
12975
12975
|
apiKey: "AIzaSyAoOpQqLrc6wQLJI5KRE2Vt7QV1cplsZv8",
|
|
12976
12976
|
authDomain: "nervowebreact.firebaseapp.com",
|
|
12977
12977
|
databaseURL: "https://nervowebreact-default-rtdb.asia-southeast1.firebasedatabase.app",
|
|
@@ -13073,39 +13073,14 @@ const Ae = class Ae {
|
|
|
13073
13073
|
setOnError(e) {
|
|
13074
13074
|
this.onError = e;
|
|
13075
13075
|
}
|
|
13076
|
+
/**
|
|
13077
|
+
* Sets a callback function to handle disconnection.
|
|
13078
|
+
* @param callback - Function to be called when the connection is lost. Takes no parameters.
|
|
13079
|
+
*/
|
|
13076
13080
|
setOnDisconnection(e) {
|
|
13077
13081
|
var t;
|
|
13078
13082
|
(t = this.backendRepository) == null || t.streamingManager.setOnDisconnection(e);
|
|
13079
13083
|
}
|
|
13080
|
-
async addfirebaseListeners(e) {
|
|
13081
|
-
this.addWindowListener(e), this.addFinalListener(e), this.addErrorListener(e);
|
|
13082
|
-
}
|
|
13083
|
-
addWindowListener(e) {
|
|
13084
|
-
const t = Jt(), s = Qt(t, `${e}`), i = g_(s, (r) => {
|
|
13085
|
-
r.val() !== null && r.key && /^\d+$/.test(r.key) && this.onWindowResults && this.onWindowResults(r.val());
|
|
13086
|
-
});
|
|
13087
|
-
this.firebaseHandlers.push(i);
|
|
13088
|
-
}
|
|
13089
|
-
removefirebaseListeners() {
|
|
13090
|
-
this.firebaseHandlers.forEach((e) => {
|
|
13091
|
-
e();
|
|
13092
|
-
}), this.firebaseHandlers = [];
|
|
13093
|
-
}
|
|
13094
|
-
addFinalListener(e) {
|
|
13095
|
-
const t = Jt(), s = Qt(t, `/${e}/averaged_results/`), i = ks(s, (r) => {
|
|
13096
|
-
r.val() !== null && (this.onFinalResults && this.onFinalResults(r.val()), this.removefirebaseListeners());
|
|
13097
|
-
});
|
|
13098
|
-
this.firebaseHandlers.push(i);
|
|
13099
|
-
}
|
|
13100
|
-
addErrorListener(e) {
|
|
13101
|
-
const t = Jt(), s = Qt(t, `/${e}/error/`), i = ks(s, (r) => {
|
|
13102
|
-
if (r.val() === null)
|
|
13103
|
-
return;
|
|
13104
|
-
const o = T.handleScanError(r.val());
|
|
13105
|
-
this.onError ? this.onError(o) : T.throwKnownError(R.ErrorCallbackNotSetError), this.removefirebaseListeners();
|
|
13106
|
-
});
|
|
13107
|
-
this.firebaseHandlers.push(i);
|
|
13108
|
-
}
|
|
13109
13084
|
/**
|
|
13110
13085
|
* Initializes the streaming manager.
|
|
13111
13086
|
* @param videoStream - The video stream to stream
|
|
@@ -13138,6 +13113,35 @@ const Ae = class Ae {
|
|
|
13138
13113
|
var e;
|
|
13139
13114
|
(e = this.backendRepository) == null || e.streamingManager.stopStreaming();
|
|
13140
13115
|
}
|
|
13116
|
+
async addfirebaseListeners(e) {
|
|
13117
|
+
this.addWindowListener(e), this.addFinalListener(e), this.addErrorListener(e);
|
|
13118
|
+
}
|
|
13119
|
+
addWindowListener(e) {
|
|
13120
|
+
const t = Jt(), s = Qt(t, `${e}`), i = g_(s, (r) => {
|
|
13121
|
+
r.val() !== null && r.key && /^\d+$/.test(r.key) && this.onWindowResults && this.onWindowResults(r.val());
|
|
13122
|
+
});
|
|
13123
|
+
this.firebaseHandlers.push(i);
|
|
13124
|
+
}
|
|
13125
|
+
removefirebaseListeners() {
|
|
13126
|
+
this.firebaseHandlers.forEach((e) => {
|
|
13127
|
+
e();
|
|
13128
|
+
}), this.firebaseHandlers = [];
|
|
13129
|
+
}
|
|
13130
|
+
addFinalListener(e) {
|
|
13131
|
+
const t = Jt(), s = Qt(t, `/${e}/averaged_results/`), i = ks(s, (r) => {
|
|
13132
|
+
r.val() !== null && (this.onFinalResults && this.onFinalResults(r.val()), this.removefirebaseListeners());
|
|
13133
|
+
});
|
|
13134
|
+
this.firebaseHandlers.push(i);
|
|
13135
|
+
}
|
|
13136
|
+
addErrorListener(e) {
|
|
13137
|
+
const t = Jt(), s = Qt(t, `/${e}/error/`), i = ks(s, (r) => {
|
|
13138
|
+
if (r.val() === null)
|
|
13139
|
+
return;
|
|
13140
|
+
const o = T.handleScanError(r.val());
|
|
13141
|
+
this.onError ? this.onError(o) : T.throwKnownError(R.ErrorCallbackNotSetError), this.removefirebaseListeners();
|
|
13142
|
+
});
|
|
13143
|
+
this.firebaseHandlers.push(i);
|
|
13144
|
+
}
|
|
13141
13145
|
};
|
|
13142
13146
|
k(Ae, "instance");
|
|
13143
13147
|
let Nr = Ae;
|