easyproctor-hml 2.7.5 → 2.7.7

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/esm/index.js CHANGED
@@ -13476,13 +13476,8 @@ var _ChunkStorageService = class _ChunkStorageService {
13476
13476
  async clearAllChunks(proctoringId2) {
13477
13477
  const db = await this.connect();
13478
13478
  return new Promise((resolve, reject) => {
13479
- const transaction = db.transaction(
13480
- _ChunkStorageService.STORE_NAME,
13481
- "readwrite"
13482
- );
13483
- const store = transaction.objectStore(
13484
- _ChunkStorageService.STORE_NAME
13485
- );
13479
+ const transaction = db.transaction(_ChunkStorageService.STORE_NAME, "readwrite");
13480
+ const store = transaction.objectStore(_ChunkStorageService.STORE_NAME);
13486
13481
  const index = store.index("proctoringId");
13487
13482
  const range = IDBKeyRange.only(proctoringId2);
13488
13483
  const request = index.openCursor(range);
@@ -13491,34 +13486,13 @@ var _ChunkStorageService = class _ChunkStorageService {
13491
13486
  if (cursor) {
13492
13487
  cursor.delete();
13493
13488
  cursor.continue();
13489
+ } else {
13490
+ resolve();
13494
13491
  }
13495
13492
  };
13496
13493
  request.onerror = () => {
13497
13494
  var _a2;
13498
- reject(
13499
- new Error(
13500
- `Erro ao limpar chunks: ${(_a2 = request.error) == null ? void 0 : _a2.message}`
13501
- )
13502
- );
13503
- };
13504
- transaction.oncomplete = () => {
13505
- resolve();
13506
- };
13507
- transaction.onerror = () => {
13508
- var _a2;
13509
- reject(
13510
- new Error(
13511
- `Transaction error: ${(_a2 = transaction.error) == null ? void 0 : _a2.message}`
13512
- )
13513
- );
13514
- };
13515
- transaction.onabort = () => {
13516
- var _a2;
13517
- reject(
13518
- new Error(
13519
- `Transaction aborted: ${(_a2 = transaction.error) == null ? void 0 : _a2.message}`
13520
- )
13521
- );
13495
+ return reject(new Error(`Erro ao limpar todos os chunks: ${(_a2 = request.error) == null ? void 0 : _a2.message}`));
13522
13496
  };
13523
13497
  });
13524
13498
  }
@@ -13577,7 +13551,7 @@ var _ChunkStorageService = class _ChunkStorageService {
13577
13551
  }
13578
13552
  };
13579
13553
  _ChunkStorageService.DB_NAME = "EasyProctorChunksDb";
13580
- /** v2: índices numéricos; v3: payload como ArrayBuffer em vez de Blob (Safari iOS). */
13554
+ /** v2: índices numéricos; v3: payload em ArrayBuffer (Safari/iOS com Blob no IDB) */
13581
13555
  _ChunkStorageService.DB_VERSION = 3;
13582
13556
  _ChunkStorageService.STORE_NAME = "chunks";
13583
13557
  var ChunkStorageService = _ChunkStorageService;
@@ -13738,7 +13712,7 @@ var BackgroundUploadService = class _BackgroundUploadService {
13738
13712
  * @param isFinal Se true, não alinha a 256KB e fecha a sessão com /TOTAL no header.
13739
13713
  */
13740
13714
  async processQueue(isFinal = false) {
13741
- var _a2, _b;
13715
+ var _a2, _b, _c2, _d, _e3, _f;
13742
13716
  if (this.isProcessing) return;
13743
13717
  this.isProcessing = true;
13744
13718
  try {
@@ -13760,41 +13734,32 @@ var BackgroundUploadService = class _BackgroundUploadService {
13760
13734
  console.log(`[BackgroundUpload] ${pendingChunks.length} chunks pendentes encontrados. Modo final: ${isFinal}`);
13761
13735
  let virtualStart = this.totalBytesPurged;
13762
13736
  const chunksWithMeta = allChunks.map((c3) => {
13763
- const byteLen = c3.arrayBuffer.byteLength;
13764
13737
  const start = virtualStart;
13765
- const end = start + byteLen - 1;
13766
- virtualStart += byteLen;
13738
+ const end = start + c3.arrayBuffer.byteLength - 1;
13739
+ virtualStart += c3.arrayBuffer.byteLength;
13767
13740
  return { chunk: c3, start, end };
13768
13741
  });
13769
- const sliceParts = [];
13742
+ const combinedBufferParts = [];
13770
13743
  let lastProcessedChunkId = null;
13771
13744
  let finalChunkIndex = 0;
13772
- let mimeType = pendingChunks[0].mimeType;
13745
+ const mimeType = (_d = (_c2 = (_a2 = pendingChunks[0]) == null ? void 0 : _a2.mimeType) != null ? _c2 : (_b = allChunks[allChunks.length - 1]) == null ? void 0 : _b.mimeType) != null ? _d : "video/webm";
13773
13746
  for (const meta of chunksWithMeta) {
13774
13747
  if (this.currentOffset > meta.end) continue;
13775
13748
  const sliceStart = Math.max(0, this.currentOffset - meta.start);
13776
- const view = new Uint8Array(meta.chunk.arrayBuffer);
13777
- sliceParts.push(view.subarray(sliceStart));
13749
+ const chunkSlice = meta.chunk.arrayBuffer.slice(sliceStart);
13750
+ combinedBufferParts.push(chunkSlice);
13778
13751
  lastProcessedChunkId = meta.chunk.id;
13779
13752
  finalChunkIndex = meta.chunk.chunkIndex;
13780
13753
  }
13781
- if (sliceParts.length === 0 && !isFinal) {
13754
+ if (combinedBufferParts.length === 0 && !isFinal) {
13782
13755
  this.isProcessing = false;
13783
13756
  return;
13784
13757
  }
13785
- const combinedLength = sliceParts.reduce((acc, p3) => acc + p3.length, 0);
13786
- const combined = new Uint8Array(combinedLength);
13787
- {
13788
- let off = 0;
13789
- for (const p3 of sliceParts) {
13790
- combined.set(p3, off);
13791
- off += p3.length;
13792
- }
13793
- }
13794
- let sendableSize = combined.byteLength;
13758
+ const fullBuffer = _BackgroundUploadService.concatArrayBuffers(combinedBufferParts);
13759
+ let sendableSize = fullBuffer.byteLength;
13795
13760
  let totalSizeForHeader = void 0;
13796
13761
  if (!isFinal) {
13797
- sendableSize = Math.floor(combined.byteLength / this.GCS_CHUNK_SIZE) * this.GCS_CHUNK_SIZE;
13762
+ sendableSize = Math.floor(fullBuffer.byteLength / this.GCS_CHUNK_SIZE) * this.GCS_CHUNK_SIZE;
13798
13763
  if (sendableSize === 0) {
13799
13764
  console.log("[BackgroundUpload] Dados insuficientes para atingir 256KB. Aguardando novo chunk...");
13800
13765
  this.isProcessing = false;
@@ -13803,19 +13768,14 @@ var BackgroundUploadService = class _BackgroundUploadService {
13803
13768
  } else {
13804
13769
  totalSizeForHeader = virtualStart;
13805
13770
  }
13806
- const payload = sendableSize === combined.byteLength ? combined : combined.subarray(0, sendableSize);
13771
+ const bufferToSend = sendableSize < fullBuffer.byteLength ? fullBuffer.slice(0, sendableSize) : fullBuffer;
13807
13772
  try {
13808
- await this.uploadData(
13809
- payload.byteLength > 0 ? payload : null,
13810
- mimeType,
13811
- finalChunkIndex,
13812
- totalSizeForHeader
13813
- );
13773
+ await this.uploadData(bufferToSend, mimeType, finalChunkIndex, totalSizeForHeader);
13814
13774
  for (const meta of chunksWithMeta) {
13815
13775
  if (meta.chunk.uploaded === 0 && meta.end < this.currentOffset) {
13816
13776
  await this.chunkStorage.markAsUploaded(meta.chunk.id);
13817
13777
  this.retryCount.delete(meta.chunk.id);
13818
- (_a2 = this.onChunkUploaded) == null ? void 0 : _a2.call(this, meta.chunk.id, meta.chunk.chunkIndex);
13778
+ (_e3 = this.onChunkUploaded) == null ? void 0 : _e3.call(this, meta.chunk.id, meta.chunk.chunkIndex);
13819
13779
  console.log(`[BackgroundUpload] Chunk ${meta.chunk.chunkIndex} marcado como enviado.`);
13820
13780
  }
13821
13781
  }
@@ -13837,7 +13797,7 @@ var BackgroundUploadService = class _BackgroundUploadService {
13837
13797
  }
13838
13798
  } catch (error) {
13839
13799
  console.error("[BackgroundUpload] Falha no upload:", error);
13840
- (_b = this.onUploadError) == null ? void 0 : _b.call(this, lastProcessedChunkId || 0, error);
13800
+ (_f = this.onUploadError) == null ? void 0 : _f.call(this, lastProcessedChunkId || 0, error);
13841
13801
  }
13842
13802
  } catch (error) {
13843
13803
  console.error("[BackgroundUpload] Erro ao processar fila:", error);
@@ -13848,8 +13808,18 @@ var BackgroundUploadService = class _BackgroundUploadService {
13848
13808
  /**
13849
13809
  * Faz o upload bruto de dados para a sessão GCS.
13850
13810
  */
13851
- async uploadData(body, mimeType, chunkIndex, totalSize) {
13852
- var _a2;
13811
+ static concatArrayBuffers(parts) {
13812
+ if (parts.length === 0) return new ArrayBuffer(0);
13813
+ const total = parts.reduce((sum, p3) => sum + p3.byteLength, 0);
13814
+ const merged = new Uint8Array(total);
13815
+ let offset = 0;
13816
+ for (const p3 of parts) {
13817
+ merged.set(new Uint8Array(p3), offset);
13818
+ offset += p3.byteLength;
13819
+ }
13820
+ return merged.buffer.byteLength === total ? merged.buffer : merged.buffer.slice(merged.byteOffset, merged.byteOffset + merged.byteLength);
13821
+ }
13822
+ async uploadData(data, mimeType, chunkIndex, totalSize) {
13853
13823
  const fileName = `EP_${this.proctoringId}_camera_0.webm`;
13854
13824
  if (!this.sessionUrl) {
13855
13825
  const initiateUrl = await this.backend.initiateUpload(this.token, `${this.proctoringId}/${fileName}`, mimeType);
@@ -13880,28 +13850,17 @@ var BackgroundUploadService = class _BackgroundUploadService {
13880
13850
  } else {
13881
13851
  console.log(`[BackgroundUpload] Usando sess\xE3o GCS existente: ${this.sessionUrl}`);
13882
13852
  }
13883
- const size = (_a2 = body == null ? void 0 : body.byteLength) != null ? _a2 : 0;
13884
13853
  const start = this.currentOffset;
13885
- const end = start + size - 1;
13854
+ const end = start + data.byteLength - 1;
13886
13855
  const totalHeader = totalSize !== void 0 ? totalSize.toString() : "*";
13887
- const contentRangeHeader = size === 0 && totalSize !== void 0 ? `bytes */${totalHeader}` : `bytes ${start}-${end}/${totalHeader}`;
13856
+ const contentRangeHeader = data.byteLength === 0 && totalSize !== void 0 ? `bytes */${totalHeader}` : `bytes ${start}-${end}/${totalHeader}`;
13888
13857
  console.log(
13889
- `[BackgroundUpload] Enviando ${size > 0 ? "dados" : "finaliza\xE7\xE3o"}: ${contentRangeHeader} (Size: ${size})`
13858
+ `[BackgroundUpload] Enviando ${data.byteLength > 0 ? "dados" : "finaliza\xE7\xE3o"}: ${contentRangeHeader} (Size: ${data.byteLength})`
13890
13859
  );
13891
- let uploadBody = null;
13892
- if (size > 0 && body) {
13893
- const raw = body.buffer;
13894
- if (raw instanceof ArrayBuffer) {
13895
- uploadBody = body.byteOffset === 0 && body.byteLength === raw.byteLength ? raw : raw.slice(body.byteOffset, body.byteOffset + body.byteLength);
13896
- } else {
13897
- uploadBody = new ArrayBuffer(body.byteLength);
13898
- new Uint8Array(uploadBody).set(body);
13899
- }
13900
- }
13901
13860
  const response = await fetch(this.sessionUrl, {
13902
13861
  method: "PUT",
13903
13862
  headers: { "Content-Range": contentRangeHeader },
13904
- body: uploadBody
13863
+ body: data.byteLength > 0 ? data : null
13905
13864
  });
13906
13865
  console.log(`[BackgroundUpload] Resposta GCS (uploadData): ${response.status}`);
13907
13866
  if (response.status !== 200 && response.status !== 201 && response.status !== 308) {
@@ -13914,13 +13873,13 @@ var BackgroundUploadService = class _BackgroundUploadService {
13914
13873
  const lastByte = parseInt(rangeHeader.split("-")[1], 10);
13915
13874
  this.currentOffset = lastByte + 1;
13916
13875
  } else {
13917
- this.currentOffset += size;
13876
+ this.currentOffset += data.byteLength;
13918
13877
  }
13919
13878
  this.saveSessionState();
13920
13879
  trackers.registerUploadFile(
13921
13880
  this.proctoringId,
13922
13881
  `GCS Stream Upload
13923
- Size: ${size}
13882
+ Size: ${data.byteLength}
13924
13883
  Range: ${start}-${end}
13925
13884
  Last Index: ${chunkIndex}`,
13926
13885
  "CameraChunk"
@@ -14439,23 +14398,19 @@ Setting: ${JSON.stringify(settings, null, 2)}`
14439
14398
  }
14440
14399
  if (this.isChunkEnabled) {
14441
14400
  if (this.backgroundUpload) {
14442
- trackers.registerError(this.proctoringId, `Flush e parada do background upload`);
14443
14401
  try {
14444
14402
  if (this.pendingChunkSaves.length > 0) {
14445
14403
  console.log(`[CameraRecorder] Aguardando ${this.pendingChunkSaves.length} salvamentos de chunks pendentes...`);
14446
14404
  await Promise.all(this.pendingChunkSaves);
14447
14405
  }
14448
14406
  await this.backgroundUpload.flush();
14449
- this.backgroundUpload.stop();
14450
14407
  } catch (e3) {
14451
14408
  console.warn("[CameraRecorder] Erro ao fazer flush dos chunks:", e3);
14452
- trackers.registerError(this.proctoringId, `Flush Chunks
14453
- Error: ${e3}`);
14454
14409
  }
14410
+ this.backgroundUpload.stop();
14455
14411
  }
14456
14412
  this.removeLifecycleListeners();
14457
14413
  this.persistSessionState("FINISHED");
14458
- trackers.registerError(this.proctoringId, `Finalizando flush e parada do background upload`);
14459
14414
  }
14460
14415
  }
14461
14416
  /**
@@ -14479,8 +14434,6 @@ Setting: ${JSON.stringify(settings, null, 2)}`
14479
14434
  this.chunkIndex++;
14480
14435
  console.log(`[CameraRecorder] Chunk ${this.chunkIndex - 1} salvo no IndexedDB.`);
14481
14436
  } catch (error) {
14482
- trackers.registerError(this.proctoringId, `Save Chunk
14483
- Error: ${error}`);
14484
14437
  console.error("[CameraRecorder] Erro ao salvar chunk no IndexedDB:", error);
14485
14438
  }
14486
14439
  })();
@@ -14629,7 +14582,6 @@ Setting: ${JSON.stringify(settings, null, 2)}`
14629
14582
  const settingsAudio = this.cameraStream.getAudioTracks()[0].getSettings();
14630
14583
  if (this.options.proctoringType == "VIDEO" || this.options.proctoringType == "REALTIME" || this.options.proctoringType == "IMAGE" && ((_a2 = this.paramsConfig.imageBehaviourParameters) == null ? void 0 : _a2.saveVideo)) {
14631
14584
  let videoFile;
14632
- trackers.registerError(this.proctoringId, `saveOnSession iniciando`);
14633
14585
  if (this.isChunkEnabled) {
14634
14586
  const isStable = await this.checkInternetStability();
14635
14587
  if (isStable) {
@@ -14638,19 +14590,13 @@ Setting: ${JSON.stringify(settings, null, 2)}`
14638
14590
  const fileName = `EP_${this.proctoringId}_camera_0.webm`;
14639
14591
  const objectName = `${this.proctoringId}/${fileName}`;
14640
14592
  const isUploaded = await this.backend.checkUpload(this.backendToken, objectName, "video/webm");
14641
- trackers.registerError(this.proctoringId, `Limpa o armazenamento local pois o v\xEDdeo j\xE1 est\xE1 no servidor`);
14642
14593
  if (isUploaded) {
14643
- try {
14644
- this.chunkStorage && await this.chunkStorage.clearAllChunks(session.id);
14645
- } catch (e3) {
14646
- trackers.registerError(this.proctoringId, `Erro ao limpar o armazenamento local: ${e3}`);
14647
- }
14594
+ this.chunkStorage && await this.chunkStorage.clearAllChunks(session.id);
14648
14595
  return;
14649
14596
  }
14650
14597
  }
14651
14598
  }
14652
14599
  }
14653
- trackers.registerError(this.proctoringId, `saveOnSession gerando v\xEDdeo a partir do buffer em mem\xF3ria (\xEDntegra)`);
14654
14600
  const rawBlob = new Blob(this.blobs, {
14655
14601
  type: ((_b = this.recorderOptions) == null ? void 0 : _b.mimeType) || "video/webm"
14656
14602
  });
@@ -14671,7 +14617,6 @@ Setting: ${JSON.stringify(settings, null, 2)}`
14671
14617
  origin: "Camera" /* Camera */
14672
14618
  });
14673
14619
  }
14674
- trackers.registerError(this.proctoringId, `saveOnSession finalizado`);
14675
14620
  }
14676
14621
  async getFile(file, name, type) {
14677
14622
  return new Promise((resolve, reject) => {
@@ -23801,14 +23746,11 @@ Error: ${error}`
23801
23746
  await this.recorder.stopAll();
23802
23747
  this.spyCam && this.spyCam.stopCheckSpyCam();
23803
23748
  this.appChecker && await this.appChecker.disconnectWebSocket();
23804
- trackers.registerError(this.proctoringId, `finish saveAllOnSession`);
23805
23749
  await this.recorder.saveAllOnSession();
23806
- trackers.registerError(this.proctoringId, `finish sendPendingRealtimeAlerts`);
23807
23750
  await this.sendPendingRealtimeAlerts();
23808
- trackers.registerError(this.proctoringId, `finish this.repository.save`);
23751
+ await this.repository.save(this.proctoringSession);
23809
23752
  let uploader;
23810
23753
  let uploaderServices;
23811
- trackers.registerError(this.proctoringId, `finish uploader`);
23812
23754
  if (versionVerify() !== "1.0.0.0") {
23813
23755
  uploader = new ProctoringUploader(
23814
23756
  this.proctoringSession,
@@ -23882,7 +23824,6 @@ Upload Services: ${uploaderServices}`,
23882
23824
  this.serviceType
23883
23825
  );
23884
23826
  }
23885
- trackers.registerError(this.proctoringId, `finish uploader success`);
23886
23827
  if (this.proctoringSession.alerts.length > 0) {
23887
23828
  await this.backend.saveAlerts(this.context, this.proctoringSession).catch((err) => {
23888
23829
  trackers.registerFinish(
@@ -23892,7 +23833,6 @@ Upload Services: ${uploaderServices}`,
23892
23833
  );
23893
23834
  });
23894
23835
  }
23895
- trackers.registerError(this.proctoringId, `finish saveAlerts ok`);
23896
23836
  await this.backend.finishAndSendUrls(this.context).then((finishResponse) => {
23897
23837
  var _a2, _b, _c2, _d;
23898
23838
  trackers.registerFinish(this.proctoringSession.id, true, "");
@@ -23904,7 +23844,6 @@ Upload Services: ${uploaderServices}`,
23904
23844
  "finish error: " + error
23905
23845
  );
23906
23846
  });
23907
- trackers.registerError(this.proctoringId, `finish call`);
23908
23847
  if (this.appChecker) {
23909
23848
  const externalSessionId = this.appChecker.getExternalCameraSessionId();
23910
23849
  if (externalSessionId != "null") {
package/index.js CHANGED
@@ -31573,13 +31573,8 @@ var _ChunkStorageService = class _ChunkStorageService {
31573
31573
  async clearAllChunks(proctoringId2) {
31574
31574
  const db = await this.connect();
31575
31575
  return new Promise((resolve, reject) => {
31576
- const transaction = db.transaction(
31577
- _ChunkStorageService.STORE_NAME,
31578
- "readwrite"
31579
- );
31580
- const store = transaction.objectStore(
31581
- _ChunkStorageService.STORE_NAME
31582
- );
31576
+ const transaction = db.transaction(_ChunkStorageService.STORE_NAME, "readwrite");
31577
+ const store = transaction.objectStore(_ChunkStorageService.STORE_NAME);
31583
31578
  const index = store.index("proctoringId");
31584
31579
  const range = IDBKeyRange.only(proctoringId2);
31585
31580
  const request = index.openCursor(range);
@@ -31588,34 +31583,13 @@ var _ChunkStorageService = class _ChunkStorageService {
31588
31583
  if (cursor) {
31589
31584
  cursor.delete();
31590
31585
  cursor.continue();
31586
+ } else {
31587
+ resolve();
31591
31588
  }
31592
31589
  };
31593
31590
  request.onerror = () => {
31594
31591
  var _a2;
31595
- reject(
31596
- new Error(
31597
- `Erro ao limpar chunks: ${(_a2 = request.error) == null ? void 0 : _a2.message}`
31598
- )
31599
- );
31600
- };
31601
- transaction.oncomplete = () => {
31602
- resolve();
31603
- };
31604
- transaction.onerror = () => {
31605
- var _a2;
31606
- reject(
31607
- new Error(
31608
- `Transaction error: ${(_a2 = transaction.error) == null ? void 0 : _a2.message}`
31609
- )
31610
- );
31611
- };
31612
- transaction.onabort = () => {
31613
- var _a2;
31614
- reject(
31615
- new Error(
31616
- `Transaction aborted: ${(_a2 = transaction.error) == null ? void 0 : _a2.message}`
31617
- )
31618
- );
31592
+ return reject(new Error(`Erro ao limpar todos os chunks: ${(_a2 = request.error) == null ? void 0 : _a2.message}`));
31619
31593
  };
31620
31594
  });
31621
31595
  }
@@ -31674,7 +31648,7 @@ var _ChunkStorageService = class _ChunkStorageService {
31674
31648
  }
31675
31649
  };
31676
31650
  _ChunkStorageService.DB_NAME = "EasyProctorChunksDb";
31677
- /** v2: índices numéricos; v3: payload como ArrayBuffer em vez de Blob (Safari iOS). */
31651
+ /** v2: índices numéricos; v3: payload em ArrayBuffer (Safari/iOS com Blob no IDB) */
31678
31652
  _ChunkStorageService.DB_VERSION = 3;
31679
31653
  _ChunkStorageService.STORE_NAME = "chunks";
31680
31654
  var ChunkStorageService = _ChunkStorageService;
@@ -31835,7 +31809,7 @@ var BackgroundUploadService = class _BackgroundUploadService {
31835
31809
  * @param isFinal Se true, não alinha a 256KB e fecha a sessão com /TOTAL no header.
31836
31810
  */
31837
31811
  async processQueue(isFinal = false) {
31838
- var _a2, _b;
31812
+ var _a2, _b, _c2, _d, _e3, _f;
31839
31813
  if (this.isProcessing) return;
31840
31814
  this.isProcessing = true;
31841
31815
  try {
@@ -31857,41 +31831,32 @@ var BackgroundUploadService = class _BackgroundUploadService {
31857
31831
  console.log(`[BackgroundUpload] ${pendingChunks.length} chunks pendentes encontrados. Modo final: ${isFinal}`);
31858
31832
  let virtualStart = this.totalBytesPurged;
31859
31833
  const chunksWithMeta = allChunks.map((c3) => {
31860
- const byteLen = c3.arrayBuffer.byteLength;
31861
31834
  const start = virtualStart;
31862
- const end = start + byteLen - 1;
31863
- virtualStart += byteLen;
31835
+ const end = start + c3.arrayBuffer.byteLength - 1;
31836
+ virtualStart += c3.arrayBuffer.byteLength;
31864
31837
  return { chunk: c3, start, end };
31865
31838
  });
31866
- const sliceParts = [];
31839
+ const combinedBufferParts = [];
31867
31840
  let lastProcessedChunkId = null;
31868
31841
  let finalChunkIndex = 0;
31869
- let mimeType = pendingChunks[0].mimeType;
31842
+ const mimeType = (_d = (_c2 = (_a2 = pendingChunks[0]) == null ? void 0 : _a2.mimeType) != null ? _c2 : (_b = allChunks[allChunks.length - 1]) == null ? void 0 : _b.mimeType) != null ? _d : "video/webm";
31870
31843
  for (const meta of chunksWithMeta) {
31871
31844
  if (this.currentOffset > meta.end) continue;
31872
31845
  const sliceStart = Math.max(0, this.currentOffset - meta.start);
31873
- const view = new Uint8Array(meta.chunk.arrayBuffer);
31874
- sliceParts.push(view.subarray(sliceStart));
31846
+ const chunkSlice = meta.chunk.arrayBuffer.slice(sliceStart);
31847
+ combinedBufferParts.push(chunkSlice);
31875
31848
  lastProcessedChunkId = meta.chunk.id;
31876
31849
  finalChunkIndex = meta.chunk.chunkIndex;
31877
31850
  }
31878
- if (sliceParts.length === 0 && !isFinal) {
31851
+ if (combinedBufferParts.length === 0 && !isFinal) {
31879
31852
  this.isProcessing = false;
31880
31853
  return;
31881
31854
  }
31882
- const combinedLength = sliceParts.reduce((acc, p3) => acc + p3.length, 0);
31883
- const combined = new Uint8Array(combinedLength);
31884
- {
31885
- let off = 0;
31886
- for (const p3 of sliceParts) {
31887
- combined.set(p3, off);
31888
- off += p3.length;
31889
- }
31890
- }
31891
- let sendableSize = combined.byteLength;
31855
+ const fullBuffer = _BackgroundUploadService.concatArrayBuffers(combinedBufferParts);
31856
+ let sendableSize = fullBuffer.byteLength;
31892
31857
  let totalSizeForHeader = void 0;
31893
31858
  if (!isFinal) {
31894
- sendableSize = Math.floor(combined.byteLength / this.GCS_CHUNK_SIZE) * this.GCS_CHUNK_SIZE;
31859
+ sendableSize = Math.floor(fullBuffer.byteLength / this.GCS_CHUNK_SIZE) * this.GCS_CHUNK_SIZE;
31895
31860
  if (sendableSize === 0) {
31896
31861
  console.log("[BackgroundUpload] Dados insuficientes para atingir 256KB. Aguardando novo chunk...");
31897
31862
  this.isProcessing = false;
@@ -31900,19 +31865,14 @@ var BackgroundUploadService = class _BackgroundUploadService {
31900
31865
  } else {
31901
31866
  totalSizeForHeader = virtualStart;
31902
31867
  }
31903
- const payload = sendableSize === combined.byteLength ? combined : combined.subarray(0, sendableSize);
31868
+ const bufferToSend = sendableSize < fullBuffer.byteLength ? fullBuffer.slice(0, sendableSize) : fullBuffer;
31904
31869
  try {
31905
- await this.uploadData(
31906
- payload.byteLength > 0 ? payload : null,
31907
- mimeType,
31908
- finalChunkIndex,
31909
- totalSizeForHeader
31910
- );
31870
+ await this.uploadData(bufferToSend, mimeType, finalChunkIndex, totalSizeForHeader);
31911
31871
  for (const meta of chunksWithMeta) {
31912
31872
  if (meta.chunk.uploaded === 0 && meta.end < this.currentOffset) {
31913
31873
  await this.chunkStorage.markAsUploaded(meta.chunk.id);
31914
31874
  this.retryCount.delete(meta.chunk.id);
31915
- (_a2 = this.onChunkUploaded) == null ? void 0 : _a2.call(this, meta.chunk.id, meta.chunk.chunkIndex);
31875
+ (_e3 = this.onChunkUploaded) == null ? void 0 : _e3.call(this, meta.chunk.id, meta.chunk.chunkIndex);
31916
31876
  console.log(`[BackgroundUpload] Chunk ${meta.chunk.chunkIndex} marcado como enviado.`);
31917
31877
  }
31918
31878
  }
@@ -31934,7 +31894,7 @@ var BackgroundUploadService = class _BackgroundUploadService {
31934
31894
  }
31935
31895
  } catch (error) {
31936
31896
  console.error("[BackgroundUpload] Falha no upload:", error);
31937
- (_b = this.onUploadError) == null ? void 0 : _b.call(this, lastProcessedChunkId || 0, error);
31897
+ (_f = this.onUploadError) == null ? void 0 : _f.call(this, lastProcessedChunkId || 0, error);
31938
31898
  }
31939
31899
  } catch (error) {
31940
31900
  console.error("[BackgroundUpload] Erro ao processar fila:", error);
@@ -31945,8 +31905,18 @@ var BackgroundUploadService = class _BackgroundUploadService {
31945
31905
  /**
31946
31906
  * Faz o upload bruto de dados para a sessão GCS.
31947
31907
  */
31948
- async uploadData(body, mimeType, chunkIndex, totalSize) {
31949
- var _a2;
31908
+ static concatArrayBuffers(parts) {
31909
+ if (parts.length === 0) return new ArrayBuffer(0);
31910
+ const total = parts.reduce((sum, p3) => sum + p3.byteLength, 0);
31911
+ const merged = new Uint8Array(total);
31912
+ let offset = 0;
31913
+ for (const p3 of parts) {
31914
+ merged.set(new Uint8Array(p3), offset);
31915
+ offset += p3.byteLength;
31916
+ }
31917
+ return merged.buffer.byteLength === total ? merged.buffer : merged.buffer.slice(merged.byteOffset, merged.byteOffset + merged.byteLength);
31918
+ }
31919
+ async uploadData(data, mimeType, chunkIndex, totalSize) {
31950
31920
  const fileName = `EP_${this.proctoringId}_camera_0.webm`;
31951
31921
  if (!this.sessionUrl) {
31952
31922
  const initiateUrl = await this.backend.initiateUpload(this.token, `${this.proctoringId}/${fileName}`, mimeType);
@@ -31977,28 +31947,17 @@ var BackgroundUploadService = class _BackgroundUploadService {
31977
31947
  } else {
31978
31948
  console.log(`[BackgroundUpload] Usando sess\xE3o GCS existente: ${this.sessionUrl}`);
31979
31949
  }
31980
- const size = (_a2 = body == null ? void 0 : body.byteLength) != null ? _a2 : 0;
31981
31950
  const start = this.currentOffset;
31982
- const end = start + size - 1;
31951
+ const end = start + data.byteLength - 1;
31983
31952
  const totalHeader = totalSize !== void 0 ? totalSize.toString() : "*";
31984
- const contentRangeHeader = size === 0 && totalSize !== void 0 ? `bytes */${totalHeader}` : `bytes ${start}-${end}/${totalHeader}`;
31953
+ const contentRangeHeader = data.byteLength === 0 && totalSize !== void 0 ? `bytes */${totalHeader}` : `bytes ${start}-${end}/${totalHeader}`;
31985
31954
  console.log(
31986
- `[BackgroundUpload] Enviando ${size > 0 ? "dados" : "finaliza\xE7\xE3o"}: ${contentRangeHeader} (Size: ${size})`
31955
+ `[BackgroundUpload] Enviando ${data.byteLength > 0 ? "dados" : "finaliza\xE7\xE3o"}: ${contentRangeHeader} (Size: ${data.byteLength})`
31987
31956
  );
31988
- let uploadBody = null;
31989
- if (size > 0 && body) {
31990
- const raw = body.buffer;
31991
- if (raw instanceof ArrayBuffer) {
31992
- uploadBody = body.byteOffset === 0 && body.byteLength === raw.byteLength ? raw : raw.slice(body.byteOffset, body.byteOffset + body.byteLength);
31993
- } else {
31994
- uploadBody = new ArrayBuffer(body.byteLength);
31995
- new Uint8Array(uploadBody).set(body);
31996
- }
31997
- }
31998
31957
  const response = await fetch(this.sessionUrl, {
31999
31958
  method: "PUT",
32000
31959
  headers: { "Content-Range": contentRangeHeader },
32001
- body: uploadBody
31960
+ body: data.byteLength > 0 ? data : null
32002
31961
  });
32003
31962
  console.log(`[BackgroundUpload] Resposta GCS (uploadData): ${response.status}`);
32004
31963
  if (response.status !== 200 && response.status !== 201 && response.status !== 308) {
@@ -32011,13 +31970,13 @@ var BackgroundUploadService = class _BackgroundUploadService {
32011
31970
  const lastByte = parseInt(rangeHeader.split("-")[1], 10);
32012
31971
  this.currentOffset = lastByte + 1;
32013
31972
  } else {
32014
- this.currentOffset += size;
31973
+ this.currentOffset += data.byteLength;
32015
31974
  }
32016
31975
  this.saveSessionState();
32017
31976
  trackers.registerUploadFile(
32018
31977
  this.proctoringId,
32019
31978
  `GCS Stream Upload
32020
- Size: ${size}
31979
+ Size: ${data.byteLength}
32021
31980
  Range: ${start}-${end}
32022
31981
  Last Index: ${chunkIndex}`,
32023
31982
  "CameraChunk"
@@ -32536,23 +32495,19 @@ Setting: ${JSON.stringify(settings, null, 2)}`
32536
32495
  }
32537
32496
  if (this.isChunkEnabled) {
32538
32497
  if (this.backgroundUpload) {
32539
- trackers.registerError(this.proctoringId, `Flush e parada do background upload`);
32540
32498
  try {
32541
32499
  if (this.pendingChunkSaves.length > 0) {
32542
32500
  console.log(`[CameraRecorder] Aguardando ${this.pendingChunkSaves.length} salvamentos de chunks pendentes...`);
32543
32501
  await Promise.all(this.pendingChunkSaves);
32544
32502
  }
32545
32503
  await this.backgroundUpload.flush();
32546
- this.backgroundUpload.stop();
32547
32504
  } catch (e3) {
32548
32505
  console.warn("[CameraRecorder] Erro ao fazer flush dos chunks:", e3);
32549
- trackers.registerError(this.proctoringId, `Flush Chunks
32550
- Error: ${e3}`);
32551
32506
  }
32507
+ this.backgroundUpload.stop();
32552
32508
  }
32553
32509
  this.removeLifecycleListeners();
32554
32510
  this.persistSessionState("FINISHED");
32555
- trackers.registerError(this.proctoringId, `Finalizando flush e parada do background upload`);
32556
32511
  }
32557
32512
  }
32558
32513
  /**
@@ -32576,8 +32531,6 @@ Setting: ${JSON.stringify(settings, null, 2)}`
32576
32531
  this.chunkIndex++;
32577
32532
  console.log(`[CameraRecorder] Chunk ${this.chunkIndex - 1} salvo no IndexedDB.`);
32578
32533
  } catch (error) {
32579
- trackers.registerError(this.proctoringId, `Save Chunk
32580
- Error: ${error}`);
32581
32534
  console.error("[CameraRecorder] Erro ao salvar chunk no IndexedDB:", error);
32582
32535
  }
32583
32536
  })();
@@ -32726,7 +32679,6 @@ Setting: ${JSON.stringify(settings, null, 2)}`
32726
32679
  const settingsAudio = this.cameraStream.getAudioTracks()[0].getSettings();
32727
32680
  if (this.options.proctoringType == "VIDEO" || this.options.proctoringType == "REALTIME" || this.options.proctoringType == "IMAGE" && ((_a2 = this.paramsConfig.imageBehaviourParameters) == null ? void 0 : _a2.saveVideo)) {
32728
32681
  let videoFile;
32729
- trackers.registerError(this.proctoringId, `saveOnSession iniciando`);
32730
32682
  if (this.isChunkEnabled) {
32731
32683
  const isStable = await this.checkInternetStability();
32732
32684
  if (isStable) {
@@ -32735,19 +32687,13 @@ Setting: ${JSON.stringify(settings, null, 2)}`
32735
32687
  const fileName = `EP_${this.proctoringId}_camera_0.webm`;
32736
32688
  const objectName = `${this.proctoringId}/${fileName}`;
32737
32689
  const isUploaded = await this.backend.checkUpload(this.backendToken, objectName, "video/webm");
32738
- trackers.registerError(this.proctoringId, `Limpa o armazenamento local pois o v\xEDdeo j\xE1 est\xE1 no servidor`);
32739
32690
  if (isUploaded) {
32740
- try {
32741
- this.chunkStorage && await this.chunkStorage.clearAllChunks(session.id);
32742
- } catch (e3) {
32743
- trackers.registerError(this.proctoringId, `Erro ao limpar o armazenamento local: ${e3}`);
32744
- }
32691
+ this.chunkStorage && await this.chunkStorage.clearAllChunks(session.id);
32745
32692
  return;
32746
32693
  }
32747
32694
  }
32748
32695
  }
32749
32696
  }
32750
- trackers.registerError(this.proctoringId, `saveOnSession gerando v\xEDdeo a partir do buffer em mem\xF3ria (\xEDntegra)`);
32751
32697
  const rawBlob = new Blob(this.blobs, {
32752
32698
  type: ((_b = this.recorderOptions) == null ? void 0 : _b.mimeType) || "video/webm"
32753
32699
  });
@@ -32768,7 +32714,6 @@ Setting: ${JSON.stringify(settings, null, 2)}`
32768
32714
  origin: "Camera" /* Camera */
32769
32715
  });
32770
32716
  }
32771
- trackers.registerError(this.proctoringId, `saveOnSession finalizado`);
32772
32717
  }
32773
32718
  async getFile(file, name, type) {
32774
32719
  return new Promise((resolve, reject) => {
@@ -39050,14 +38995,11 @@ Error: ${error}`
39050
38995
  await this.recorder.stopAll();
39051
38996
  this.spyCam && this.spyCam.stopCheckSpyCam();
39052
38997
  this.appChecker && await this.appChecker.disconnectWebSocket();
39053
- trackers.registerError(this.proctoringId, `finish saveAllOnSession`);
39054
38998
  await this.recorder.saveAllOnSession();
39055
- trackers.registerError(this.proctoringId, `finish sendPendingRealtimeAlerts`);
39056
38999
  await this.sendPendingRealtimeAlerts();
39057
- trackers.registerError(this.proctoringId, `finish this.repository.save`);
39000
+ await this.repository.save(this.proctoringSession);
39058
39001
  let uploader;
39059
39002
  let uploaderServices;
39060
- trackers.registerError(this.proctoringId, `finish uploader`);
39061
39003
  if (versionVerify() !== "1.0.0.0") {
39062
39004
  uploader = new ProctoringUploader(
39063
39005
  this.proctoringSession,
@@ -39131,7 +39073,6 @@ Upload Services: ${uploaderServices}`,
39131
39073
  this.serviceType
39132
39074
  );
39133
39075
  }
39134
- trackers.registerError(this.proctoringId, `finish uploader success`);
39135
39076
  if (this.proctoringSession.alerts.length > 0) {
39136
39077
  await this.backend.saveAlerts(this.context, this.proctoringSession).catch((err) => {
39137
39078
  trackers.registerFinish(
@@ -39141,7 +39082,6 @@ Upload Services: ${uploaderServices}`,
39141
39082
  );
39142
39083
  });
39143
39084
  }
39144
- trackers.registerError(this.proctoringId, `finish saveAlerts ok`);
39145
39085
  await this.backend.finishAndSendUrls(this.context).then((finishResponse) => {
39146
39086
  var _a2, _b, _c2, _d;
39147
39087
  trackers.registerFinish(this.proctoringSession.id, true, "");
@@ -39153,7 +39093,6 @@ Upload Services: ${uploaderServices}`,
39153
39093
  "finish error: " + error
39154
39094
  );
39155
39095
  });
39156
- trackers.registerError(this.proctoringId, `finish call`);
39157
39096
  if (this.appChecker) {
39158
39097
  const externalSessionId = this.appChecker.getExternalCameraSessionId();
39159
39098
  if (externalSessionId != "null") {
@@ -32,6 +32,7 @@ export declare class BackgroundUploadService {
32
32
  flush(): Promise<void>;
33
33
  private syncOffset;
34
34
  private processQueue;
35
+ private static concatArrayBuffers;
35
36
  private uploadData;
36
37
  static recoverPendingUploads(backend: BackendService, token: string): Promise<string[]>;
37
38
  private sleep;