@incodetech/core 2.2.0-rc.8 → 2.3.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD_PARTY_NOTICES.txt +281 -0
- package/dist/BaseWasmProvider-Dyi6dKp1.d.ts +65 -0
- package/dist/{BrowserDiagnosticsCryptoProvider-DslcXorZ.esm.js → BrowserDiagnosticsCryptoProvider-C_9o3L2L.esm.js} +1 -1
- package/dist/{BrowserVisibilityObserverProvider-BX1BiLDK.esm.js → BrowserVisibilityObserverProvider-BrJN1B8A.esm.js} +2 -0
- package/dist/FaceDetectionProvider-DTetAE8H.esm.js +476 -0
- package/dist/FaceDetectionProvider-LdZ47bWy.d.ts +36 -0
- package/dist/{IIdCaptureCapability-DHTT3FC2.d.ts → IIdCaptureCapability-RNiFhvXR.d.ts} +7 -33
- package/dist/IWasmUtilCapability-CXXDA5l1.d.ts +159 -0
- package/dist/{MotionSensorProvider-DGiV77J_.esm.js → MotionSensorProvider-BgTYwg9L.esm.js} +1 -1
- package/dist/{deepsightService-DLVQS_RH.d.ts → StreamCanvasCapture-B3YT2Bt6.d.ts} +54 -41
- package/dist/{StreamCanvasCapture-D2XcXCZ4.esm.js → StreamCanvasCapture-C9jtgBdT.esm.js} +2 -2
- package/dist/{addressSearch-D1XpBdUS.esm.js → addressSearch-BRSu_aGA.esm.js} +1 -1
- package/dist/advanceableErrors-CpF2cBy6.esm.js +21 -0
- package/dist/ae-signature.d.ts +4 -2
- package/dist/ae-signature.esm.js +1 -1
- package/dist/antifraud.esm.js +2 -2
- package/dist/{antifraudManager-CQFNgSPt.esm.js → antifraudManager-Bg9ynGum.esm.js} +2 -2
- package/dist/{antifraudStateMachine-Bf_JVNwn.esm.js → antifraudStateMachine-BHxehiJZ.esm.js} +1 -1
- package/dist/{apiError-D4rZe9BR.esm.js → apiError-D0v5hFyN.esm.js} +14 -2
- package/dist/authentication.d.ts +3 -3
- package/dist/authentication.esm.js +2 -2
- package/dist/{authenticationManager-EfCuQy_Y.esm.js → authenticationManager-C4B4-29g.esm.js} +5 -5
- package/dist/{authenticationManager-BBMGTcwW.d.ts → authenticationManager-DXTIUcma.d.ts} +7 -1
- package/dist/{authenticationStateMachine-B9l3sHEg.esm.js → authenticationStateMachine-DJ0zUm-A.esm.js} +6 -62
- package/dist/avatar.d.ts +1 -2
- package/dist/avatar.esm.js +1 -1
- package/dist/{backCameraStream-CUeYm5eu.esm.js → backCameraStream-BOtyQowf.esm.js} +83 -22
- package/dist/{camera-_2sXMXiF.esm.js → camera-sIa9ceW2.esm.js} +19 -1
- package/dist/camera.esm.js +1 -1
- package/dist/{canvas-E1zGkel4.esm.js → canvas-BxFzWTt-.esm.js} +19 -0
- package/dist/certificate-issuance.d.ts +2 -302
- package/dist/certificate-issuance.esm.js +3 -66
- package/dist/certificateIssuanceManager-Bfvkq7Cy.esm.js +69 -0
- package/dist/certificateIssuanceManager-DCgEidHz.d.ts +312 -0
- package/dist/{certificateIssuanceStateMachine-D_R92TYu.esm.js → certificateIssuanceStateMachine-BBD5h8c4.esm.js} +1 -1
- package/dist/consent.d.ts +1 -1
- package/dist/consent.esm.js +2 -2
- package/dist/{consentManager-BxjpLZAG.esm.js → consentManager-B5Vqdez-.esm.js} +2 -2
- package/dist/{consentManager-3Pbtj-RV.d.ts → consentManager-uhDPdU6i.d.ts} +4 -4
- package/dist/{consentStateMachine-D9D4ON8Z.esm.js → consentStateMachine-DbUmqWgV.esm.js} +1 -1
- package/dist/createCameraCycleOwnership-DQ5-F2oW.esm.js +826 -0
- package/dist/{createFaceAvatar-DQKaRise.esm.js → createFaceAvatar-BNHdeFj8.esm.js} +2 -2
- package/dist/createFaceAvatar-BlcTYgJv.d.ts +497 -0
- package/dist/cross-document-data-match.esm.js +1 -1
- package/dist/{crossDocumentDataMatchManager-CGT0V6RV.esm.js → crossDocumentDataMatchManager-QMOGwHXR.esm.js} +2 -2
- package/dist/curp-validation.d.ts +1 -1
- package/dist/curp-validation.esm.js +2 -2
- package/dist/{curpValidationManager-6Nmkn5u1.esm.js → curpValidationManager-D1ppROcF.esm.js} +2 -2
- package/dist/{curpValidationManager-DVGr7Fq7.d.ts → curpValidationManager-SSKNrm5Z.d.ts} +1 -1
- package/dist/{curpValidationStateMachine-Ds7KMacK.esm.js → curpValidationStateMachine-DvUPC_8S.esm.js} +1 -1
- package/dist/custom-fields.d.ts +2 -114
- package/dist/custom-fields.esm.js +2 -232
- package/dist/custom-watchlist.d.ts +2 -51
- package/dist/custom-watchlist.esm.js +3 -70
- package/dist/customFieldsManager-2j_PBq4U.esm.js +264 -0
- package/dist/customFieldsManager-8-W2KY4n.d.ts +141 -0
- package/dist/customWatchlistManager-DUVrEdw9.esm.js +73 -0
- package/dist/customWatchlistManager-PBWHr_oM.d.ts +64 -0
- package/dist/{customWatchlistStateMachine-YWSgKLbF.esm.js → customWatchlistStateMachine-qZVgkKgP.esm.js} +1 -1
- package/dist/{deepsightLoader-DEcRUKfT.esm.js → deepsightLoader-Dm7ejW4v.esm.js} +27 -71
- package/dist/device.d.ts +25 -2
- package/dist/device.esm.js +69 -7
- package/dist/document-capture.d.ts +2 -2
- package/dist/document-capture.esm.js +2 -2
- package/dist/{documentCaptureManager-DsQQhWry.esm.js → documentCaptureManager-DR_Wv-3H.esm.js} +2 -2
- package/dist/{documentCaptureManager-B3t0ydtg.d.ts → documentCaptureManager-DensIj5F.d.ts} +83 -83
- package/dist/{documentCaptureStateMachine-BM4Ex_5x.esm.js → documentCaptureStateMachine-CWOATHfE.esm.js} +5 -5
- package/dist/dynamic-forms.d.ts +1 -1
- package/dist/dynamic-forms.esm.js +2 -2
- package/dist/{dynamicFormsManager-fhK0yINk.d.ts → dynamicFormsManager-D5R_uxLQ.d.ts} +25 -3
- package/dist/{dynamicFormsManager-CmvBSrzC.esm.js → dynamicFormsManager-Dt98SDfV.esm.js} +16 -5
- package/dist/{dynamicFormsStateMachine-C37Rtz1G.esm.js → dynamicFormsStateMachine-obKr4IIp.esm.js} +35 -3
- package/dist/ekyb.d.ts +1 -1
- package/dist/ekyb.esm.js +3 -3
- package/dist/{ekybManager-Bx6dG89U.esm.js → ekybManager-DNZKrKF3.esm.js} +2 -2
- package/dist/{ekybStateMachine-uscz9zIj.esm.js → ekybStateMachine-DjhHQXZ8.esm.js} +3 -3
- package/dist/ekyc.esm.js +2 -2
- package/dist/{ekycManager-DgT48ky6.esm.js → ekycManager-CmQBpeiI.esm.js} +2 -2
- package/dist/{ekycStateMachine-CQwqiR-R.esm.js → ekycStateMachine-CmdW2gVm.esm.js} +2 -2
- package/dist/electronic-signature.d.ts +3 -3
- package/dist/electronic-signature.esm.js +2 -2
- package/dist/electronicSignatureManager-Ds-KEVTq.d.ts +2786 -0
- package/dist/{electronicSignatureManager-_QiHi1U5.esm.js → electronicSignatureManager-DzulxM4_.esm.js} +357 -51
- package/dist/email.esm.js +2 -2
- package/dist/{emailManager-BY0jeYwR.esm.js → emailManager-B5ek_UfM.esm.js} +2 -2
- package/dist/{emailStateMachine-Crw8QVmc.esm.js → emailStateMachine-CyPFZ7dW.esm.js} +1 -1
- package/dist/{endpoints-CCzL3XD_.esm.js → endpoints-D3B9mUHh.esm.js} +24 -7
- package/dist/{events-DYiyoSlx.esm.js → events-ijlbX_Wx.esm.js} +2 -2
- package/dist/events.d.ts +1 -1
- package/dist/events.esm.js +1 -1
- package/dist/extensibility.d.ts +24 -64
- package/dist/extensibility.esm.js +35 -29
- package/dist/face-match.esm.js +2 -2
- package/dist/{faceCaptureManagerFactory-BxWPpxyd.d.ts → faceCaptureManagerFactory-CvtqcLxs.d.ts} +87 -54
- package/dist/{faceCaptureManagerFactory-Bkueb8mk.esm.js → faceCaptureManagerFactory-pCmG4MeF.esm.js} +68 -7
- package/dist/faceCaptureSetup-BSextack.esm.js +2106 -0
- package/dist/{faceMatchManager-Ri4UbNz0.esm.js → faceMatchManager-Caal2zyV.esm.js} +2 -2
- package/dist/{faceMatchStateMachine-20DdZ3jg.esm.js → faceMatchStateMachine-BUc5FXYy.esm.js} +1 -1
- package/dist/{feature-management-B3Uygq6K.esm.js → feature-management-B0sGlozZ.esm.js} +32 -7
- package/dist/feature-management.d.ts +1 -1
- package/dist/feature-management.esm.js +1 -1
- package/dist/field-comparison.esm.js +1 -1
- package/dist/{fieldComparisonManager-Cg6kPQQx.esm.js → fieldComparisonManager-BIs6HPJG.esm.js} +2 -2
- package/dist/fiscal-qr.d.ts +2 -56
- package/dist/fiscal-qr.esm.js +2 -308
- package/dist/fiscalQrManager-Bp_-3LJr.esm.js +34131 -0
- package/dist/fiscalQrManager-CHcBJwUM.d.ts +68 -0
- package/dist/flow-events.d.ts +1 -1
- package/dist/flow.d.ts +212 -185
- package/dist/flow.esm.js +119 -30
- package/dist/{flowCompletionService-UakxNaeg.esm.js → flowCompletionService-CLtbWhSK.esm.js} +2 -2
- package/dist/{flowServices-CD5m8HqZ.esm.js → flowServices-B5FwukTQ.esm.js} +91 -26
- package/dist/geolocation.esm.js +2 -2
- package/dist/{geolocationManager-Bz6wJrfI.esm.js → geolocationManager-DIw-xq9a.esm.js} +2 -2
- package/dist/{geolocationStateMachine-psEJIVjN.esm.js → geolocationStateMachine-DpG0TFOU.esm.js} +3 -3
- package/dist/getBrowser-CBiibsL-.esm.js +19 -0
- package/dist/{getBrowser-DNrQeL4T.esm.js → getBrowser-Cbe1C4Tn.esm.js} +2 -1
- package/dist/{getDeviceClass-9y-kbVDw.esm.js → getDeviceClass-5NYZg9s6.esm.js} +2 -2
- package/dist/getParsedUserAgent-B2iFDql1.esm.js +1278 -0
- package/dist/government-validation.d.ts +2 -85
- package/dist/government-validation.esm.js +3 -120
- package/dist/governmentValidationManager-D02vT4yY.d.ts +63 -0
- package/dist/governmentValidationManager-TjC9iVjH.esm.js +79 -0
- package/dist/governmentValidationStateMachine-D1ZnEqdd.esm.js +54 -0
- package/dist/home.d.ts +1 -1
- package/dist/home.esm.js +1 -1
- package/dist/id-ocr.d.ts +2 -2
- package/dist/id-ocr.esm.js +2 -2
- package/dist/id-selfie-flow.d.ts +3 -2
- package/dist/id-selfie-flow.esm.js +11 -10
- package/dist/id-verification.esm.js +2 -2
- package/dist/id.d.ts +29 -5
- package/dist/id.esm.js +48 -46
- package/dist/idCaptureDefaults-BcxjQDI3.esm.js +484 -0
- package/dist/{idCaptureManager-CqrqSjJV.d.ts → idCaptureManager-CvmHOWWd.d.ts} +227 -39
- package/dist/{idCaptureManager-BJAquKfp.esm.js → idCaptureManager-Vby8oYqh.esm.js} +259 -46
- package/dist/{idCaptureServices-CM6ki4IH.esm.js → idCaptureServices-CJIxD9ep.esm.js} +342 -31
- package/dist/idCaptureStateMachine-CmqihkUy.esm.js +5343 -0
- package/dist/{idOcrManager-DXc_xRN7.d.ts → idOcrManager-BF_cXZq8.d.ts} +1 -1
- package/dist/{idOcrManager-BIQYQXXj.esm.js → idOcrManager-DHU22hVn.esm.js} +2 -2
- package/dist/{idOcrStateMachine-cSxzHpHt.esm.js → idOcrStateMachine-33UvRAHE.esm.js} +1 -1
- package/dist/{idVerificationManager-JpV_SAsl.esm.js → idVerificationManager-CyaixD0D.esm.js} +2 -2
- package/dist/{idVerificationStateMachine-nPeUNyFq.esm.js → idVerificationStateMachine-BPGrQZEm.esm.js} +1 -1
- package/dist/identity-reuse.esm.js +2 -2
- package/dist/{identityReuseManager-kNCg9AbD.esm.js → identityReuseManager-CWaNHBO3.esm.js} +2 -2
- package/dist/{identityReuseStateMachine-DyulxDjP.esm.js → identityReuseStateMachine-CQgnATo5.esm.js} +1 -1
- package/dist/{index-CLMF0QLQ.d.ts → index-DLcJT5YP.d.ts} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/{invokeOnCaptureCallback-GpvMuz9o.esm.js → invokeOnCaptureCallback-BjzPjJ_p.esm.js} +1 -1
- package/dist/mandatory-consent.d.ts +2 -2
- package/dist/mandatory-consent.esm.js +2 -2
- package/dist/{mandatoryConsentManager-DyPzUmsZ.d.ts → mandatoryConsentManager-CJSyhTpi.d.ts} +5 -5
- package/dist/{mandatoryConsentManager-B4Niyg_u.esm.js → mandatoryConsentManager-Du-m-tZ_.esm.js} +2 -2
- package/dist/{mandatoryConsentStateMachine-B4-1u-L8.esm.js → mandatoryConsentStateMachine-DSDAk7WZ.esm.js} +1 -1
- package/dist/multipartRecordingService-B3C_zlev.esm.js +594 -0
- package/dist/{permissionGuards-KINpmKtI.esm.js → permissionGuards-uYZYFu4J.esm.js} +1 -1
- package/dist/{permissionServices-UvUcOSRb.esm.js → permissionServices-Bj_fyWtv.esm.js} +5 -5
- package/dist/personhood.d.ts +6 -5
- package/dist/personhood.esm.js +10 -10
- package/dist/phone.esm.js +2 -2
- package/dist/{phoneManager-FsJ0W2Ei.esm.js → phoneManager-N1-sbrY4.esm.js} +2 -2
- package/dist/{phoneStateMachine-Ba0wKHyX.esm.js → phoneStateMachine-jl8LJKCo.esm.js} +1 -1
- package/dist/{platform-BJrm5nzZ.esm.js → platform-DkcRc9JV.esm.js} +29 -1
- package/dist/qe-signature.d.ts +5 -3
- package/dist/qe-signature.esm.js +2 -2
- package/dist/recordingsRepository-CCWy13M-.esm.js +72 -0
- package/dist/redirect-to-mobile.esm.js +2 -2
- package/dist/{redirectToMobileManager-y4VQB11M.esm.js → redirectToMobileManager-DsFzdTwA.esm.js} +2 -2
- package/dist/{redirectToMobileStateMachine-Cyv2x0PP.esm.js → redirectToMobileStateMachine-v3otpT-L.esm.js} +1 -1
- package/dist/{rolldown-runtime-FZ4Itg2g.esm.js → rolldown-runtime-FDOR9p9I.esm.js} +1 -19
- package/dist/{runChildModule-BR2RIfRg.esm.js → runChildModule-TuyGE00X.esm.js} +3 -21
- package/dist/safeStorage-B-trhxg6.esm.js +423 -0
- package/dist/{sdkVersion-BWOdgLZ1.esm.js → sdkVersion-CLxKvdyz.esm.js} +1 -1
- package/dist/selfie.d.ts +5 -5
- package/dist/selfie.esm.js +14 -76
- package/dist/{selfieErrorUtils-C2PYBVsp.esm.js → selfieErrorUtils-C77GXJH6.esm.js} +30 -4
- package/dist/{selfieManager-BlImAV-k.esm.js → selfieManager-CihVnODO.esm.js} +5 -5
- package/dist/{selfieManager-DwlCppg0.d.ts → selfieManager-D1KRJ39M.d.ts} +8 -11
- package/dist/selfieStateMachine-fwMmNtOi.esm.js +69 -0
- package/dist/{session-Bp17qJsu.esm.js → session-BHIeAamR.esm.js} +4 -5
- package/dist/session.d.ts +21 -11
- package/dist/session.esm.js +5 -5
- package/dist/{sessionInitializer-CcqQD9Q4.esm.js → sessionInitializer-BLoK7SP9.esm.js} +187 -68
- package/dist/{setup-BgoWtvIS.d.ts → setup-Cv-JM9QC.d.ts} +63 -69
- package/dist/{setup-CXj5ozZN.esm.js → setup-msLybMbC.esm.js} +226 -100
- package/dist/signature.esm.js +2 -2
- package/dist/{signatureManager-Ca43yhwk.esm.js → signatureManager-ChsB-nMD.esm.js} +2 -2
- package/dist/{signatureStateMachine-K1LMRrxG.esm.js → signatureStateMachine-BHPwkJZS.esm.js} +1 -1
- package/dist/{src-0Jurt29N.esm.js → src-35ekGRzK.esm.js} +1 -1
- package/dist/{stats-B0nFKawG.esm.js → stats-DkK-f8JT.esm.js} +1 -1
- package/dist/stats.esm.js +1 -1
- package/dist/{trueSightService-D05SY_Ij.esm.js → trueSightService-CKrrfV0Q.esm.js} +7 -7
- package/dist/trust-graph.esm.js +1 -1
- package/dist/{types-BX_XkMsQ2.d.ts → types-9_esGTPj.d.ts} +1 -1
- package/dist/types-BT_Oalip.d.ts +1 -0
- package/dist/{types-DelMqZLe.d.ts → types-BjSly8cp.d.ts} +1 -1
- package/dist/{types-Hmd7U0JA.d.ts → types-CM-jtjJ2.d.ts} +6 -81
- package/dist/{types-Bdf8_LYB2.d.ts → types-CjKBS37a2.d.ts} +303 -13
- package/dist/{types-DVmXIdzW.d.ts → types-D0gekt4U.d.ts} +38 -5
- package/dist/types-DgDvvzg0.d.ts +10 -0
- package/dist/{types-KPvmag_B.d.ts → types-Do5rEXij.d.ts} +7 -4
- package/dist/types-ZT1XFIJ8.d.ts +6 -0
- package/dist/video-selfie.d.ts +59 -35
- package/dist/video-selfie.esm.js +510 -601
- package/dist/{videoSelfieCameraWarmer-BhTWYfGn.esm.js → videoSelfieCameraWarmer-CB1IzZkt.esm.js} +14 -153
- package/dist/videoSelfieFlowModuleMachine-BUe2uACW.esm.js +32 -0
- package/dist/{videoSelfieStepDetector-D3oo2ofo.d.ts → videoSelfieStepDetector-5YHFe0Mq.d.ts} +21 -5
- package/dist/virtualCameraCheck-WOloJ-do.esm.js +48 -0
- package/dist/warmup-CUUnwYxe.esm.js +714 -0
- package/dist/warmup-Cis2p6O0.d.ts +128 -0
- package/dist/wasm.d.ts +30 -6
- package/dist/wasm.esm.js +36 -4
- package/dist/{wasmDsFlagSync-BqUCwLY8.esm.js → wasmDsFlagSync-B2e8p268.esm.js} +2 -2
- package/dist/{wasmWebClient-DM8lkb0z.esm.js → wasmWebClient-B7baE-Wf.esm.js} +358 -28
- package/dist/watchlist-for-business.d.ts +2 -78
- package/dist/watchlist-for-business.esm.js +3 -102
- package/dist/watchlist.esm.js +2 -2
- package/dist/watchlistForBusinessManager-CpuuB1J2.esm.js +107 -0
- package/dist/watchlistForBusinessManager-CsnJnG-C.d.ts +99 -0
- package/dist/{watchlistForBusinessStateMachine-CxFnlshm.esm.js → watchlistForBusinessStateMachine-DEzgjz7C.esm.js} +13 -6
- package/dist/{watchlistManager-LoNZH9qm.esm.js → watchlistManager-CI8BHFob.esm.js} +2 -2
- package/dist/{watchlistStateMachine-DIKQDoUT.esm.js → watchlistStateMachine-DvOby3a-.esm.js} +1 -1
- package/dist/workflow.d.ts +12 -8
- package/dist/workflow.esm.js +48 -39
- package/package.json +4 -10
- package/dist/BrowserStorageProvider-k-FDkC4W.esm.js +0 -67
- package/dist/FaceDetectionProvider-Mh6q3EbA.d.ts +0 -349
- package/dist/IFaceAvatarCapability-BrL19G0s.d.ts +0 -23
- package/dist/IStorageCapability-ORkQfK3F.d.ts +0 -242
- package/dist/OpenViduRecordingProvider-Du98qevC.esm.js +0 -85
- package/dist/createFaceAvatar-BEj18KXi.d.ts +0 -50
- package/dist/document-upload.d.ts +0 -325
- package/dist/document-upload.esm.js +0 -197
- package/dist/electronicSignatureManager-CcUXQZS7.d.ts +0 -1300
- package/dist/faceCaptureSetup-BECAis8R.esm.js +0 -863
- package/dist/getBrowser-Cb8Zgrgp.esm.js +0 -7
- package/dist/getParsedUserAgent-pJjATANs.esm.js +0 -1622
- package/dist/governmentValidationStateMachine-CK9DrZXX.esm.js +0 -226
- package/dist/idCaptureDefaults-WeHbQM7W.esm.js +0 -225
- package/dist/idCaptureStateMachine-fi-Gq1AH.esm.js +0 -3342
- package/dist/lib-DAyUtOTj.esm.js +0 -12420
- package/dist/manualReviewService-D4IkipnN.esm.js +0 -15
- package/dist/mediaRecorderOptions-dALSV8af.esm.js +0 -40
- package/dist/onDeviceFaceResults-CB62pUQf.esm.js +0 -646
- package/dist/openviduLazy-CCDpFWg1.esm.js +0 -10
- package/dist/recordingService-BRgmVnUT.esm.js +0 -329
- package/dist/safeStorage-Ep56I-f_.esm.js +0 -982
- package/dist/selfieStateMachine-CPXEC4wV.esm.js +0 -55
- package/dist/trueSight-CY0Ibfm9.esm.js +0 -1
- package/dist/types-EELWyWpd.d.ts +0 -6
- package/dist/types-Vb4P9ovf.d.ts +0 -22
- package/dist/warmup-Dv2alr2-.d.ts +0 -82
- package/dist/wasmDefaults-DTUrftxR.esm.js +0 -125
- package/dist/{Face2DProvider-UUQt_vRC.esm.js → Face2DProvider-BF48sz5c.esm.js} +1 -1
- package/dist/{PrivacyLensProvider-D8PS7AJa.esm.js → PrivacyLensProvider-EwnC_C5n.esm.js} +1 -1
- /package/dist/{types-BfgmV7s72.d.ts → types-BfgmV7s7.d.ts} +0 -0
- /package/dist/{types-CJ7Yl9K-2.d.ts → types-CJ7Yl9K-.d.ts} +0 -0
|
@@ -0,0 +1,594 @@
|
|
|
1
|
+
import { t as BrowserTimerProvider } from "./BrowserTimerProvider-BXhgNxLt.esm.js";
|
|
2
|
+
import { t as api } from "./api-Bx3gKW_y.esm.js";
|
|
3
|
+
import { t as endpoints } from "./endpoints-D3B9mUHh.esm.js";
|
|
4
|
+
import { a as isIOS } from "./platform-DkcRc9JV.esm.js";
|
|
5
|
+
//#region ../infra/src/media/mediaRecorderOptions.ts
|
|
6
|
+
/**
|
|
7
|
+
* Picks a `MediaRecorder` mime type the current browser actually supports.
|
|
8
|
+
* WebM avoids Safari's fragmented-MP4 unknown-duration metadata on versions
|
|
9
|
+
* that can record it; older Safari versions fall back to MP4. Returns '' when
|
|
10
|
+
* none match.
|
|
11
|
+
*/
|
|
12
|
+
function getSupportedMediaRecorderMimeType() {
|
|
13
|
+
for (const type of [
|
|
14
|
+
"video/webm",
|
|
15
|
+
"video/webm;codecs=vp9",
|
|
16
|
+
"video/webm;codecs=vp8",
|
|
17
|
+
"video/mp4"
|
|
18
|
+
]) if (MediaRecorder.isTypeSupported(type)) return type;
|
|
19
|
+
return "";
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* `MediaRecorder` options tuned per platform — a higher bitrate on iOS, lower
|
|
23
|
+
* elsewhere — paired with the supported mime type.
|
|
24
|
+
*/
|
|
25
|
+
function getAdaptiveMediaRecorderOptions() {
|
|
26
|
+
const mimeType = getSupportedMediaRecorderMimeType();
|
|
27
|
+
if (isIOS()) return {
|
|
28
|
+
mimeType,
|
|
29
|
+
videoBitsPerSecond: 1e6,
|
|
30
|
+
bitsPerSecond: 1e6
|
|
31
|
+
};
|
|
32
|
+
return {
|
|
33
|
+
mimeType,
|
|
34
|
+
videoBitsPerSecond: 5e5,
|
|
35
|
+
bitsPerSecond: 5e5
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region ../infra/src/providers/browser/MultipartRecordingProvider.ts
|
|
40
|
+
/**
|
|
41
|
+
* How often `MediaRecorder` hands us buffered data (incremental blobs).
|
|
42
|
+
* 500 ms keeps each blob — and therefore each upload chunk — small: less
|
|
43
|
+
* tail lost when a session is interrupted, and a smaller first blob (init
|
|
44
|
+
* header + keyframe), which is the largest and most timeout-prone chunk.
|
|
45
|
+
* Not lower: request rate doubles per halving, and browsers stop honoring
|
|
46
|
+
* very small timeslices reliably.
|
|
47
|
+
*/
|
|
48
|
+
const TIMESLICE_MS = 500;
|
|
49
|
+
/**
|
|
50
|
+
* Encoder target for the full video-selfie session. Higher than the
|
|
51
|
+
* short-clip liveness path (0.5–1 Mbps) so a multi-minute session keeps
|
|
52
|
+
* usable quality. It's a ceiling — a still scene still encodes well below it.
|
|
53
|
+
*/
|
|
54
|
+
const VIDEO_BITS_PER_SECOND = 25e5;
|
|
55
|
+
/**
|
|
56
|
+
* Records a stream and emits every `MediaRecorder` timeslice blob as its own
|
|
57
|
+
* part, in order. Each blob is a whole container fragment (WebM cluster /
|
|
58
|
+
* fMP4 `moof`+`mdat`), which is the property the video-selfie-service's
|
|
59
|
+
* gap-splicing depends on — parts must never cut a fragment at a byte
|
|
60
|
+
* offset. The service stages sub-5 MiB chunks and combines them server-side,
|
|
61
|
+
* so emitting the smallest whole-fragment unit (~0.5 s of video) maximizes
|
|
62
|
+
* what an interrupted session can salvage.
|
|
63
|
+
*
|
|
64
|
+
* Page-lifecycle orchestration lives in Core: it pauses this recorder before a
|
|
65
|
+
* backgrounded camera can stall, restores the camera/compositor, and only then
|
|
66
|
+
* resumes this same media container.
|
|
67
|
+
*/
|
|
68
|
+
var MultipartRecordingProvider = class {
|
|
69
|
+
constructor() {
|
|
70
|
+
this.mediaRecorder = null;
|
|
71
|
+
this._isRecording = false;
|
|
72
|
+
this._hasError = false;
|
|
73
|
+
this._error = null;
|
|
74
|
+
this.mimeType = "";
|
|
75
|
+
this.partNumber = 0;
|
|
76
|
+
this.onPart = null;
|
|
77
|
+
}
|
|
78
|
+
get isRecording() {
|
|
79
|
+
return this._isRecording;
|
|
80
|
+
}
|
|
81
|
+
get hasError() {
|
|
82
|
+
return this._hasError;
|
|
83
|
+
}
|
|
84
|
+
get error() {
|
|
85
|
+
return this._error;
|
|
86
|
+
}
|
|
87
|
+
startRecording(stream, onPart) {
|
|
88
|
+
this.reset();
|
|
89
|
+
this.partNumber = 0;
|
|
90
|
+
this.onPart = onPart;
|
|
91
|
+
try {
|
|
92
|
+
this.mimeType = getSupportedMediaRecorderMimeType();
|
|
93
|
+
const recorder = new MediaRecorder(stream.clone(), {
|
|
94
|
+
mimeType: this.mimeType,
|
|
95
|
+
videoBitsPerSecond: VIDEO_BITS_PER_SECOND
|
|
96
|
+
});
|
|
97
|
+
recorder.ondataavailable = (event) => {
|
|
98
|
+
if (event.data.size > 0 && this.onPart) {
|
|
99
|
+
this.partNumber += 1;
|
|
100
|
+
this.onPart({
|
|
101
|
+
chunk: event.data,
|
|
102
|
+
partNumber: this.partNumber
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
recorder.onerror = (event) => {
|
|
107
|
+
const detail = event instanceof ErrorEvent && event.error instanceof Error ? event.error.message : event.type;
|
|
108
|
+
this._error = `Recording error: ${detail}`;
|
|
109
|
+
this._isRecording = false;
|
|
110
|
+
this._hasError = true;
|
|
111
|
+
};
|
|
112
|
+
recorder.start(TIMESLICE_MS);
|
|
113
|
+
this.mediaRecorder = recorder;
|
|
114
|
+
this._isRecording = true;
|
|
115
|
+
this._error = null;
|
|
116
|
+
this._hasError = false;
|
|
117
|
+
} catch (err) {
|
|
118
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
119
|
+
this._error = `Failed to start recording: ${detail}`;
|
|
120
|
+
this._hasError = true;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
pauseRecording() {
|
|
124
|
+
const recorder = this.mediaRecorder;
|
|
125
|
+
if (!recorder || !this._isRecording || this._hasError) return false;
|
|
126
|
+
if (recorder.state === "paused") return true;
|
|
127
|
+
if (recorder.state !== "recording") return false;
|
|
128
|
+
try {
|
|
129
|
+
recorder.pause();
|
|
130
|
+
return true;
|
|
131
|
+
} catch (err) {
|
|
132
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
133
|
+
this._error = `Failed to pause recording: ${detail}`;
|
|
134
|
+
this._hasError = true;
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
resumeRecording() {
|
|
139
|
+
const recorder = this.mediaRecorder;
|
|
140
|
+
if (!recorder || !this._isRecording || this._hasError) return false;
|
|
141
|
+
if (recorder.state === "recording") return true;
|
|
142
|
+
if (recorder.state !== "paused") return false;
|
|
143
|
+
try {
|
|
144
|
+
recorder.resume();
|
|
145
|
+
return true;
|
|
146
|
+
} catch (err) {
|
|
147
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
148
|
+
this._error = `Failed to resume recording: ${detail}`;
|
|
149
|
+
this._hasError = true;
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
stopRecording() {
|
|
154
|
+
const recorder = this.mediaRecorder;
|
|
155
|
+
return new Promise((resolve) => {
|
|
156
|
+
if (recorder && this._isRecording) {
|
|
157
|
+
recorder.onstop = () => {
|
|
158
|
+
resolve();
|
|
159
|
+
};
|
|
160
|
+
recorder.stop();
|
|
161
|
+
this._isRecording = false;
|
|
162
|
+
} else resolve();
|
|
163
|
+
recorder?.stream?.getTracks().forEach((track) => track.stop());
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
reset() {
|
|
167
|
+
const recorder = this.mediaRecorder;
|
|
168
|
+
if (recorder) {
|
|
169
|
+
recorder.ondataavailable = null;
|
|
170
|
+
recorder.onerror = null;
|
|
171
|
+
recorder.onstop = null;
|
|
172
|
+
if (recorder.state !== "inactive") recorder.stop();
|
|
173
|
+
recorder.stream.getTracks().forEach((track) => track.stop());
|
|
174
|
+
this.mediaRecorder = null;
|
|
175
|
+
}
|
|
176
|
+
this.onPart = null;
|
|
177
|
+
this._isRecording = false;
|
|
178
|
+
this._error = null;
|
|
179
|
+
this._hasError = false;
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
//#endregion
|
|
183
|
+
//#region ../infra/src/providers/browser/BrowserNetworkStatusProvider.ts
|
|
184
|
+
var BrowserNetworkStatusProvider = class {
|
|
185
|
+
onOnline(listener) {
|
|
186
|
+
if (typeof window === "undefined" || typeof window.addEventListener !== "function") return () => {};
|
|
187
|
+
window.addEventListener("online", listener);
|
|
188
|
+
return () => {
|
|
189
|
+
window.removeEventListener("online", listener);
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
//#endregion
|
|
194
|
+
//#region src/internal/recordings/videoSelfieUploadService.ts
|
|
195
|
+
/**
|
|
196
|
+
* Opens a scoped multipart video upload session. Idempotent server-side: if
|
|
197
|
+
* an upload is already in progress for the `(session, scope)` pair, the same `uploadId`
|
|
198
|
+
* comes back along with the parts already stored (`parts` non-empty) — but
|
|
199
|
+
* always with a fresh `epoch` that locks out whoever held the previous one.
|
|
200
|
+
*/
|
|
201
|
+
async function initiateVideoSelfieUpload(scope = "videoselfie") {
|
|
202
|
+
const response = await api.post(endpoints.videoSelfieUploadInitiate, void 0, { query: { scope } });
|
|
203
|
+
return {
|
|
204
|
+
uploadId: response.data.uploadId,
|
|
205
|
+
epoch: response.data.epoch,
|
|
206
|
+
scope,
|
|
207
|
+
parts: response.data.parts ?? []
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Uploads a single chunk as a multipart part. The body is the raw video bytes
|
|
212
|
+
* (no base64, no client-side encryption — encryption at rest is server-side
|
|
213
|
+
* S3 SSE). Every part except the last must be >= 5 MiB (enforced
|
|
214
|
+
* server-side). Returns the part number + `etag` needed to complete the
|
|
215
|
+
* upload. Rejects with a `409` status when a newer initiate fenced this
|
|
216
|
+
* session out.
|
|
217
|
+
*/
|
|
218
|
+
async function uploadVideoSelfiePart(session, partNumber, chunk) {
|
|
219
|
+
const response = await api.post(endpoints.videoSelfieUploadPart, chunk, {
|
|
220
|
+
query: {
|
|
221
|
+
uploadId: session.uploadId,
|
|
222
|
+
epoch: session.epoch,
|
|
223
|
+
partNumber,
|
|
224
|
+
scope: session.scope
|
|
225
|
+
},
|
|
226
|
+
headers: { "Content-Type": "application/octet-stream" }
|
|
227
|
+
});
|
|
228
|
+
return {
|
|
229
|
+
partNumber: response.data.partNumber,
|
|
230
|
+
etag: response.data.etag
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Finalizes the upload. The service assembles from the parts it stored; the
|
|
235
|
+
* optional `parts` list is deliberately NOT sent — chunks staged below the
|
|
236
|
+
* S3 minimum are combined and renumbered server-side, so a client-side list
|
|
237
|
+
* could contradict the authoritative one. Safe to repeat if the response
|
|
238
|
+
* was lost. Returns the server-reported status. Rejects with `400` naming a
|
|
239
|
+
* missing part when the sequence has a hole.
|
|
240
|
+
*/
|
|
241
|
+
async function completeVideoSelfieUpload(session) {
|
|
242
|
+
return (await api.post(endpoints.videoSelfieUploadComplete, {
|
|
243
|
+
uploadId: session.uploadId,
|
|
244
|
+
epoch: session.epoch
|
|
245
|
+
}, { query: { scope: session.scope } })).data.status;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Discards an in-progress upload and everything already sent for it, so the
|
|
249
|
+
* backend fails the upload straight away instead of waiting for its expiry.
|
|
250
|
+
* Call when a recording is abandoned or its upload can no longer complete.
|
|
251
|
+
*/
|
|
252
|
+
async function abortVideoSelfieUpload(session) {
|
|
253
|
+
return (await api.post(endpoints.videoSelfieUploadAbort, {
|
|
254
|
+
uploadId: session.uploadId,
|
|
255
|
+
epoch: session.epoch
|
|
256
|
+
}, { query: { scope: session.scope } })).data.status;
|
|
257
|
+
}
|
|
258
|
+
//#endregion
|
|
259
|
+
//#region src/internal/recordings/videoSelfieChunkUploader.ts
|
|
260
|
+
/**
|
|
261
|
+
* How many part uploads run concurrently. The service allows 10 rps with a
|
|
262
|
+
* burst of 30 per session; a real recorder emits ~2 chunks/s, so this cap
|
|
263
|
+
* only matters when a backlog is draining after a network stall.
|
|
264
|
+
*/
|
|
265
|
+
const MAX_IN_FLIGHT = 3;
|
|
266
|
+
/** Attempts per chunk in the live round (first try + retries). */
|
|
267
|
+
const MAX_ATTEMPTS = 4;
|
|
268
|
+
/** Extra attempts per parked chunk during the final drain() round. */
|
|
269
|
+
const DRAIN_ATTEMPTS = 2;
|
|
270
|
+
const BACKOFF_BASE_MS = 500;
|
|
271
|
+
const BACKOFF_CAP_MS = 8e3;
|
|
272
|
+
/** Upper bound honored for a server-sent `Retry-After` (seconds). */
|
|
273
|
+
const RETRY_AFTER_CAP_MS = 3e4;
|
|
274
|
+
/**
|
|
275
|
+
* Ceiling on un-acknowledged chunk bytes held in memory. On a network slower
|
|
276
|
+
* than the encoder the backlog grows without bound; past this the upload
|
|
277
|
+
* cannot realistically catch up, so the uploader fails instead of eating
|
|
278
|
+
* memory on a low-end device. ~48 MiB ≈ 2.5 minutes of video at our bitrate.
|
|
279
|
+
*/
|
|
280
|
+
const MAX_BUFFERED_BYTES = 48 * 1024 * 1024;
|
|
281
|
+
function httpStatusOf$1(error) {
|
|
282
|
+
if (typeof error === "object" && error !== null && "status" in error && typeof error.status === "number") return error.status;
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
function retryAfterMsOf(error) {
|
|
286
|
+
if (typeof error === "object" && error !== null && "headers" in error && typeof error.headers === "object") {
|
|
287
|
+
const headers = error.headers;
|
|
288
|
+
const seconds = Number(headers?.["retry-after"]);
|
|
289
|
+
if (Number.isFinite(seconds) && seconds >= 0) return Math.min(seconds * 1e3, RETRY_AFTER_CAP_MS);
|
|
290
|
+
}
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Uploads video-selfie chunks with the client-side half of the service's
|
|
295
|
+
* resilience contract (`video-selfie-service` README, "What a client can
|
|
296
|
+
* rely on"):
|
|
297
|
+
*
|
|
298
|
+
* - **Keep-until-ack** — every chunk is held in memory until its upload
|
|
299
|
+
* returns 200 (a hole in the sequence can only be filled by that exact
|
|
300
|
+
* data). Acked bytes are durable in S3 (stored as a part or staged), so
|
|
301
|
+
* the blob is released the moment the ack lands.
|
|
302
|
+
* - **Retry with backoff** — transient failures (network error/timeout,
|
|
303
|
+
* 408, 429, 5xx) retry the same bytes under the same partNumber with
|
|
304
|
+
* exponential backoff + full jitter; 429 honors the server's
|
|
305
|
+
* `Retry-After`. Chunks may land out of order — the service stages them.
|
|
306
|
+
* - **Park, then drain** — a chunk that exhausts its live retries is parked
|
|
307
|
+
* (blob kept) without failing the recording; {@link drain} gives every
|
|
308
|
+
* parked chunk a final round once recording stops, so a mid-recording
|
|
309
|
+
* network outage only fails the upload if it persists to the end. A
|
|
310
|
+
* browser `online` event un-parks early: parked chunks get a fresh live
|
|
311
|
+
* round as soon as connectivity returns instead of waiting for stop.
|
|
312
|
+
* - **409 is fatal** — a newer initiate fenced this session out ("latest
|
|
313
|
+
* initiate wins"); no retry can succeed, so the uploader stops.
|
|
314
|
+
* - **Bounded memory** — when un-acked bytes exceed the ceiling the
|
|
315
|
+
* uploader fails rather than buffering a runaway backlog.
|
|
316
|
+
*/
|
|
317
|
+
var VideoSelfieChunkUploader = class {
|
|
318
|
+
constructor(session, dependencies = {}) {
|
|
319
|
+
this.queue = [];
|
|
320
|
+
this.parked = [];
|
|
321
|
+
this.inFlight = 0;
|
|
322
|
+
this.bufferedBytes = 0;
|
|
323
|
+
this.fatal = false;
|
|
324
|
+
this.disposed = false;
|
|
325
|
+
this.tasks = [];
|
|
326
|
+
this.session = session;
|
|
327
|
+
this.timer = dependencies.timer ?? BrowserTimerProvider.getInstance();
|
|
328
|
+
this.jitter = dependencies.jitter ?? Math.random;
|
|
329
|
+
const networkStatus = dependencies.networkStatus ?? new BrowserNetworkStatusProvider();
|
|
330
|
+
this.unsubscribeOnline = networkStatus.onOnline(() => this.unparkEarly());
|
|
331
|
+
}
|
|
332
|
+
/** True once the upload cannot complete (fenced out or over the memory cap). */
|
|
333
|
+
get failed() {
|
|
334
|
+
return this.fatal;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Accepts the next chunk for upload. Non-blocking: the upload (and any
|
|
338
|
+
* retries) run in the background; failures surface through {@link failed}
|
|
339
|
+
* and {@link drain}.
|
|
340
|
+
*/
|
|
341
|
+
enqueue(partNumber, chunk) {
|
|
342
|
+
if (this.fatal || this.disposed) return;
|
|
343
|
+
this.bufferedBytes += chunk.size;
|
|
344
|
+
if (this.bufferedBytes > MAX_BUFFERED_BYTES) {
|
|
345
|
+
this.fatal = true;
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
this.queue.push({
|
|
349
|
+
partNumber,
|
|
350
|
+
chunk,
|
|
351
|
+
attempts: 0
|
|
352
|
+
});
|
|
353
|
+
this.pump();
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Waits for every accepted chunk to be acknowledged, giving parked chunks
|
|
357
|
+
* one final retry round. Returns `true` when all chunks landed and the
|
|
358
|
+
* upload can be completed.
|
|
359
|
+
*/
|
|
360
|
+
async drain() {
|
|
361
|
+
this.unsubscribeOnline();
|
|
362
|
+
await this.settleLiveRound();
|
|
363
|
+
while (!this.fatal && this.parked.length > 0) {
|
|
364
|
+
const chunk = this.parked.shift();
|
|
365
|
+
chunk.attempts = MAX_ATTEMPTS - DRAIN_ATTEMPTS;
|
|
366
|
+
this.queue.push(chunk);
|
|
367
|
+
this.pump();
|
|
368
|
+
await this.settleLiveRound();
|
|
369
|
+
if (this.parked.some((p) => p.partNumber === chunk.partNumber)) return false;
|
|
370
|
+
}
|
|
371
|
+
return !this.disposed && !this.fatal && this.parked.length === 0;
|
|
372
|
+
}
|
|
373
|
+
/** Cancels all pending work; held blobs are released. */
|
|
374
|
+
dispose() {
|
|
375
|
+
this.disposed = true;
|
|
376
|
+
this.queue = [];
|
|
377
|
+
this.parked = [];
|
|
378
|
+
this.unsubscribeOnline();
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Connectivity is back (browser `online` event) — give parked chunks a
|
|
382
|
+
* fresh live round right away instead of holding them until {@link drain}.
|
|
383
|
+
* The event is only a hint: chunks that still fail simply park again.
|
|
384
|
+
*/
|
|
385
|
+
unparkEarly() {
|
|
386
|
+
if (this.fatal || this.disposed || this.parked.length === 0) return;
|
|
387
|
+
for (const chunk of this.parked.splice(0)) {
|
|
388
|
+
chunk.attempts = 0;
|
|
389
|
+
this.queue.push(chunk);
|
|
390
|
+
}
|
|
391
|
+
this.pump();
|
|
392
|
+
}
|
|
393
|
+
async settleLiveRound() {
|
|
394
|
+
while (this.tasks.length > 0) {
|
|
395
|
+
const snapshot = [...this.tasks];
|
|
396
|
+
await Promise.all(snapshot);
|
|
397
|
+
this.tasks = this.tasks.filter((task) => !snapshot.includes(task));
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
pump() {
|
|
401
|
+
while (!this.fatal && !this.disposed && this.inFlight < MAX_IN_FLIGHT && this.queue.length > 0) {
|
|
402
|
+
const chunk = this.queue.shift();
|
|
403
|
+
this.inFlight += 1;
|
|
404
|
+
const task = this.uploadWithRetry(chunk).finally(() => {
|
|
405
|
+
this.inFlight -= 1;
|
|
406
|
+
this.pump();
|
|
407
|
+
});
|
|
408
|
+
this.tasks.push(task);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
async uploadWithRetry(pending) {
|
|
412
|
+
while (!this.disposed) {
|
|
413
|
+
pending.attempts += 1;
|
|
414
|
+
try {
|
|
415
|
+
await uploadVideoSelfiePart(this.session, pending.partNumber, pending.chunk);
|
|
416
|
+
this.bufferedBytes -= pending.chunk.size;
|
|
417
|
+
return;
|
|
418
|
+
} catch (error) {
|
|
419
|
+
const status = httpStatusOf$1(error);
|
|
420
|
+
if (status === 409) {
|
|
421
|
+
this.fatal = true;
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
if (status !== null && status >= 400 && status < 500 && status !== 408 && status !== 429 || pending.attempts >= MAX_ATTEMPTS) {
|
|
425
|
+
this.parked.push(pending);
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
await this.delayBeforeRetry(pending.attempts, error);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
delayBeforeRetry(attempt, error) {
|
|
433
|
+
const retryAfterMs = retryAfterMsOf(error);
|
|
434
|
+
const backoffCeiling = Math.min(BACKOFF_BASE_MS * 2 ** (attempt - 1), BACKOFF_CAP_MS);
|
|
435
|
+
const waitMs = retryAfterMs ?? backoffCeiling / 2 + this.jitter() * (backoffCeiling / 2);
|
|
436
|
+
return new Promise((resolve) => {
|
|
437
|
+
this.timer.setTimeout(resolve, waitMs);
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
//#endregion
|
|
442
|
+
//#region src/internal/recordings/multipartRecordingService.ts
|
|
443
|
+
/** Attempts for `complete` — documented safe to repeat if the response was lost. */
|
|
444
|
+
const COMPLETE_ATTEMPTS = 3;
|
|
445
|
+
const COMPLETE_BACKOFF_MS = 500;
|
|
446
|
+
function httpStatusOf(error) {
|
|
447
|
+
if (typeof error === "object" && error !== null && "status" in error && typeof error.status === "number") return error.status;
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Records the camera on-device and streams it to the backend as it is
|
|
452
|
+
* captured, using the video-selfie-service multipart upload protocol
|
|
453
|
+
* (`/v1/video-upload/*`).
|
|
454
|
+
*
|
|
455
|
+
* This is the client-side recorder for Video Selfie and for scoped regular
|
|
456
|
+
* Selfie and ID recordings. It replaces the former server-side recording path.
|
|
457
|
+
*
|
|
458
|
+
* Every ~0.5 s recorder blob uploads as its own chunk, concurrently with
|
|
459
|
+
* recording, through {@link VideoSelfieChunkUploader} (keep-until-ack +
|
|
460
|
+
* retry with backoff — see its doc for the full policy). The service stages
|
|
461
|
+
* sub-5 MiB chunks and combines them server-side, so `stop()` only drains
|
|
462
|
+
* the stragglers and finalizes; client memory holds un-acked chunks only.
|
|
463
|
+
* No client-side encryption: video is encrypted at rest server-side
|
|
464
|
+
* (S3 SSE-AES-256).
|
|
465
|
+
*/
|
|
466
|
+
var MultipartRecordingService = class {
|
|
467
|
+
constructor(scope = "videoselfie") {
|
|
468
|
+
this.scope = scope;
|
|
469
|
+
this.recorder = new MultipartRecordingProvider();
|
|
470
|
+
this.timer = BrowserTimerProvider.getInstance();
|
|
471
|
+
this.session = null;
|
|
472
|
+
this.uploader = null;
|
|
473
|
+
this.chunksEmitted = 0;
|
|
474
|
+
this.stopPromise = null;
|
|
475
|
+
this.abandonRequested = false;
|
|
476
|
+
}
|
|
477
|
+
get isRecording() {
|
|
478
|
+
return this.recorder.isRecording;
|
|
479
|
+
}
|
|
480
|
+
async start(stream) {
|
|
481
|
+
if (this.recorder.isRecording) return;
|
|
482
|
+
let initiated = await initiateVideoSelfieUpload(this.scope);
|
|
483
|
+
if (initiated.parts.length > 0) {
|
|
484
|
+
await abortVideoSelfieUpload(initiated).catch(() => {});
|
|
485
|
+
initiated = await initiateVideoSelfieUpload(this.scope);
|
|
486
|
+
}
|
|
487
|
+
this.session = {
|
|
488
|
+
uploadId: initiated.uploadId,
|
|
489
|
+
epoch: initiated.epoch,
|
|
490
|
+
scope: this.scope
|
|
491
|
+
};
|
|
492
|
+
this.uploader = new VideoSelfieChunkUploader(this.session);
|
|
493
|
+
this.chunksEmitted = 0;
|
|
494
|
+
this.abandonRequested = false;
|
|
495
|
+
this.recorder.startRecording(stream, ({ chunk, partNumber }) => {
|
|
496
|
+
this.chunksEmitted += 1;
|
|
497
|
+
this.uploader?.enqueue(partNumber, chunk);
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
/** Pause the current media container without finalizing its upload. */
|
|
501
|
+
pause() {
|
|
502
|
+
return this.recorder.pauseRecording?.() ?? false;
|
|
503
|
+
}
|
|
504
|
+
/** Resume the same media container after its video source has recovered. */
|
|
505
|
+
resume() {
|
|
506
|
+
return this.recorder.resumeRecording?.() ?? false;
|
|
507
|
+
}
|
|
508
|
+
stop() {
|
|
509
|
+
if (this.stopPromise) return this.stopPromise;
|
|
510
|
+
const stopPromise = this.finalizeRecording();
|
|
511
|
+
this.stopPromise = stopPromise;
|
|
512
|
+
const clearStopPromise = () => {
|
|
513
|
+
if (this.stopPromise === stopPromise) {
|
|
514
|
+
this.stopPromise = null;
|
|
515
|
+
this.abandonRequested = false;
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
stopPromise.then(clearStopPromise, clearStopPromise);
|
|
519
|
+
return stopPromise;
|
|
520
|
+
}
|
|
521
|
+
async finalizeRecording() {
|
|
522
|
+
const session = this.session;
|
|
523
|
+
const uploader = this.uploader;
|
|
524
|
+
if (!this.recorder.isRecording || !session || !uploader) return { recordingId: null };
|
|
525
|
+
try {
|
|
526
|
+
await this.recorder.stopRecording();
|
|
527
|
+
if (this.abandonRequested) {
|
|
528
|
+
this.abandonUpload(session);
|
|
529
|
+
return { recordingId: null };
|
|
530
|
+
}
|
|
531
|
+
const delivered = await uploader.drain();
|
|
532
|
+
if (this.abandonRequested || !delivered || uploader.failed || this.chunksEmitted === 0) {
|
|
533
|
+
this.abandonUpload(session);
|
|
534
|
+
return { recordingId: null };
|
|
535
|
+
}
|
|
536
|
+
} catch (error) {
|
|
537
|
+
this.abandonUpload(session);
|
|
538
|
+
throw error;
|
|
539
|
+
}
|
|
540
|
+
try {
|
|
541
|
+
await this.completeWithRetry(session);
|
|
542
|
+
this.session = null;
|
|
543
|
+
this.uploader = null;
|
|
544
|
+
return { recordingId: session.uploadId };
|
|
545
|
+
} catch {
|
|
546
|
+
this.abandonUpload(session);
|
|
547
|
+
return { recordingId: null };
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
cleanup() {
|
|
551
|
+
if (this.session) if (this.stopPromise) {
|
|
552
|
+
this.abandonRequested = true;
|
|
553
|
+
this.uploader?.dispose();
|
|
554
|
+
} else this.abandonUpload(this.session);
|
|
555
|
+
this.recorder.reset();
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* `complete` is idempotent server-side ("safe to repeat if the response
|
|
559
|
+
* was lost"), so transient failures — network errors, 5xx, 429 — retry a
|
|
560
|
+
* couple of times before the recording is declared failed. A 4xx (e.g.
|
|
561
|
+
* `400` naming a missing part) is permanent: after a clean drain every
|
|
562
|
+
* chunk was acked, so a reported hole cannot be filled from here.
|
|
563
|
+
*/
|
|
564
|
+
async completeWithRetry(session) {
|
|
565
|
+
for (let attempt = 1;; attempt += 1) {
|
|
566
|
+
if (this.abandonRequested) throw new Error("Video upload abandoned");
|
|
567
|
+
try {
|
|
568
|
+
await completeVideoSelfieUpload(session);
|
|
569
|
+
return;
|
|
570
|
+
} catch (error) {
|
|
571
|
+
const status = httpStatusOf(error);
|
|
572
|
+
if (status !== null && status >= 400 && status < 500 && status !== 408 && status !== 429 || attempt >= COMPLETE_ATTEMPTS) throw error;
|
|
573
|
+
await new Promise((resolve) => {
|
|
574
|
+
this.timer.setTimeout(resolve, COMPLETE_BACKOFF_MS * attempt);
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Fire-and-forget abort: the upload can no longer complete, so tell the
|
|
581
|
+
* backend to fail it immediately rather than at its expiry. Best-effort —
|
|
582
|
+
* an abort that doesn't land (including a 409 from a newer epoch having
|
|
583
|
+
* taken over) just means the server falls back to expiry or salvage.
|
|
584
|
+
*/
|
|
585
|
+
abandonUpload(session) {
|
|
586
|
+
if (this.session !== session) return;
|
|
587
|
+
this.session = null;
|
|
588
|
+
this.uploader?.dispose();
|
|
589
|
+
this.uploader = null;
|
|
590
|
+
abortVideoSelfieUpload(session).catch(() => {});
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
//#endregion
|
|
594
|
+
export { getAdaptiveMediaRecorderOptions as n, MultipartRecordingService as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as isWasmMotionPrimedForModule } from "./permissionServices-
|
|
1
|
+
import { a as isWasmMotionPrimedForModule } from "./permissionServices-Bj_fyWtv.esm.js";
|
|
2
2
|
//#region src/internal/permissions/permissionGuards.ts
|
|
3
3
|
function resolveStoredPermissionResult(fromEvent, fromContext) {
|
|
4
4
|
if (fromEvent === "granted" || fromEvent === "denied" || fromEvent === "prompt" || fromEvent === "refresh") return fromEvent;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { r as WasmUtilProvider } from "./safeStorage-
|
|
2
|
-
import { n as isAndroidWebView } from "./platform-
|
|
3
|
-
import { t as MotionSensorProvider } from "./MotionSensorProvider-
|
|
4
|
-
import {
|
|
1
|
+
import { r as WasmUtilProvider } from "./safeStorage-B-trhxg6.esm.js";
|
|
2
|
+
import { n as isAndroidWebView } from "./platform-DkcRc9JV.esm.js";
|
|
3
|
+
import { t as MotionSensorProvider } from "./MotionSensorProvider-BgTYwg9L.esm.js";
|
|
4
|
+
import { c as isCameraGrantedInDocument, i as requestCameraAccess, o as stopCameraStream, s as clearCameraGrantedInDocument } from "./camera-sIa9ceW2.esm.js";
|
|
5
5
|
//#region ../infra/src/media/permissions.ts
|
|
6
6
|
async function queryPermission(name) {
|
|
7
7
|
try {
|
|
@@ -139,4 +139,4 @@ async function invokeRequestPermissionActor(input) {
|
|
|
139
139
|
return requestPermission({ requestMotion: true });
|
|
140
140
|
}
|
|
141
141
|
//#endregion
|
|
142
|
-
export { isWasmMotionPrimedForModule as a, requestPermission as i, invokeRequestPermissionActor as n, resetWasmMotionPrimedForModule as o, primeMotionFromUserGestureIfNeeded as r, checkPermission as t };
|
|
142
|
+
export { isWasmMotionPrimedForModule as a, requestPermission as i, invokeRequestPermissionActor as n, resetWasmMotionPrimedForModule as o, primeMotionFromUserGestureIfNeeded as r, queryCameraPermission as s, checkPermission as t };
|
package/dist/personhood.d.ts
CHANGED
|
@@ -2,12 +2,13 @@ import { A as StateMachine, i as ActorRefFrom, l as AnyStateMachine } from "./sp
|
|
|
2
2
|
import "./StateMachine-EDpYWy0i.js";
|
|
3
3
|
import { t as Manager } from "./Manager-CQQ99QOI.js";
|
|
4
4
|
import "./Actor-iTq7YY48.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { t as FaceDetectionProvider } from "./FaceDetectionProvider-Mh6q3EbA.js";
|
|
8
|
-
import { n as DetectionStatus, s as IWasmUtilCapability } from "./types-Hmd7U0JA.js";
|
|
5
|
+
import { y as IncodeCanvas } from "./createFaceAvatar-BlcTYgJv.js";
|
|
6
|
+
import { i as IStorageCapability, t as IWasmUtilCapability } from "./IWasmUtilCapability-CXXDA5l1.js";
|
|
9
7
|
import { n as PermissionStatus, t as PermissionResult } from "./types-BEwVKkLJ.js";
|
|
10
|
-
import { n as
|
|
8
|
+
import { n as DetectionStatus } from "./types-CM-jtjJ2.js";
|
|
9
|
+
import { n as DeepsightService, t as StreamCanvasCapture } from "./StreamCanvasCapture-B3YT2Bt6.js";
|
|
10
|
+
import { t as FaceDetectionProvider } from "./FaceDetectionProvider-LdZ47bWy.js";
|
|
11
|
+
import { t as CameraStream } from "./camera-9wWD-pwg.js";
|
|
11
12
|
//#region src/modules/personhood/types.d.ts
|
|
12
13
|
/**
|
|
13
14
|
* Head pose (degrees) computed per-frame from the WASM face detector.
|
package/dist/personhood.esm.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { l as BrowserStorageProvider } from "./setup-msLybMbC.esm.js";
|
|
2
|
+
import { r as WasmUtilProvider } from "./safeStorage-B-trhxg6.esm.js";
|
|
3
3
|
import { t as BrowserTimerProvider } from "./BrowserTimerProvider-BXhgNxLt.esm.js";
|
|
4
4
|
import { t as api } from "./api-Bx3gKW_y.esm.js";
|
|
5
|
-
import {
|
|
6
|
-
import { n as eventModuleNames } from "./events-
|
|
7
|
-
import {
|
|
8
|
-
import { t as endpoints } from "./endpoints-
|
|
5
|
+
import { b as getStoredHttpConfig, w as createApi$1, y as randomUUID } from "./trueSightService-CKrrfV0Q.esm.js";
|
|
6
|
+
import { n as eventModuleNames } from "./events-ijlbX_Wx.esm.js";
|
|
7
|
+
import { b as BrowserEnvironmentProvider, h as isBrowserSimulation, n as getFingerprintEnabled, v as getThumbmarkId, y as getDeviceFingerprintInfo } from "./sessionInitializer-BLoK7SP9.esm.js";
|
|
8
|
+
import { t as endpoints } from "./endpoints-D3B9mUHh.esm.js";
|
|
9
9
|
import { i as assign, s as createActor, t as setup, u as createManager } from "./xstate.esm-BuFLFuzz.esm.js";
|
|
10
10
|
import { n as fromPromise, t as fromCallback } from "./xstate-actors.esm-BXeQ-Ucz.esm.js";
|
|
11
|
-
import {
|
|
12
|
-
import { i as requestPermission, t as checkPermission } from "./permissionServices-
|
|
13
|
-
import {
|
|
11
|
+
import { i as requestCameraAccess, o as stopCameraStream } from "./camera-sIa9ceW2.esm.js";
|
|
12
|
+
import { i as requestPermission, t as checkPermission } from "./permissionServices-Bj_fyWtv.esm.js";
|
|
13
|
+
import { i as initializeDeepsightSession, l as stopStream, o as startDetection, t as FaceDetectionProvider } from "./FaceDetectionProvider-DTetAE8H.esm.js";
|
|
14
14
|
import { t as sleep } from "./ITimerCapability-DgdDzp8G.esm.js";
|
|
15
|
-
import { t as StreamCanvasCapture } from "./StreamCanvasCapture-
|
|
15
|
+
import { t as StreamCanvasCapture } from "./StreamCanvasCapture-C9jtgBdT.esm.js";
|
|
16
16
|
//#region src/modules/personhood/personhoodServices.ts
|
|
17
17
|
/**
|
|
18
18
|
* Config used for the passive liveness pass. Deliberately stripped down from
|
package/dist/phone.esm.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as phoneMachine } from "./phoneStateMachine-
|
|
2
|
-
import { t as createPhoneManager } from "./phoneManager-
|
|
1
|
+
import { t as phoneMachine } from "./phoneStateMachine-jl8LJKCo.esm.js";
|
|
2
|
+
import { t as createPhoneManager } from "./phoneManager-N1-sbrY4.esm.js";
|
|
3
3
|
export { createPhoneManager, phoneMachine };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { n as eventModuleNames, o as createManagerInstrumentation } from "./events-
|
|
1
|
+
import { n as eventModuleNames, o as createManagerInstrumentation } from "./events-ijlbX_Wx.esm.js";
|
|
2
2
|
import { s as createActor, u as createManager } from "./xstate.esm-BuFLFuzz.esm.js";
|
|
3
|
-
import { t as phoneMachine } from "./phoneStateMachine-
|
|
3
|
+
import { t as phoneMachine } from "./phoneStateMachine-jl8LJKCo.esm.js";
|
|
4
4
|
//#region src/modules/phone/phoneActor.ts
|
|
5
5
|
function createPhoneActor(options) {
|
|
6
6
|
return createActor(phoneMachine, { input: { config: options.config } }).start();
|