dashcam 1.3.13-beta → 1.3.15-beta
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/bin/dashcam-background.js +32 -4
- package/bin/dashcam.js +90 -9
- package/lib/processManager.js +131 -16
- package/lib/uploader.js +41 -7
- package/package.json +1 -1
|
@@ -36,13 +36,41 @@ logger.info('Background recording process started', {
|
|
|
36
36
|
// Write status file
|
|
37
37
|
function writeStatus(status) {
|
|
38
38
|
try {
|
|
39
|
-
|
|
39
|
+
const statusData = {
|
|
40
40
|
...status,
|
|
41
41
|
timestamp: Date.now(),
|
|
42
|
-
pid: process.pid
|
|
43
|
-
|
|
42
|
+
pid: process.pid,
|
|
43
|
+
platform: process.platform
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
logger.debug('Background process writing status file', {
|
|
47
|
+
statusFile: STATUS_FILE,
|
|
48
|
+
pid: statusData.pid,
|
|
49
|
+
isRecording: statusData.isRecording,
|
|
50
|
+
platform: statusData.platform
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
fs.writeFileSync(STATUS_FILE, JSON.stringify(statusData, null, 2));
|
|
54
|
+
|
|
55
|
+
// Verify it was written
|
|
56
|
+
if (fs.existsSync(STATUS_FILE)) {
|
|
57
|
+
logger.debug('Status file written and verified', { statusFile: STATUS_FILE });
|
|
58
|
+
|
|
59
|
+
// Read it back to verify content
|
|
60
|
+
const writtenContent = fs.readFileSync(STATUS_FILE, 'utf8');
|
|
61
|
+
logger.debug('Status file content verification', {
|
|
62
|
+
contentLength: writtenContent.length,
|
|
63
|
+
parseable: true
|
|
64
|
+
});
|
|
65
|
+
} else {
|
|
66
|
+
logger.error('Status file does not exist after write!', { statusFile: STATUS_FILE });
|
|
67
|
+
}
|
|
44
68
|
} catch (error) {
|
|
45
|
-
logger.error('Failed to write status file', {
|
|
69
|
+
logger.error('Failed to write status file in background process', {
|
|
70
|
+
error: error.message,
|
|
71
|
+
stack: error.stack,
|
|
72
|
+
statusFile: STATUS_FILE
|
|
73
|
+
});
|
|
46
74
|
}
|
|
47
75
|
}
|
|
48
76
|
|
package/bin/dashcam.js
CHANGED
|
@@ -395,8 +395,39 @@ program
|
|
|
395
395
|
// Enable verbose logging for stop command
|
|
396
396
|
setVerbose(true);
|
|
397
397
|
|
|
398
|
-
|
|
398
|
+
logger.debug('Stop command invoked', {
|
|
399
|
+
platform: process.platform,
|
|
400
|
+
cwd: process.cwd(),
|
|
401
|
+
pid: process.pid,
|
|
402
|
+
processDir: require('os').homedir() + '/.dashcam-cli'
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
const isActive = processManager.isRecordingActive();
|
|
406
|
+
logger.debug('Recording active check result', { isActive });
|
|
407
|
+
|
|
408
|
+
if (!isActive) {
|
|
399
409
|
console.log('No active recording to stop');
|
|
410
|
+
logger.warn('Stop command called but no active recording found', {
|
|
411
|
+
platform: process.platform,
|
|
412
|
+
statusFile: require('path').join(require('os').homedir(), '.dashcam-cli', 'status.json'),
|
|
413
|
+
statusFileExists: require('fs').existsSync(require('path').join(require('os').homedir(), '.dashcam-cli', 'status.json'))
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
// Try to read and display status file for debugging
|
|
417
|
+
try {
|
|
418
|
+
const statusPath = require('path').join(require('os').homedir(), '.dashcam-cli', 'status.json');
|
|
419
|
+
if (require('fs').existsSync(statusPath)) {
|
|
420
|
+
const statusContent = require('fs').readFileSync(statusPath, 'utf8');
|
|
421
|
+
logger.debug('Status file contents', { content: statusContent });
|
|
422
|
+
console.log('Status file exists but recording not detected as active');
|
|
423
|
+
console.log('Status file location:', statusPath);
|
|
424
|
+
} else {
|
|
425
|
+
console.log('Status file does not exist');
|
|
426
|
+
}
|
|
427
|
+
} catch (err) {
|
|
428
|
+
logger.error('Failed to read status file for debugging', { error: err.message });
|
|
429
|
+
}
|
|
430
|
+
|
|
400
431
|
process.exit(0);
|
|
401
432
|
}
|
|
402
433
|
|
|
@@ -404,55 +435,94 @@ program
|
|
|
404
435
|
const logFile = path.join(process.cwd(), '.dashcam', 'recording.log');
|
|
405
436
|
|
|
406
437
|
console.log('Stopping recording...');
|
|
438
|
+
logger.debug('Active status before stop:', activeStatus);
|
|
407
439
|
|
|
408
440
|
try {
|
|
441
|
+
logger.debug('Calling stopActiveRecording...');
|
|
409
442
|
const result = await processManager.stopActiveRecording();
|
|
410
443
|
|
|
411
444
|
if (!result) {
|
|
412
445
|
console.log('Failed to stop recording');
|
|
446
|
+
logger.error('stopActiveRecording returned null/false');
|
|
413
447
|
process.exit(1);
|
|
414
448
|
}
|
|
415
449
|
|
|
416
450
|
console.log('Recording stopped successfully');
|
|
451
|
+
logger.debug('Stop result:', result);
|
|
417
452
|
|
|
418
453
|
// Wait for upload to complete (background process handles this)
|
|
419
454
|
logger.debug('Waiting for background upload to complete...');
|
|
420
|
-
console.log('
|
|
455
|
+
console.log('Checking if background process uploaded...');
|
|
421
456
|
|
|
422
457
|
// Wait up to 2 minutes for upload result to appear
|
|
423
458
|
const maxWaitForUpload = 120000; // 2 minutes
|
|
424
459
|
const startWaitForUpload = Date.now();
|
|
425
460
|
let uploadResult = null;
|
|
461
|
+
let checkCount = 0;
|
|
426
462
|
|
|
427
463
|
while (!uploadResult && (Date.now() - startWaitForUpload) < maxWaitForUpload) {
|
|
428
464
|
uploadResult = processManager.readUploadResult();
|
|
465
|
+
checkCount++;
|
|
466
|
+
|
|
429
467
|
if (!uploadResult) {
|
|
468
|
+
// Log every 10 seconds to show progress
|
|
469
|
+
if (checkCount % 10 === 0) {
|
|
470
|
+
const elapsed = Math.round((Date.now() - startWaitForUpload) / 1000);
|
|
471
|
+
logger.debug(`Still waiting for background upload... (${elapsed}s elapsed)`);
|
|
472
|
+
console.log(`Waiting for background upload... (${elapsed}s)`);
|
|
473
|
+
}
|
|
430
474
|
await new Promise(resolve => setTimeout(resolve, 1000)); // Check every second
|
|
431
475
|
}
|
|
432
476
|
}
|
|
433
477
|
|
|
434
|
-
logger.debug('Upload result read attempt', {
|
|
478
|
+
logger.debug('Upload result read attempt', {
|
|
479
|
+
found: !!uploadResult,
|
|
480
|
+
shareLink: uploadResult?.shareLink,
|
|
481
|
+
checksPerformed: checkCount,
|
|
482
|
+
timeElapsed: Math.round((Date.now() - startWaitForUpload) / 1000) + 's'
|
|
483
|
+
});
|
|
435
484
|
|
|
436
485
|
if (uploadResult && uploadResult.shareLink) {
|
|
437
486
|
console.log('Watch your recording:', uploadResult.shareLink);
|
|
487
|
+
logger.info('Background process upload succeeded');
|
|
438
488
|
// Clean up the result file now that we've read it
|
|
439
489
|
processManager.cleanup();
|
|
440
490
|
process.exit(0);
|
|
441
491
|
}
|
|
442
492
|
|
|
493
|
+
logger.debug('No upload result from background process, checking files...');
|
|
494
|
+
|
|
443
495
|
// Check if files still exist - if not, background process already uploaded
|
|
444
|
-
const
|
|
445
|
-
|
|
446
|
-
|
|
496
|
+
const videoExists = fs.existsSync(result.outputPath);
|
|
497
|
+
const gifExists = !result.gifPath || fs.existsSync(result.gifPath);
|
|
498
|
+
const snapshotExists = !result.snapshotPath || fs.existsSync(result.snapshotPath);
|
|
499
|
+
|
|
500
|
+
logger.debug('File existence check:', {
|
|
501
|
+
video: videoExists,
|
|
502
|
+
gif: gifExists,
|
|
503
|
+
snapshot: snapshotExists,
|
|
504
|
+
outputPath: result.outputPath,
|
|
505
|
+
gifPath: result.gifPath,
|
|
506
|
+
snapshotPath: result.snapshotPath
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
const filesExist = videoExists && gifExists && snapshotExists;
|
|
447
510
|
|
|
448
511
|
if (!filesExist) {
|
|
449
|
-
console.log('Recording uploaded by background process');
|
|
450
|
-
logger.info('Files were cleaned up by background process');
|
|
512
|
+
console.log('Recording appears to be uploaded by background process (files deleted)');
|
|
513
|
+
logger.info('Files were cleaned up by background process, assuming upload succeeded');
|
|
451
514
|
process.exit(0);
|
|
452
515
|
}
|
|
453
516
|
|
|
454
517
|
// Always attempt to upload - let upload function find project if needed
|
|
455
|
-
console.log('
|
|
518
|
+
console.log('No upload result found, uploading from foreground process...');
|
|
519
|
+
logger.debug('Starting foreground upload with metadata:', {
|
|
520
|
+
title: activeStatus?.options?.title,
|
|
521
|
+
project: activeStatus?.options?.project,
|
|
522
|
+
duration: result.duration,
|
|
523
|
+
outputPath: result.outputPath
|
|
524
|
+
});
|
|
525
|
+
|
|
456
526
|
try {
|
|
457
527
|
const uploadResult = await upload(result.outputPath, {
|
|
458
528
|
title: activeStatus?.options?.title,
|
|
@@ -467,12 +537,23 @@ program
|
|
|
467
537
|
});
|
|
468
538
|
|
|
469
539
|
console.log('Watch your recording:', uploadResult.shareLink);
|
|
540
|
+
logger.info('Foreground upload succeeded');
|
|
470
541
|
} catch (uploadError) {
|
|
471
542
|
console.error('Upload failed:', uploadError.message);
|
|
543
|
+
logger.error('Upload error details:', {
|
|
544
|
+
message: uploadError.message,
|
|
545
|
+
stack: uploadError.stack,
|
|
546
|
+
code: uploadError.code,
|
|
547
|
+
statusCode: uploadError.response?.statusCode
|
|
548
|
+
});
|
|
472
549
|
console.log('Recording saved locally:', result.outputPath);
|
|
473
550
|
}
|
|
474
551
|
} catch (error) {
|
|
475
552
|
console.error('Failed to stop recording:', error.message);
|
|
553
|
+
logger.error('Stop recording error details:', {
|
|
554
|
+
message: error.message,
|
|
555
|
+
stack: error.stack
|
|
556
|
+
});
|
|
476
557
|
process.exit(1);
|
|
477
558
|
}
|
|
478
559
|
|
package/lib/processManager.js
CHANGED
|
@@ -30,27 +30,86 @@ class ProcessManager {
|
|
|
30
30
|
|
|
31
31
|
writeStatus(status) {
|
|
32
32
|
try {
|
|
33
|
-
|
|
33
|
+
const statusData = {
|
|
34
34
|
...status,
|
|
35
35
|
timestamp: Date.now(),
|
|
36
36
|
pid: process.pid
|
|
37
|
-
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
logger.debug('Writing status file', {
|
|
40
|
+
statusFile: STATUS_FILE,
|
|
41
|
+
pid: statusData.pid,
|
|
42
|
+
isRecording: statusData.isRecording,
|
|
43
|
+
platform: process.platform
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
fs.writeFileSync(STATUS_FILE, JSON.stringify(statusData, null, 2));
|
|
47
|
+
|
|
48
|
+
// Verify it was written
|
|
49
|
+
if (fs.existsSync(STATUS_FILE)) {
|
|
50
|
+
logger.debug('Status file written successfully');
|
|
51
|
+
} else {
|
|
52
|
+
logger.error('Status file does not exist after write!');
|
|
53
|
+
}
|
|
38
54
|
} catch (error) {
|
|
39
|
-
logger.error('Failed to write status file', {
|
|
55
|
+
logger.error('Failed to write status file', {
|
|
56
|
+
error: error.message,
|
|
57
|
+
stack: error.stack,
|
|
58
|
+
statusFile: STATUS_FILE
|
|
59
|
+
});
|
|
40
60
|
}
|
|
41
61
|
}
|
|
42
62
|
|
|
43
63
|
readStatus() {
|
|
44
64
|
try {
|
|
45
|
-
|
|
65
|
+
logger.debug('Reading status file', {
|
|
66
|
+
statusFile: STATUS_FILE,
|
|
67
|
+
exists: fs.existsSync(STATUS_FILE)
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
if (!fs.existsSync(STATUS_FILE)) {
|
|
71
|
+
logger.debug('Status file does not exist');
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
46
75
|
const data = fs.readFileSync(STATUS_FILE, 'utf8');
|
|
47
|
-
|
|
76
|
+
const status = JSON.parse(data);
|
|
77
|
+
|
|
78
|
+
logger.debug('Status file read successfully', {
|
|
79
|
+
pid: status.pid,
|
|
80
|
+
isRecording: status.isRecording,
|
|
81
|
+
timestamp: status.timestamp,
|
|
82
|
+
startTime: status.startTime,
|
|
83
|
+
outputPath: status.outputPath
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
return status;
|
|
48
87
|
} catch (error) {
|
|
49
|
-
logger.error('Failed to read status file', {
|
|
88
|
+
logger.error('Failed to read status file', {
|
|
89
|
+
error: error.message,
|
|
90
|
+
stack: error.stack,
|
|
91
|
+
statusFile: STATUS_FILE
|
|
92
|
+
});
|
|
50
93
|
return null;
|
|
51
94
|
}
|
|
52
95
|
}
|
|
53
96
|
|
|
97
|
+
markStatusCompleted(completionData = {}) {
|
|
98
|
+
try {
|
|
99
|
+
const status = this.readStatus();
|
|
100
|
+
if (status) {
|
|
101
|
+
fs.writeFileSync(STATUS_FILE, JSON.stringify({
|
|
102
|
+
...status,
|
|
103
|
+
isRecording: false,
|
|
104
|
+
completedAt: Date.now(),
|
|
105
|
+
...completionData
|
|
106
|
+
}, null, 2));
|
|
107
|
+
}
|
|
108
|
+
} catch (error) {
|
|
109
|
+
logger.error('Failed to mark status as completed', { error });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
54
113
|
writeUploadResult(result) {
|
|
55
114
|
try {
|
|
56
115
|
logger.info('Writing upload result to file', { path: RESULT_FILE, shareLink: result.shareLink });
|
|
@@ -82,24 +141,77 @@ class ProcessManager {
|
|
|
82
141
|
}
|
|
83
142
|
|
|
84
143
|
isProcessRunning(pid) {
|
|
85
|
-
if (!pid)
|
|
144
|
+
if (!pid) {
|
|
145
|
+
logger.debug('isProcessRunning: no PID provided');
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
|
|
86
149
|
try {
|
|
87
150
|
process.kill(pid, 0); // Signal 0 just checks if process exists
|
|
151
|
+
logger.debug('Process is running', { pid });
|
|
88
152
|
return true;
|
|
89
153
|
} catch (error) {
|
|
154
|
+
logger.debug('Process is not running', {
|
|
155
|
+
pid,
|
|
156
|
+
error: error.code,
|
|
157
|
+
platform: process.platform
|
|
158
|
+
});
|
|
90
159
|
return false;
|
|
91
160
|
}
|
|
92
161
|
}
|
|
93
162
|
|
|
94
163
|
isRecordingActive() {
|
|
164
|
+
logger.debug('Checking if recording is active...', {
|
|
165
|
+
statusFile: STATUS_FILE,
|
|
166
|
+
processDir: PROCESS_DIR,
|
|
167
|
+
platform: process.platform
|
|
168
|
+
});
|
|
169
|
+
|
|
95
170
|
const status = this.readStatus();
|
|
96
171
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
172
|
+
logger.debug('Status check result', {
|
|
173
|
+
hasStatus: !!status,
|
|
174
|
+
hasPid: !!(status && status.pid),
|
|
175
|
+
isRecording: status ? status.isRecording : null,
|
|
176
|
+
statusPid: status ? status.pid : null,
|
|
177
|
+
currentPid: process.pid
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
if (!status) {
|
|
181
|
+
logger.debug('No status found - recording not active');
|
|
100
182
|
return false;
|
|
101
183
|
}
|
|
102
184
|
|
|
185
|
+
if (!status.pid) {
|
|
186
|
+
logger.debug('Status has no PID - marking as completed');
|
|
187
|
+
this.markStatusCompleted({ reason: 'no_pid_in_status' });
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const processRunning = this.isProcessRunning(status.pid);
|
|
192
|
+
logger.debug('Process running check', {
|
|
193
|
+
pid: status.pid,
|
|
194
|
+
isRunning: processRunning
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
if (!processRunning) {
|
|
198
|
+
logger.debug('Process not running - marking as completed', {
|
|
199
|
+
pid: status.pid,
|
|
200
|
+
wasRecording: status.isRecording
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// Mark as completed if process is dead but status exists
|
|
204
|
+
if (status.isRecording) {
|
|
205
|
+
this.markStatusCompleted({ reason: 'process_not_running' });
|
|
206
|
+
}
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
logger.debug('Recording active status', {
|
|
211
|
+
isRecording: status.isRecording,
|
|
212
|
+
pid: status.pid
|
|
213
|
+
});
|
|
214
|
+
|
|
103
215
|
return status.isRecording;
|
|
104
216
|
}
|
|
105
217
|
|
|
@@ -111,7 +223,7 @@ class ProcessManager {
|
|
|
111
223
|
cleanup(options = {}) {
|
|
112
224
|
const { preserveResult = false } = options;
|
|
113
225
|
try {
|
|
114
|
-
|
|
226
|
+
// Only delete result file, keep status file for history
|
|
115
227
|
if (!preserveResult && fs.existsSync(RESULT_FILE)) fs.unlinkSync(RESULT_FILE);
|
|
116
228
|
} catch (error) {
|
|
117
229
|
logger.error('Failed to cleanup process files', { error });
|
|
@@ -137,7 +249,7 @@ class ProcessManager {
|
|
|
137
249
|
const pid = status.pid;
|
|
138
250
|
if (!pid || !this.isProcessRunning(pid)) {
|
|
139
251
|
logger.warn('Background process not running');
|
|
140
|
-
this.
|
|
252
|
+
this.markStatusCompleted({ reason: 'process_already_stopped' });
|
|
141
253
|
return false;
|
|
142
254
|
}
|
|
143
255
|
|
|
@@ -172,6 +284,12 @@ class ProcessManager {
|
|
|
172
284
|
|
|
173
285
|
logger.info('Background process stopped');
|
|
174
286
|
|
|
287
|
+
// Mark status as completed
|
|
288
|
+
this.markStatusCompleted({
|
|
289
|
+
reason: 'stopped_by_user',
|
|
290
|
+
duration: Date.now() - status.startTime
|
|
291
|
+
});
|
|
292
|
+
|
|
175
293
|
// Return a minimal result indicating success
|
|
176
294
|
// The upload will be handled by the stop command checking the result file
|
|
177
295
|
return {
|
|
@@ -291,11 +409,8 @@ class ProcessManager {
|
|
|
291
409
|
logger.info('Recording stopped successfully during graceful exit');
|
|
292
410
|
} catch (error) {
|
|
293
411
|
logger.error('Failed to stop recording during graceful exit', { error });
|
|
294
|
-
this.
|
|
412
|
+
this.markStatusCompleted({ reason: 'graceful_exit_error' });
|
|
295
413
|
}
|
|
296
|
-
} else {
|
|
297
|
-
// Just cleanup if no recording is active
|
|
298
|
-
this.cleanup();
|
|
299
414
|
}
|
|
300
415
|
|
|
301
416
|
process.exit(0);
|
package/lib/uploader.js
CHANGED
|
@@ -110,6 +110,11 @@ class Uploader {
|
|
|
110
110
|
total: progress.total,
|
|
111
111
|
speedMBps: speedMBps.toFixed(2)
|
|
112
112
|
});
|
|
113
|
+
|
|
114
|
+
// Also output to console for user feedback
|
|
115
|
+
if (fileType === 'video') {
|
|
116
|
+
console.log(`Uploading video: ${percent}%`);
|
|
117
|
+
}
|
|
113
118
|
}
|
|
114
119
|
|
|
115
120
|
// Call progress callback if registered
|
|
@@ -125,6 +130,7 @@ class Uploader {
|
|
|
125
130
|
const uploadDuration = (Date.now() - upload.startTime) / 1000;
|
|
126
131
|
|
|
127
132
|
if (extension !== 'png') {
|
|
133
|
+
console.log(`Uploaded ${fileType} successfully (${uploadDuration.toFixed(1)}s)`);
|
|
128
134
|
logger.info(`Successfully uploaded ${fileType}`, {
|
|
129
135
|
key: result.Key,
|
|
130
136
|
location: result.Location,
|
|
@@ -143,10 +149,14 @@ class Uploader {
|
|
|
143
149
|
logExit();
|
|
144
150
|
return result;
|
|
145
151
|
} catch (error) {
|
|
152
|
+
console.error(`Failed to upload ${fileType}: ${error.message}`);
|
|
146
153
|
logger.error('Upload error:', {
|
|
147
154
|
fileType,
|
|
148
155
|
file: path.basename(file),
|
|
149
156
|
error: error.message,
|
|
157
|
+
code: error.code,
|
|
158
|
+
statusCode: error.$metadata?.httpStatusCode,
|
|
159
|
+
requestId: error.$metadata?.requestId,
|
|
150
160
|
stack: error.stack
|
|
151
161
|
});
|
|
152
162
|
|
|
@@ -254,6 +264,7 @@ export async function upload(filePath, metadata = {}) {
|
|
|
254
264
|
|
|
255
265
|
logger.verbose('Creating replay with config', replayConfig);
|
|
256
266
|
|
|
267
|
+
console.log('Creating replay on server...');
|
|
257
268
|
logger.info('Creating replay', replayConfig);
|
|
258
269
|
|
|
259
270
|
// Create the replay first
|
|
@@ -261,6 +272,7 @@ export async function upload(filePath, metadata = {}) {
|
|
|
261
272
|
|
|
262
273
|
let newReplay;
|
|
263
274
|
try {
|
|
275
|
+
logger.debug('Sending replay creation request...');
|
|
264
276
|
newReplay = await got.post('https://testdriver-api.onrender.com/api/v1/replay', {
|
|
265
277
|
headers: {
|
|
266
278
|
Authorization: `Bearer ${token}`
|
|
@@ -269,16 +281,19 @@ export async function upload(filePath, metadata = {}) {
|
|
|
269
281
|
timeout: 30000
|
|
270
282
|
}).json();
|
|
271
283
|
|
|
284
|
+
console.log('Replay created successfully');
|
|
272
285
|
logger.info('Replay created successfully', {
|
|
273
286
|
replayId: newReplay.replay.id,
|
|
274
287
|
shareKey: newReplay.replay.shareKey,
|
|
275
288
|
shareLink: newReplay.replay.shareLink
|
|
276
289
|
});
|
|
277
290
|
} catch (error) {
|
|
291
|
+
console.error('Failed to create replay on server');
|
|
278
292
|
logger.error('Failed to create replay', {
|
|
279
293
|
status: error.response?.statusCode,
|
|
280
294
|
statusText: error.response?.statusMessage,
|
|
281
295
|
body: error.response?.body,
|
|
296
|
+
message: error.message,
|
|
282
297
|
replayConfig: replayConfig
|
|
283
298
|
});
|
|
284
299
|
throw error;
|
|
@@ -310,8 +325,10 @@ export async function upload(filePath, metadata = {}) {
|
|
|
310
325
|
}
|
|
311
326
|
|
|
312
327
|
logger.verbose('Getting STS credentials for replay', { replayId: newReplay.replay.id });
|
|
328
|
+
console.log('Getting upload credentials...');
|
|
313
329
|
const sts = await auth.getStsCredentials(replayData);
|
|
314
330
|
|
|
331
|
+
console.log('Starting file uploads...');
|
|
315
332
|
logger.verbose('STS credentials received', {
|
|
316
333
|
hasVideo: !!sts.video,
|
|
317
334
|
hasImage: !!sts.image,
|
|
@@ -342,6 +359,7 @@ export async function upload(filePath, metadata = {}) {
|
|
|
342
359
|
}
|
|
343
360
|
|
|
344
361
|
logger.info('Starting asset uploads', { totalUploads: promises.length });
|
|
362
|
+
console.log(`Uploading ${promises.length} file(s)...`);
|
|
345
363
|
|
|
346
364
|
// Process and upload logs if available
|
|
347
365
|
if (metadata.logs && metadata.logs.length > 0) {
|
|
@@ -420,6 +438,8 @@ export async function upload(filePath, metadata = {}) {
|
|
|
420
438
|
});
|
|
421
439
|
}
|
|
422
440
|
|
|
441
|
+
logger.debug('Waiting for all uploads to complete...');
|
|
442
|
+
console.log('Finalizing uploads...');
|
|
423
443
|
await Promise.all(promises);
|
|
424
444
|
|
|
425
445
|
// Clean up uploaded files after all uploads complete successfully
|
|
@@ -436,13 +456,27 @@ export async function upload(filePath, metadata = {}) {
|
|
|
436
456
|
|
|
437
457
|
// Publish the replay (like the desktop app does)
|
|
438
458
|
logger.debug('Publishing replay...');
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
459
|
+
console.log('Publishing replay...');
|
|
460
|
+
|
|
461
|
+
try {
|
|
462
|
+
await got.post('https://testdriver-api.onrender.com/api/v1/replay/publish', {
|
|
463
|
+
headers: {
|
|
464
|
+
Authorization: `Bearer ${token}`
|
|
465
|
+
},
|
|
466
|
+
json: { id: newReplay.replay.id },
|
|
467
|
+
timeout: 30000
|
|
468
|
+
}).json();
|
|
469
|
+
|
|
470
|
+
console.log('Replay published successfully');
|
|
471
|
+
} catch (error) {
|
|
472
|
+
console.error('Failed to publish replay:', error.message);
|
|
473
|
+
logger.error('Publish error:', {
|
|
474
|
+
message: error.message,
|
|
475
|
+
statusCode: error.response?.statusCode,
|
|
476
|
+
body: error.response?.body
|
|
477
|
+
});
|
|
478
|
+
throw error;
|
|
479
|
+
}
|
|
446
480
|
|
|
447
481
|
logger.info('Upload process completed successfully', {
|
|
448
482
|
replayId: newReplay.replay.id,
|