easyproctor-hml 2.7.0 → 2.7.1

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
@@ -13551,8 +13551,8 @@ var _ChunkStorageService = class _ChunkStorageService {
13551
13551
  }
13552
13552
  };
13553
13553
  _ChunkStorageService.DB_NAME = "EasyProctorChunksDb";
13554
- /** Incrementado para v2 para recriar índices com tipos numéricos em vez de boolean */
13555
- _ChunkStorageService.DB_VERSION = 2;
13554
+ /** v2: índices numéricos; v3: payload como ArrayBuffer em vez de Blob (Safari iOS). */
13555
+ _ChunkStorageService.DB_VERSION = 3;
13556
13556
  _ChunkStorageService.STORE_NAME = "chunks";
13557
13557
  var ChunkStorageService = _ChunkStorageService;
13558
13558
 
@@ -13734,32 +13734,41 @@ var BackgroundUploadService = class _BackgroundUploadService {
13734
13734
  console.log(`[BackgroundUpload] ${pendingChunks.length} chunks pendentes encontrados. Modo final: ${isFinal}`);
13735
13735
  let virtualStart = this.totalBytesPurged;
13736
13736
  const chunksWithMeta = allChunks.map((c3) => {
13737
+ const byteLen = c3.arrayBuffer.byteLength;
13737
13738
  const start = virtualStart;
13738
- const end = start + c3.blob.size - 1;
13739
- virtualStart += c3.blob.size;
13739
+ const end = start + byteLen - 1;
13740
+ virtualStart += byteLen;
13740
13741
  return { chunk: c3, start, end };
13741
13742
  });
13742
- let combinedBlobParts = [];
13743
+ const sliceParts = [];
13743
13744
  let lastProcessedChunkId = null;
13744
13745
  let finalChunkIndex = 0;
13745
13746
  let mimeType = pendingChunks[0].mimeType;
13746
13747
  for (const meta of chunksWithMeta) {
13747
13748
  if (this.currentOffset > meta.end) continue;
13748
13749
  const sliceStart = Math.max(0, this.currentOffset - meta.start);
13749
- const chunkSlice = meta.chunk.blob.slice(sliceStart);
13750
- combinedBlobParts.push(chunkSlice);
13750
+ const view = new Uint8Array(meta.chunk.arrayBuffer);
13751
+ sliceParts.push(view.subarray(sliceStart));
13751
13752
  lastProcessedChunkId = meta.chunk.id;
13752
13753
  finalChunkIndex = meta.chunk.chunkIndex;
13753
13754
  }
13754
- if (combinedBlobParts.length === 0 && !isFinal) {
13755
+ if (sliceParts.length === 0 && !isFinal) {
13755
13756
  this.isProcessing = false;
13756
13757
  return;
13757
13758
  }
13758
- let fullBlob = new Blob(combinedBlobParts, { type: mimeType });
13759
- let sendableSize = fullBlob.size;
13759
+ const combinedLength = sliceParts.reduce((acc, p3) => acc + p3.length, 0);
13760
+ const combined = new Uint8Array(combinedLength);
13761
+ {
13762
+ let off = 0;
13763
+ for (const p3 of sliceParts) {
13764
+ combined.set(p3, off);
13765
+ off += p3.length;
13766
+ }
13767
+ }
13768
+ let sendableSize = combined.byteLength;
13760
13769
  let totalSizeForHeader = void 0;
13761
13770
  if (!isFinal) {
13762
- sendableSize = Math.floor(fullBlob.size / this.GCS_CHUNK_SIZE) * this.GCS_CHUNK_SIZE;
13771
+ sendableSize = Math.floor(combined.byteLength / this.GCS_CHUNK_SIZE) * this.GCS_CHUNK_SIZE;
13763
13772
  if (sendableSize === 0) {
13764
13773
  console.log("[BackgroundUpload] Dados insuficientes para atingir 256KB. Aguardando novo chunk...");
13765
13774
  this.isProcessing = false;
@@ -13768,9 +13777,14 @@ var BackgroundUploadService = class _BackgroundUploadService {
13768
13777
  } else {
13769
13778
  totalSizeForHeader = virtualStart;
13770
13779
  }
13771
- const blobToSend = fullBlob.slice(0, sendableSize);
13780
+ const payload = sendableSize === combined.byteLength ? combined : combined.subarray(0, sendableSize);
13772
13781
  try {
13773
- await this.uploadData(blobToSend, mimeType, finalChunkIndex, totalSizeForHeader);
13782
+ await this.uploadData(
13783
+ payload.byteLength > 0 ? payload : null,
13784
+ mimeType,
13785
+ finalChunkIndex,
13786
+ totalSizeForHeader
13787
+ );
13774
13788
  for (const meta of chunksWithMeta) {
13775
13789
  if (meta.chunk.uploaded === 0 && meta.end < this.currentOffset) {
13776
13790
  await this.chunkStorage.markAsUploaded(meta.chunk.id);
@@ -13781,7 +13795,10 @@ var BackgroundUploadService = class _BackgroundUploadService {
13781
13795
  }
13782
13796
  if (this.config.cleanAfterUpload) {
13783
13797
  const chunksToClear = chunksWithMeta.filter((meta) => meta.chunk.uploaded === 1 || meta.chunk.uploaded === 0 && meta.end < this.currentOffset);
13784
- const sizePurged = chunksToClear.reduce((acc, meta) => acc + meta.chunk.blob.size, 0);
13798
+ const sizePurged = chunksToClear.reduce(
13799
+ (acc, meta) => acc + meta.chunk.arrayBuffer.byteLength,
13800
+ 0
13801
+ );
13785
13802
  await this.chunkStorage.clearUploadedChunks(this.proctoringId);
13786
13803
  if (sizePurged > 0) {
13787
13804
  this.totalBytesPurged += sizePurged;
@@ -13805,7 +13822,8 @@ var BackgroundUploadService = class _BackgroundUploadService {
13805
13822
  /**
13806
13823
  * Faz o upload bruto de dados para a sessão GCS.
13807
13824
  */
13808
- async uploadData(blob, mimeType, chunkIndex, totalSize) {
13825
+ async uploadData(body, mimeType, chunkIndex, totalSize) {
13826
+ var _a2;
13809
13827
  const fileName = `EP_${this.proctoringId}_camera_0.webm`;
13810
13828
  if (!this.sessionUrl) {
13811
13829
  const initiateUrl = await this.backend.initiateUpload(this.token, `${this.proctoringId}/${fileName}`, mimeType);
@@ -13836,16 +13854,28 @@ var BackgroundUploadService = class _BackgroundUploadService {
13836
13854
  } else {
13837
13855
  console.log(`[BackgroundUpload] Usando sess\xE3o GCS existente: ${this.sessionUrl}`);
13838
13856
  }
13857
+ const size = (_a2 = body == null ? void 0 : body.byteLength) != null ? _a2 : 0;
13839
13858
  const start = this.currentOffset;
13840
- const end = start + blob.size - 1;
13859
+ const end = start + size - 1;
13841
13860
  const totalHeader = totalSize !== void 0 ? totalSize.toString() : "*";
13842
- const contentRangeHeader = blob.size === 0 && totalSize !== void 0 ? `bytes */${totalHeader}` : `bytes ${start}-${end}/${totalHeader}`;
13843
- console.log(`[BackgroundUpload] Enviando ${blob.size > 0 ? "dados" : "finaliza\xE7\xE3o"}: ${contentRangeHeader} (Size: ${blob.size})`);
13861
+ const contentRangeHeader = size === 0 && totalSize !== void 0 ? `bytes */${totalHeader}` : `bytes ${start}-${end}/${totalHeader}`;
13862
+ console.log(
13863
+ `[BackgroundUpload] Enviando ${size > 0 ? "dados" : "finaliza\xE7\xE3o"}: ${contentRangeHeader} (Size: ${size})`
13864
+ );
13865
+ let uploadBody = null;
13866
+ if (size > 0 && body) {
13867
+ const raw = body.buffer;
13868
+ if (raw instanceof ArrayBuffer) {
13869
+ uploadBody = body.byteOffset === 0 && body.byteLength === raw.byteLength ? raw : raw.slice(body.byteOffset, body.byteOffset + body.byteLength);
13870
+ } else {
13871
+ uploadBody = new ArrayBuffer(body.byteLength);
13872
+ new Uint8Array(uploadBody).set(body);
13873
+ }
13874
+ }
13844
13875
  const response = await fetch(this.sessionUrl, {
13845
13876
  method: "PUT",
13846
13877
  headers: { "Content-Range": contentRangeHeader },
13847
- body: blob.size > 0 ? blob : null
13848
- // Usa null para garantir corpo vazio se necessário
13878
+ body: uploadBody
13849
13879
  });
13850
13880
  console.log(`[BackgroundUpload] Resposta GCS (uploadData): ${response.status}`);
13851
13881
  if (response.status !== 200 && response.status !== 201 && response.status !== 308) {
@@ -13858,13 +13888,13 @@ var BackgroundUploadService = class _BackgroundUploadService {
13858
13888
  const lastByte = parseInt(rangeHeader.split("-")[1], 10);
13859
13889
  this.currentOffset = lastByte + 1;
13860
13890
  } else {
13861
- this.currentOffset += blob.size;
13891
+ this.currentOffset += size;
13862
13892
  }
13863
13893
  this.saveSessionState();
13864
13894
  trackers.registerUploadFile(
13865
13895
  this.proctoringId,
13866
13896
  `GCS Stream Upload
13867
- Size: ${blob.size}
13897
+ Size: ${size}
13868
13898
  Range: ${start}-${end}
13869
13899
  Last Index: ${chunkIndex}`,
13870
13900
  "CameraChunk"
@@ -14407,10 +14437,11 @@ Setting: ${JSON.stringify(settings, null, 2)}`
14407
14437
  const savePromise = (async () => {
14408
14438
  var _a2;
14409
14439
  try {
14440
+ const arrayBuffer = await blob.arrayBuffer();
14410
14441
  await this.chunkStorage.saveChunk({
14411
14442
  proctoringId: this.proctoringId,
14412
14443
  chunkIndex: this.chunkIndex,
14413
- blob,
14444
+ arrayBuffer,
14414
14445
  timestamp: Date.now(),
14415
14446
  uploaded: 0,
14416
14447
  mimeType: ((_a2 = this.recorderOptions) == null ? void 0 : _a2.mimeType) || "video/webm"
@@ -16352,8 +16383,8 @@ var CapturePhoto = class {
16352
16383
  }
16353
16384
  };
16354
16385
 
16355
- // src/extension/extensionEasyProctor.ts
16356
- var ExtensionEasyProctor = class {
16386
+ // src/extension/extension.ts
16387
+ var Extension = class {
16357
16388
  constructor() {
16358
16389
  this.hasExtension = false;
16359
16390
  this.tryes = 0;
@@ -16398,89 +16429,6 @@ var ExtensionEasyProctor = class {
16398
16429
  }
16399
16430
  };
16400
16431
 
16401
- // src/extension/extensionEasyCatcher.ts
16402
- var ExtensionEasyCatcher = class {
16403
- constructor(options) {
16404
- this.hasExtension = false;
16405
- this.tryes = 0;
16406
- this.responseStart = false;
16407
- this.options = options || {};
16408
- }
16409
- /**
16410
- * Verifica se a extensão está instalada e ativa.
16411
- * Retorna o número da versão se encontrada, ou lança erro após timeout.
16412
- */
16413
- checkExtensionInstalled(timeoutMs = 2e3) {
16414
- return new Promise((resolve, reject) => {
16415
- let handled = false;
16416
- const handler = (event) => {
16417
- if (event.source === window && event.data.sender === "easyproctor-extension" && event.data.message_name === "version") {
16418
- handled = true;
16419
- window.removeEventListener("message", handler);
16420
- resolve(event.data.message);
16421
- }
16422
- };
16423
- window.addEventListener("message", handler);
16424
- window.postMessage({
16425
- type: "easycatcher",
16426
- func: "verifyExtensionEasycatcher"
16427
- }, "*");
16428
- setTimeout(() => {
16429
- if (!handled) {
16430
- window.removeEventListener("message", handler);
16431
- reject(new Error("Extens\xE3o n\xE3o detectada ou n\xE3o respondeu."));
16432
- }
16433
- }, timeoutMs);
16434
- });
16435
- }
16436
- /**
16437
- * Solicita o JSON da sessão atual capturado pela extensão.
16438
- */
16439
- getSessionData(timeoutMs = 5e3) {
16440
- return new Promise((resolve, reject) => {
16441
- let handled = false;
16442
- const handler = (event) => {
16443
- if (event.source === window && event.data.sender === "easyproctor-extension" && event.data.message_name === "data_response") {
16444
- handled = true;
16445
- window.removeEventListener("message", handler);
16446
- resolve(event.data.payload);
16447
- }
16448
- };
16449
- window.addEventListener("message", handler);
16450
- window.postMessage({
16451
- type: "easycatcher",
16452
- func: "getDataExtensionEasycatcher"
16453
- }, "*");
16454
- setTimeout(() => {
16455
- if (!handled) {
16456
- window.removeEventListener("message", handler);
16457
- reject(new Error("Timeout ao aguardar dados da extens\xE3o."));
16458
- }
16459
- }, timeoutMs);
16460
- });
16461
- }
16462
- start() {
16463
- return new Promise((resolve, reject) => {
16464
- let handled = false;
16465
- const handler = (event) => {
16466
- if (event.source === window && event.data.sender === "easyproctor-extension" && event.data.message_name === "started_confirmed") {
16467
- handled = true;
16468
- window.removeEventListener("message", handler);
16469
- resolve(true);
16470
- }
16471
- };
16472
- window.addEventListener("message", handler);
16473
- window.postMessage({ type: "easycatcher", func: "startExtensionEasycatcher" }, "*");
16474
- setTimeout(() => {
16475
- if (!handled) {
16476
- window.removeEventListener("message", handler);
16477
- reject(new Error("Timeout: Extens\xE3o n\xE3o confirmou o in\xEDcio."));
16478
- }
16479
- }, 3e3);
16480
- });
16481
- }
16482
- };
16483
-
16484
16432
  // src/modules/onChangeDevices.ts
16485
16433
  var onChangeDevices = class {
16486
16434
  constructor(repositoryDevices, proctoringId2, sessionOptions, allRecorders) {
@@ -23655,10 +23603,7 @@ var Proctoring = class {
23655
23603
  if (this.context.token === void 0) {
23656
23604
  throw TOKEN_MISSING;
23657
23605
  }
23658
- if (options.useChallenge) {
23659
- this.extensionEasycatcher = new ExtensionEasyCatcher();
23660
- }
23661
- this.extension = new ExtensionEasyProctor();
23606
+ this.extension = new Extension();
23662
23607
  this.extension.addEventListener();
23663
23608
  const baseURL = this.backend.selectBaseUrl(this.context.type);
23664
23609
  const devices = await enumarateDevices();
@@ -24042,61 +23987,6 @@ Error: ` + error
24042
23987
  _screenStream: (_a2 = this.allRecorders.screenRecorder) == null ? void 0 : _a2.screenStream
24043
23988
  };
24044
23989
  }
24045
- async startChallenge(templateId) {
24046
- var _a2;
24047
- if (!this.sessionOptions.useChallenge) {
24048
- throw new Error("useChallenge is set as false on start method");
24049
- }
24050
- await this.extensionEasycatcher.checkExtensionInstalled().catch((err) => {
24051
- throw new Error("EasyCatcher Extension is not installed");
24052
- });
24053
- this.extensionEasycatcher.start();
24054
- const start = Date.now() - ((_a2 = this.allRecorders.cameraRecorder.getStartTime()) == null ? void 0 : _a2.getTime()) || 0;
24055
- await this.backend.startChallenge({
24056
- proctoringId: this.proctoringId,
24057
- templateId,
24058
- start
24059
- }).then((resp) => {
24060
- console.log(resp);
24061
- this.challengeId = resp.id;
24062
- }).catch((reason) => {
24063
- trackers.registerError(
24064
- this.proctoringId,
24065
- "N\xE3o foi poss\xEDvel iniciar desafio!"
24066
- );
24067
- throw reason;
24068
- });
24069
- this.isChallengeRunning = true;
24070
- }
24071
- async stopChallenge() {
24072
- var _a2;
24073
- if (!this.isChallengeRunning) {
24074
- throw new Error("Challenge not started");
24075
- }
24076
- try {
24077
- const sessionData = await this.extensionEasycatcher.getSessionData();
24078
- const end = Date.now() - ((_a2 = this.allRecorders.cameraRecorder.getStartTime()) == null ? void 0 : _a2.getTime()) || 0;
24079
- await this.backend.stopChallenge(
24080
- this.challengeId,
24081
- {
24082
- end,
24083
- data: sessionData
24084
- }
24085
- ).catch((reason) => {
24086
- trackers.registerError(
24087
- this.proctoringId,
24088
- "N\xE3o foi poss\xEDvel finalizar o desafio no backend!"
24089
- );
24090
- return void 0;
24091
- });
24092
- this.isChallengeRunning = false;
24093
- } catch (error) {
24094
- trackers.registerError(
24095
- this.proctoringId,
24096
- "Erro ao recuperar dados da extens\xE3o: " + error.message
24097
- );
24098
- }
24099
- }
24100
23990
  };
24101
23991
 
24102
23992
  // src/proctoring/SignTerm.ts
@@ -24325,8 +24215,6 @@ function useProctoring(proctoringOptions, enviromentConfig = "prod") {
24325
24215
  return originalStart(parameters2, videoOptions);
24326
24216
  };
24327
24217
  const finish = proctoring.finish.bind(proctoring);
24328
- const startChallenge = proctoring.startChallenge.bind(proctoring);
24329
- const stopChallenge = proctoring.stopChallenge.bind(proctoring);
24330
24218
  const pause = proctoring.pause.bind(proctoring);
24331
24219
  const resume = proctoring.resume.bind(proctoring);
24332
24220
  const onFocus = proctoring.setOnFocusCallback.bind(proctoring);
@@ -24351,8 +24239,6 @@ function useProctoring(proctoringOptions, enviromentConfig = "prod") {
24351
24239
  login,
24352
24240
  start,
24353
24241
  finish,
24354
- startChallenge,
24355
- stopChallenge,
24356
24242
  onFocus,
24357
24243
  onLostFocus,
24358
24244
  onChangeDevices: onChangeDevices2,
@@ -1,5 +1,5 @@
1
1
  import { ProctoringFinisherOptions } from "../proctoring/proctoring";
2
- export declare class ExtensionEasyProctor {
2
+ export declare class Extension {
3
3
  hasExtension: boolean;
4
4
  tryes: number;
5
5
  responseStart: boolean;