@incodetech/core 2.4.1-agentic.5 → 2.4.1-agentic.6
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/dist/DateFormattingProvider-DPq9zco-.esm.js +25 -0
- package/dist/{FaceDetectionProvider-ZiDiL_hY.esm.js → FaceDetectionProvider-DjXSD4uI.esm.js} +7 -7
- package/dist/addressSearch-D6cKPWmk.esm.js +72 -0
- package/dist/ae-signature.esm.js +1 -1
- package/dist/antifraud.esm.js +2 -2
- package/dist/{antifraudManager-BObuHBjn.esm.js → antifraudManager-CbIwM35x.esm.js} +2 -2
- package/dist/{antifraudStateMachine-Dfrd2-26.esm.js → antifraudStateMachine-qNNXrlsP.esm.js} +1 -1
- package/dist/{api-CpP4PS4S.esm.js → api-C_P9YXbL.esm.js} +1 -0
- package/dist/{apiError-CeyLcwt3.esm.js → apiError-DzZ5OriE.esm.js} +1 -1
- package/dist/{attemptCarry-WOkfvFMw.esm.js → attemptCarry-BaAXPR_w.esm.js} +1 -1
- package/dist/authentication.d.ts +3 -3
- package/dist/authentication.esm.js +2 -2
- package/dist/{authenticationManager-ffZXiENz.esm.js → authenticationManager-B-l8_8tH.esm.js} +4 -4
- package/dist/{authenticationManager-CWmh7aSY.d.ts → authenticationManager-DKLRA91K.d.ts} +1 -1
- package/dist/{authenticationStateMachine-ebqsPLXI.esm.js → authenticationStateMachine-Cg00UH7p.esm.js} +3 -3
- package/dist/{browser-pQZA35G2-Bu4in9gN.esm.js → browser-pQZA35G2-DJEJnmCd.esm.js} +1 -1
- package/dist/certificate-issuance.esm.js +2 -2
- package/dist/{certificateIssuanceManager-IRO_1Ug6.esm.js → certificateIssuanceManager-CrF3wjCH.esm.js} +2 -2
- package/dist/{certificateIssuanceStateMachine-CjxTBZuH.esm.js → certificateIssuanceStateMachine-uSD9IkcV.esm.js} +1 -1
- package/dist/consent.esm.js +2 -2
- package/dist/{consentManager-DMlSL6Ax.esm.js → consentManager-BD7wwgat.esm.js} +2 -2
- package/dist/{consentStateMachine-DIYSMxKQ.esm.js → consentStateMachine-BAiLDE3D.esm.js} +1 -1
- package/dist/{cpf-uAZTPUBy.esm.js → cpf-BIADjddF.esm.js} +1 -25
- package/dist/cross-document-data-match.esm.js +1 -1
- package/dist/{crossDocumentDataMatchManager-BFTdiEDB.esm.js → crossDocumentDataMatchManager-CUc1uACE.esm.js} +2 -2
- package/dist/curp-validation.d.ts +1 -1
- package/dist/curp-validation.esm.js +2 -2
- package/dist/{curpValidationManager-z8428oCM.d.ts → curpValidationManager-Crz3bnCo.d.ts} +1 -1
- package/dist/{curpValidationManager-DNpC3wyf.esm.js → curpValidationManager-DBfZSQbu.esm.js} +2 -2
- package/dist/{curpValidationStateMachine-B3iVsDyt.esm.js → curpValidationStateMachine-DyAEyScb.esm.js} +2 -2
- package/dist/custom-fields.esm.js +1 -1
- package/dist/custom-watchlist.esm.js +2 -2
- package/dist/{customFieldsManager-CvI-pDT3.esm.js → customFieldsManager-BZhIPyaY.esm.js} +2 -2
- package/dist/{customWatchlistManager-BuHtUb0y.esm.js → customWatchlistManager-B4cmxi__.esm.js} +2 -2
- package/dist/{customWatchlistStateMachine-CiVD9wyF.esm.js → customWatchlistStateMachine-ZZoDGRAZ.esm.js} +1 -1
- package/dist/{deepsightLoader-CJbBiTpq.esm.js → deepsightLoader-S0ktD2dZ.esm.js} +3 -3
- package/dist/{addressSearch-DzbE9Ogt.esm.js → definitionSource-1vPLtuXE.esm.js} +1 -72
- package/dist/{desktopCameraElection-BGMtYwk3.esm.js → desktopCameraElection-m2dAj6Zu.esm.js} +1 -1
- package/dist/document-capture.d.ts +1 -1
- package/dist/document-capture.esm.js +2 -2
- package/dist/{documentCaptureManager-CD5iQiUI.d.ts → documentCaptureManager-DDfviFg0.d.ts} +1 -1
- package/dist/{documentCaptureManager-DLPqruXJ.esm.js → documentCaptureManager-v57klTso.esm.js} +2 -2
- package/dist/{documentCaptureStateMachine-DCvWQhFG.esm.js → documentCaptureStateMachine-CgCtimSa.esm.js} +2 -2
- package/dist/dynamic-forms.esm.js +2 -2
- package/dist/{dynamicFormsManager-C1pBbCWs.esm.js → dynamicFormsManager-BKAlol5I.esm.js} +2 -2
- package/dist/{dynamicFormsStateMachine-iVdrXC1r.esm.js → dynamicFormsStateMachine-DTyEVRIb.esm.js} +2 -2
- package/dist/ekyb.d.ts +1 -1
- package/dist/ekyb.esm.js +2 -2
- package/dist/{ekybManager-OZ0SeXvq.esm.js → ekybManager-BYFWVBTW.esm.js} +2 -2
- package/dist/{ekybStateMachine-BDh-yJkS.esm.js → ekybStateMachine-CxSx0HNz.esm.js} +6 -4
- package/dist/ekyc-prefill.d.ts +17 -0
- package/dist/ekyc-prefill.esm.js +3 -0
- package/dist/ekyc.d.ts +2 -2
- package/dist/ekyc.esm.js +3 -3
- package/dist/{ekycManager-DymCvmVB.esm.js → ekycManager-Bwv-qYAZ.esm.js} +2 -2
- package/dist/{ekycManager-DlGIn9wA.d.ts → ekycManager-CERRvIfg.d.ts} +1 -1
- package/dist/ekycPrefillManager-CbI1rTKP.esm.js +102 -0
- package/dist/ekycPrefillManager-DHfC1T9s.d.ts +565 -0
- package/dist/ekycPrefillStateMachine-ClGEAsOy.esm.js +686 -0
- package/dist/ekycRules-B7vXnbdg.esm.js +319 -0
- package/dist/{ekycStateMachine-CoFCUJ2z.esm.js → ekycStateMachine-DlN1RCob.esm.js} +418 -533
- package/dist/{ekycUtils-GRuMELYr.esm.js → ekycUtils-K6VJXnOg.esm.js} +18 -6
- package/dist/electronic-signature.esm.js +1 -1
- package/dist/{electronicSignatureManager-CHe4KM2h.esm.js → electronicSignatureManager-Co_sso4-.esm.js} +3 -3
- package/dist/email.esm.js +2 -2
- package/dist/{emailManager-CGoE3CUe.esm.js → emailManager-BSaGg1Gl.esm.js} +2 -2
- package/dist/{emailStateMachine-KgHfDNvM.esm.js → emailStateMachine-CaoPZtZN.esm.js} +2 -2
- package/dist/{events-ggpBBaZ8.esm.js → events-kU5WJU4B.esm.js} +1 -1
- package/dist/events.esm.js +1 -1
- package/dist/extensibility.d.ts +14 -13
- package/dist/extensibility.esm.js +36 -35
- package/dist/face-match.esm.js +2 -2
- package/dist/{faceCaptureManagerFactory-GmZMp6TR.esm.js → faceCaptureManagerFactory-ErFltb83.esm.js} +2 -2
- package/dist/{faceCaptureManagerFactory-DV2ULUYS.d.ts → faceCaptureManagerFactory-ZudYP6Qp.d.ts} +3 -3
- package/dist/{faceCaptureSetup--MEv7wIJ.esm.js → faceCaptureSetup-D9VsC504.esm.js} +9 -9
- package/dist/{faceMatchManager-D2xKPjjQ.esm.js → faceMatchManager-qPJsa5Ac.esm.js} +2 -2
- package/dist/{faceMatchStateMachine-CUvwiQi9.esm.js → faceMatchStateMachine-D90ZHY1r.esm.js} +2 -2
- package/dist/{feature-management-hZhfjdAu.esm.js → feature-management-TNTHwnkm.esm.js} +1 -1
- package/dist/feature-management.esm.js +1 -1
- package/dist/field-comparison.esm.js +1 -1
- package/dist/{fieldComparisonManager-DgDbEeFZ.esm.js → fieldComparisonManager-BLLj_Ey1.esm.js} +2 -2
- package/dist/fiscal-qr.esm.js +1 -1
- package/dist/{fiscalQrManager-BZeklojR.esm.js → fiscalQrManager-Bh3rxb7Y.esm.js} +2 -2
- package/dist/flow-events.d.ts +1 -1
- package/dist/flow.d.ts +9 -8
- package/dist/flow.esm.js +46 -10
- package/dist/{flowCompletionService-E8ipjpAG.esm.js → flowCompletionService-BvoiqVJA.esm.js} +2 -2
- package/dist/{flowServices-Co77kn9L.esm.js → flowServices-BkrZ4ZU5.esm.js} +8 -8
- package/dist/geolocation.esm.js +2 -2
- package/dist/{geolocationManager-C8DY8c1D.esm.js → geolocationManager-hU9kxsr8.esm.js} +2 -2
- package/dist/{geolocationStateMachine-BluJR9Ew.esm.js → geolocationStateMachine-DyYMzzIb.esm.js} +3 -3
- package/dist/government-validation.esm.js +2 -2
- package/dist/{governmentValidationManager-CjChjZ3C.esm.js → governmentValidationManager-D5HkBqfr.esm.js} +2 -2
- package/dist/{governmentValidationStateMachine-AEbn3Afi.esm.js → governmentValidationStateMachine-BwMClTqC.esm.js} +1 -1
- package/dist/home.d.ts +1 -1
- package/dist/home.esm.js +1 -1
- package/dist/http.esm.js +1 -1
- package/dist/id-ocr.d.ts +2 -2
- package/dist/id-ocr.esm.js +3 -19
- package/dist/id-selfie-flow.d.ts +1 -1
- package/dist/id-selfie-flow.esm.js +6 -6
- package/dist/id-verification.esm.js +2 -2
- package/dist/id.d.ts +2 -2
- package/dist/id.esm.js +3 -3
- package/dist/{idCaptureManager-CCA2D1Ah.d.ts → idCaptureManager-NRGuCVv2.d.ts} +2 -2
- package/dist/{idCaptureManager-6amWi8Ko.esm.js → idCaptureManager-Xxlpem7N.esm.js} +6 -6
- package/dist/{idCaptureServices-Bpa4MmVC.esm.js → idCaptureServices-199UFURA.esm.js} +4 -4
- package/dist/{idCaptureStateMachine-BzBA2B4_.esm.js → idCaptureStateMachine-Bv-dhwgK.esm.js} +42 -14
- package/dist/idOcrCpfUtils-Nfln1Psb.esm.js +18 -0
- package/dist/{idOcrManager-BTdHlJ9D.d.ts → idOcrManager-B5xeI2lg.d.ts} +2 -2
- package/dist/{idOcrManager-xyEZNOBa.esm.js → idOcrManager-BMK2oou0.esm.js} +2 -2
- package/dist/{idOcrStateMachine-DNKXh4Rn.esm.js → idOcrStateMachine-RjNycN07.esm.js} +8 -7
- package/dist/{idVerificationManager-DdnvYfgN.esm.js → idVerificationManager-4wY-Ee4j.esm.js} +2 -2
- package/dist/{idVerificationStateMachine-DtIBCa32.esm.js → idVerificationStateMachine-Bj00uWvh.esm.js} +1 -1
- package/dist/identity-reuse.d.ts +1 -1
- package/dist/identity-reuse.esm.js +2 -2
- package/dist/{identityReuseManager-CcpovlfD.esm.js → identityReuseManager-CCZ-ES2E.esm.js} +2 -2
- package/dist/{identityReuseManager-B1birg5X.d.ts → identityReuseManager-ooAbp6Kc.d.ts} +4 -4
- package/dist/{identityReuseStateMachine-DxZFWy47.esm.js → identityReuseStateMachine-BtpkGpYZ.esm.js} +1 -1
- package/dist/{index-DC0P2Vzw.d.ts → index-BGnYn_4J.d.ts} +1 -1
- package/dist/{index-bD4-zpjs.d.ts → index-DlVDVTcf.d.ts} +31 -16
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/{invokeOnCaptureCallback-BJ0GVHGr.esm.js → invokeOnCaptureCallback-BkvXSZfa.esm.js} +1 -1
- package/dist/kyb-checks.esm.js +2 -2
- package/dist/{kybChecksManager-CbqLrEox.esm.js → kybChecksManager-CEEih5pC.esm.js} +1 -1
- package/dist/{kybChecksStateMachine-B_GS-KmL.esm.js → kybChecksStateMachine-DOE71Lv7.esm.js} +5 -4
- package/dist/mandatory-consent.d.ts +2 -2
- package/dist/mandatory-consent.esm.js +2 -2
- package/dist/{mandatoryConsentManager-B4vCYslr.esm.js → mandatoryConsentManager-BBeOo3Sz.esm.js} +2 -2
- package/dist/{mandatoryConsentManager-CEn59Ytw.d.ts → mandatoryConsentManager-MhZYQg10.d.ts} +1 -1
- package/dist/{mandatoryConsentStateMachine-DWslYPA3.esm.js → mandatoryConsentStateMachine-BJEyS63E.esm.js} +1 -1
- package/dist/{multipartRecordingService-BTqkHGG9.esm.js → multipartRecordingService-2iVLb-2Y.esm.js} +1 -1
- package/dist/phone.esm.js +2 -2
- package/dist/{phoneFormat-JJNaWthV.esm.js → phoneFormat-DEpESpz2.esm.js} +13 -1
- package/dist/{phoneManager-Dy5tODCU.esm.js → phoneManager-BylOWecM.esm.js} +2 -2
- package/dist/{phoneServices-DJgyOzU2.esm.js → phoneServices-Crge7uSV.esm.js} +1 -1
- package/dist/{phoneStateMachine-DnlPhnw7.esm.js → phoneStateMachine-CHnhCS-4.esm.js} +2 -2
- package/dist/{processFaceMatch-Bst83HaS.esm.js → processFaceMatch-BveUAHts.esm.js} +1 -1
- package/dist/qe-signature.esm.js +1 -1
- package/dist/{recordingService-CTko6Cjn.esm.js → recordingService-DKXaaOHO.esm.js} +2 -2
- package/dist/redirect-to-mobile.esm.js +2 -2
- package/dist/{redirectToMobileManager-CCSNyi19.esm.js → redirectToMobileManager-DUpLyXsq.esm.js} +2 -2
- package/dist/{redirectToMobileStateMachine-BKyOdAUe.esm.js → redirectToMobileStateMachine-D0DW4y-f.esm.js} +1 -1
- package/dist/{resolveForm-O7-r79VA.esm.js → resolveForm-f9PhUo9j.esm.js} +1 -209
- package/dist/{runChildModule-DHDczcGZ.esm.js → runChildModule-CDixuH1W.esm.js} +2 -2
- package/dist/{sdkVersion-CxaRTa9r.esm.js → sdkVersion-BNA7_9wn.esm.js} +1 -1
- package/dist/selfie.d.ts +3 -3
- package/dist/selfie.esm.js +9 -9
- package/dist/{selfieErrorUtils-Dk0ofKio.esm.js → selfieErrorUtils-Geee35WF.esm.js} +1 -1
- package/dist/{selfieManager-DmZFzs1-.d.ts → selfieManager-BPOlD-UN.d.ts} +1 -1
- package/dist/{selfieManager-EgnSX_Hu.esm.js → selfieManager-DVWFz5tv.esm.js} +4 -4
- package/dist/{selfieStateMachine-B8pBvum8.esm.js → selfieStateMachine-D9KQUtMs.esm.js} +3 -3
- package/dist/{session-CaliXPVw.esm.js → session-DoFzV1FT.esm.js} +4 -4
- package/dist/session.d.ts +1 -1
- package/dist/session.esm.js +5 -5
- package/dist/{sessionInitializer-Tr_ZkaSs.esm.js → sessionInitializer-DOZzSzqm.esm.js} +7 -7
- package/dist/{setup-Bz4l-E3R.esm.js → setup-B6WhRfCS.esm.js} +10 -13
- package/dist/{setup-Dyv1tJFj.d.ts → setup-prV5HQCQ.d.ts} +1 -1
- package/dist/signature.esm.js +2 -2
- package/dist/{signatureManager-CwqjcxPg.esm.js → signatureManager-QlegdTo3.esm.js} +2 -2
- package/dist/{signatureStateMachine-DBVDd1Eu.esm.js → signatureStateMachine-DFbbbFwg.esm.js} +1 -1
- package/dist/{stats-CatA2dea.esm.js → stats-Bv5PiWvo.esm.js} +1 -1
- package/dist/stats.esm.js +1 -1
- package/dist/step-up.d.ts +3 -5
- package/dist/step-up.esm.js +5 -11
- package/dist/{tri-CKUbuky5.esm.js → tri-B9aoyV2Z.esm.js} +3 -32
- package/dist/tri.d.ts +1 -1
- package/dist/tri.esm-DgtAka_v.esm.js +2145 -0
- package/dist/tri.esm.js +1 -1
- package/dist/{trueSightService-DDdJ8TrY.esm.js → trueSightService-nGcZHLsZ.esm.js} +3 -3
- package/dist/trust-graph.esm.js +1 -1
- package/dist/{types-Csh8vzPo.d.ts → types-0Rr7etmf.d.ts} +1 -1
- package/dist/types-B2M1IPZn.d.ts +6 -0
- package/dist/{types-BEVHQbbC.d.ts → types-BD9sV5oG.d.ts} +1 -1
- package/dist/{types-CuMJ2M7D.d.ts → types-BaDx6utW.d.ts} +4 -1
- package/dist/{types-BPm1JSu7.d.ts → types-BpJ21a4T.d.ts} +1 -1
- package/dist/{types-CJ7Yl9K-.d.ts → types-Bpo97EOh.d.ts} +4 -2
- package/dist/{types-CRaFu6wS.d.ts → types-CquDWYfv.d.ts} +6 -2
- package/dist/types-D9vIGFbl.d.ts +115 -0
- package/dist/{types-Cd0J0F9D.d.ts → types-NMBsvLIN.d.ts} +1 -1
- package/dist/usStates-CwOQ2kAx.esm.js +209 -0
- package/dist/video-selfie.d.ts +1 -1
- package/dist/video-selfie.esm.js +6 -6
- package/dist/{videoSelfieCameraWarmer-Dsk8JQNy.esm.js → videoSelfieCameraWarmer-BH8HH2Yo.esm.js} +4 -4
- package/dist/{videoSelfieStepDetector-Dv3Mgws-.d.ts → videoSelfieStepDetector-B78BE_x9.d.ts} +2 -2
- package/dist/wasm.d.ts +1 -1
- package/dist/wasm.esm.js +1 -1
- package/dist/watchlist-for-business.esm.js +2 -2
- package/dist/watchlist.esm.js +2 -2
- package/dist/{watchlistForBusinessManager-DqUpAEj_.esm.js → watchlistForBusinessManager-DOYmIiaj.esm.js} +2 -2
- package/dist/{watchlistForBusinessStateMachine-DdaPl2PS.esm.js → watchlistForBusinessStateMachine-D8qIyL8w.esm.js} +1 -1
- package/dist/{watchlistManager-CdpXzT4B.esm.js → watchlistManager-BJGLRv-x.esm.js} +2 -2
- package/dist/{watchlistStateMachine-ofHW_lPk.esm.js → watchlistStateMachine-DeLfuGSl.esm.js} +1 -1
- package/dist/workflow.d.ts +1 -1
- package/dist/workflow.esm.js +42 -36
- package/package.json +6 -1
- package/dist/tri.esm-DvgaFxHR.esm.js +0 -3838
- package/dist/types-J6g6iKe_.d.ts +0 -6
|
@@ -0,0 +1,686 @@
|
|
|
1
|
+
import { t as api, u as endpoints } from "./api-C_P9YXbL.esm.js";
|
|
2
|
+
import { i as toIncodeApiError } from "./apiError-DzZ5OriE.esm.js";
|
|
3
|
+
import { n as loadPhoneValidation } from "./phoneValidation-OggtfjRt.esm.js";
|
|
4
|
+
import { i as assign, t as setup } from "./xstate.esm-DSajW7CJ.esm.js";
|
|
5
|
+
import { n as fromPromise } from "./xstate-actors.esm-8Gzepa_A.esm.js";
|
|
6
|
+
import { t as createBundledDefinitionSource } from "./definitionSource-1vPLtuXE.esm.js";
|
|
7
|
+
import { n as checkSupport, t as resolveForm } from "./resolveForm-f9PhUo9j.esm.js";
|
|
8
|
+
import { t as formatPhoneE164 } from "./phoneFormat-DEpESpz2.esm.js";
|
|
9
|
+
import { i as cleanName, l as validateEkycField, n as projectRules, o as formatSSN } from "./ekycRules-B7vXnbdg.esm.js";
|
|
10
|
+
import { t as formatCPF } from "./idOcrCpfUtils-Nfln1Psb.esm.js";
|
|
11
|
+
//#region src/modules/ekyc-prefill/ekycPrefillConfig.ts
|
|
12
|
+
const isString = (value) => typeof value === "string" && value !== "";
|
|
13
|
+
function toConfigField(raw) {
|
|
14
|
+
if (typeof raw !== "object" || raw === null) return void 0;
|
|
15
|
+
const { field, check, mandatory } = raw;
|
|
16
|
+
if (!isString(field)) return void 0;
|
|
17
|
+
return {
|
|
18
|
+
field,
|
|
19
|
+
check: check === true,
|
|
20
|
+
mandatory: mandatory === true
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Normalizes the served `EKYC_PREFILL` configuration. Idempotent, so a
|
|
25
|
+
* configuration that is already normalized passes through unchanged.
|
|
26
|
+
*
|
|
27
|
+
* - `check` and `mandatory` are `true` only when served as `true`; a `null`
|
|
28
|
+
* check hides the field.
|
|
29
|
+
* - `fields` stays `undefined` when the configuration has no `fields` array:
|
|
30
|
+
* the flat dashboard shape, which the module can't render.
|
|
31
|
+
* - `source`, `displayMode` and other per-field keys are dropped.
|
|
32
|
+
*/
|
|
33
|
+
function toEkycPrefillConfig(raw) {
|
|
34
|
+
const config = raw ?? {};
|
|
35
|
+
const fields = Array.isArray(config.fields) ? config.fields.map(toConfigField).filter((field) => !!field) : void 0;
|
|
36
|
+
const requireAnyOf = Array.isArray(config.requireAnyOf) ? config.requireAnyOf.filter(isString) : [];
|
|
37
|
+
return {
|
|
38
|
+
country: isString(config.country) ? config.country : void 0,
|
|
39
|
+
source: isString(config.source) ? config.source : void 0,
|
|
40
|
+
fields,
|
|
41
|
+
requireAnyOf,
|
|
42
|
+
autoExecution: config.autoExecution === true
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region ../form-definitions/generated/ekycprefill.ts
|
|
47
|
+
const EKYCPREFILL_DEFINITIONS = {
|
|
48
|
+
"ekycprefill/BR": {
|
|
49
|
+
schemaVersion: 1,
|
|
50
|
+
vocabulary: "1.0",
|
|
51
|
+
id: "ekycprefill/BR",
|
|
52
|
+
module: "ekycprefill",
|
|
53
|
+
country: "BR",
|
|
54
|
+
fields: [{
|
|
55
|
+
name: "taxIdNumber",
|
|
56
|
+
kind: "text",
|
|
57
|
+
group: "ssn",
|
|
58
|
+
label: { key: "verification.labels.taxId" },
|
|
59
|
+
displayLabel: {
|
|
60
|
+
key: "verification.labels.cpf",
|
|
61
|
+
text: "CPF"
|
|
62
|
+
},
|
|
63
|
+
input: {
|
|
64
|
+
maxLength: 14,
|
|
65
|
+
keyboard: "numeric"
|
|
66
|
+
},
|
|
67
|
+
rules: [{ id: "cpf" }],
|
|
68
|
+
payload: { transforms: [{
|
|
69
|
+
id: "stripSeparators",
|
|
70
|
+
params: { chars: ".-" }
|
|
71
|
+
}] }
|
|
72
|
+
}],
|
|
73
|
+
submit: {
|
|
74
|
+
static: { plugins: ["kyc-prefill"] },
|
|
75
|
+
context: { countryCode: "country" }
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"ekycprefill/US": {
|
|
79
|
+
schemaVersion: 1,
|
|
80
|
+
vocabulary: "1.3",
|
|
81
|
+
id: "ekycprefill/US",
|
|
82
|
+
module: "ekycprefill",
|
|
83
|
+
country: "US",
|
|
84
|
+
fields: [
|
|
85
|
+
{
|
|
86
|
+
name: "phone",
|
|
87
|
+
kind: "phone",
|
|
88
|
+
group: "phone",
|
|
89
|
+
label: { key: "verification.labels.phone" },
|
|
90
|
+
input: { autofill: "phone" },
|
|
91
|
+
phone: { lockCountry: true },
|
|
92
|
+
rules: [{ id: "phoneFormat" }],
|
|
93
|
+
payload: { transforms: [{ id: "e164" }] }
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: "dateOfBirth",
|
|
97
|
+
kind: "date",
|
|
98
|
+
group: "dateOfBirth",
|
|
99
|
+
label: { key: "verification.labels.dateOfBirth" },
|
|
100
|
+
input: { autofill: "birthday" },
|
|
101
|
+
rules: [{ id: "notFuture" }, {
|
|
102
|
+
id: "maxAge",
|
|
103
|
+
params: { years: 120 }
|
|
104
|
+
}]
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: "ssn",
|
|
108
|
+
kind: "text",
|
|
109
|
+
group: "ssn",
|
|
110
|
+
widget: "masked",
|
|
111
|
+
label: { key: "verification.labels.ssn" },
|
|
112
|
+
input: {
|
|
113
|
+
maxLength: 11,
|
|
114
|
+
keyboard: "numeric"
|
|
115
|
+
},
|
|
116
|
+
rules: [{ id: "ssnFormat" }],
|
|
117
|
+
payload: { transforms: [{
|
|
118
|
+
id: "stripSeparators",
|
|
119
|
+
params: { chars: "-" }
|
|
120
|
+
}] }
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: "surName",
|
|
124
|
+
kind: "text",
|
|
125
|
+
group: "name",
|
|
126
|
+
label: { key: "verification.labels.lastName" },
|
|
127
|
+
placeholder: { key: "verification.placeholder.lastName" },
|
|
128
|
+
input: {
|
|
129
|
+
maxLength: 100,
|
|
130
|
+
autofill: "familyName"
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
submit: {
|
|
135
|
+
static: { plugins: ["kyc-prefill"] },
|
|
136
|
+
context: { countryCode: "country" }
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
//#endregion
|
|
141
|
+
//#region src/modules/ekyc-prefill/ekycPrefillDefinition.ts
|
|
142
|
+
/**
|
|
143
|
+
* eKYC Pre-fill adapter for form definitions.
|
|
144
|
+
*
|
|
145
|
+
* The catalog (`catalog/ekycprefill`) holds one definition per country with
|
|
146
|
+
* every input the country's sources take, all optional: their kind, label,
|
|
147
|
+
* rules and request key. The served module configuration decides the rest
|
|
148
|
+
* (ENG-61990): which inputs show (`check`), which are required (`mandatory`)
|
|
149
|
+
* and which are "at least one of" (`requireAnyOf`). This overlays the served
|
|
150
|
+
* configuration on the country's definition, so eKYC Pre-fill runs the same
|
|
151
|
+
* kernel (`checkSupport`, `resolveForm`) as eKYC, eKYB and KYB Checks. It
|
|
152
|
+
* goes away once the backend serves form definitions itself.
|
|
153
|
+
*/
|
|
154
|
+
const EKYC_PREFILL_MODULE = "ekycprefill";
|
|
155
|
+
/** The message of the "at least one of" rule. Its `fields` param lists the members' labels. */
|
|
156
|
+
const ANY_OF_MESSAGE_KEY = "ekycPrefill.errors.requireAnyOf";
|
|
157
|
+
/** What the projection can express: exactly the ids the catalog uses. */
|
|
158
|
+
const EKYC_PREFILL_SUPPORTED_IDS = {
|
|
159
|
+
schemaVersions: [1],
|
|
160
|
+
vocabulary: "1.3",
|
|
161
|
+
kinds: /* @__PURE__ */ new Set([
|
|
162
|
+
"text",
|
|
163
|
+
"date",
|
|
164
|
+
"phone"
|
|
165
|
+
]),
|
|
166
|
+
groups: /* @__PURE__ */ new Set([
|
|
167
|
+
"phone",
|
|
168
|
+
"dateOfBirth",
|
|
169
|
+
"ssn",
|
|
170
|
+
"name"
|
|
171
|
+
]),
|
|
172
|
+
rules: /* @__PURE__ */ new Set([
|
|
173
|
+
"phoneFormat",
|
|
174
|
+
"notFuture",
|
|
175
|
+
"maxAge",
|
|
176
|
+
"ssnFormat",
|
|
177
|
+
"cpf"
|
|
178
|
+
]),
|
|
179
|
+
transforms: /* @__PURE__ */ new Set(["e164", "stripSeparators"]),
|
|
180
|
+
groupRules: /* @__PURE__ */ new Set(["oneOfRequired"]),
|
|
181
|
+
optionLists: /* @__PURE__ */ new Set(),
|
|
182
|
+
conditions: /* @__PURE__ */ new Set(),
|
|
183
|
+
prefillSources: /* @__PURE__ */ new Set()
|
|
184
|
+
};
|
|
185
|
+
const bundled = createBundledDefinitionSource(EKYCPREFILL_DEFINITIONS);
|
|
186
|
+
/** The catalog definition for a country, or `undefined` when it has none. */
|
|
187
|
+
function selectEkycPrefillDefinition(country) {
|
|
188
|
+
return bundled.select({
|
|
189
|
+
module: EKYC_PREFILL_MODULE,
|
|
190
|
+
country
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Applies the served configuration to the country's definition:
|
|
195
|
+
*
|
|
196
|
+
* - a field shows only when its served `check` is `true`; its group is on;
|
|
197
|
+
* - a shown field is required when served `mandatory`;
|
|
198
|
+
* - `requireAnyOf`, kept to the shown fields, becomes a `oneOfRequired`
|
|
199
|
+
* rule. One member left is simply required, so it gets the usual
|
|
200
|
+
* asterisk and message instead of an "at least one of" message;
|
|
201
|
+
* - the served `source` goes into the request body, as a served definition
|
|
202
|
+
* would carry it.
|
|
203
|
+
*
|
|
204
|
+
* A served input the definition has no field for is left out with a warning.
|
|
205
|
+
*/
|
|
206
|
+
function toEkycPrefillResolution(definition, config) {
|
|
207
|
+
const served = new Map((config.fields ?? []).map((field) => [field.field, field]));
|
|
208
|
+
const known = new Set(definition.fields.map((field) => field.name));
|
|
209
|
+
const unknownMandatory = [];
|
|
210
|
+
for (const field of served.values()) {
|
|
211
|
+
if (known.has(field.field) || !field.check) continue;
|
|
212
|
+
console.warn(`[ekyc-prefill] No "${field.field}" field for ${definition.id}; it is not shown`);
|
|
213
|
+
if (field.mandatory) unknownMandatory.push(field.field);
|
|
214
|
+
}
|
|
215
|
+
const shown = definition.fields.filter((field) => served.get(field.name)?.check === true);
|
|
216
|
+
const shownNames = new Set(shown.map((field) => field.name));
|
|
217
|
+
const anyOf = [...new Set(config.requireAnyOf)].filter((name) => shownNames.has(name));
|
|
218
|
+
const loneMember = anyOf.length === 1 ? anyOf[0] : void 0;
|
|
219
|
+
const fields = shown.map((field) => ({
|
|
220
|
+
...field,
|
|
221
|
+
required: served.get(field.name)?.mandatory === true || field.name === loneMember
|
|
222
|
+
}));
|
|
223
|
+
const groupRules = anyOf.length > 1 ? [{
|
|
224
|
+
id: "oneOfRequired",
|
|
225
|
+
fields: anyOf,
|
|
226
|
+
message: {
|
|
227
|
+
key: ANY_OF_MESSAGE_KEY,
|
|
228
|
+
text: "Provide at least one of {{fields}}"
|
|
229
|
+
}
|
|
230
|
+
}] : [];
|
|
231
|
+
return {
|
|
232
|
+
definition: {
|
|
233
|
+
...definition,
|
|
234
|
+
...config.source && { source: config.source },
|
|
235
|
+
fields,
|
|
236
|
+
groupRules,
|
|
237
|
+
submit: {
|
|
238
|
+
...definition.submit,
|
|
239
|
+
context: {
|
|
240
|
+
...definition.submit.context,
|
|
241
|
+
...config.source && { source: "source" }
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
context: { groups: Object.fromEntries(fields.map((field) => [field.group, true])) },
|
|
246
|
+
unknownMandatory
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
//#endregion
|
|
250
|
+
//#region src/modules/ekyc-prefill/ekycPrefillFields.ts
|
|
251
|
+
const PHONE_INVALID_ERROR = { key: "verification.errors.phoneInvalid" };
|
|
252
|
+
/** Vocabulary autofill ids → HTML `autocomplete` tokens (WCAG 2.2 SC 1.3.5). */
|
|
253
|
+
const AUTOCOMPLETE = {
|
|
254
|
+
givenName: "given-name",
|
|
255
|
+
middleName: "additional-name",
|
|
256
|
+
familyName: "family-name",
|
|
257
|
+
email: "email",
|
|
258
|
+
phone: "tel",
|
|
259
|
+
addressLine1: "address-line1",
|
|
260
|
+
addressLine2: "address-line2",
|
|
261
|
+
addressLevel1: "address-level1",
|
|
262
|
+
addressLevel2: "address-level2",
|
|
263
|
+
postalCode: "postal-code",
|
|
264
|
+
birthday: "bday",
|
|
265
|
+
organization: "organization"
|
|
266
|
+
};
|
|
267
|
+
const TYPES = {
|
|
268
|
+
date: "date",
|
|
269
|
+
phone: "phone"
|
|
270
|
+
};
|
|
271
|
+
/** The as-you-type format a field's rule or group implies. */
|
|
272
|
+
function formatAsOf(field) {
|
|
273
|
+
const rules = new Set((field.rules ?? []).map((rule) => rule.id));
|
|
274
|
+
if (rules.has("cpf")) return "cpf";
|
|
275
|
+
if (rules.has("ssnFormat")) return "ssn";
|
|
276
|
+
if (field.group === "name") return "name";
|
|
277
|
+
}
|
|
278
|
+
function projectField(resolved, country) {
|
|
279
|
+
const { field, required, phoneLocked } = resolved;
|
|
280
|
+
const validation = required ? [{ type: "required" }] : [];
|
|
281
|
+
validation.push(...projectRules(field.rules ?? [], country, required));
|
|
282
|
+
const autoComplete = field.input?.autofill ? AUTOCOMPLETE[field.input.autofill] : void 0;
|
|
283
|
+
const formatAs = formatAsOf(field);
|
|
284
|
+
return {
|
|
285
|
+
name: field.name,
|
|
286
|
+
type: TYPES[field.kind] ?? "text",
|
|
287
|
+
label: field.label.key,
|
|
288
|
+
required,
|
|
289
|
+
...field.displayLabel && { displayLabel: field.displayLabel.text ?? field.displayLabel.key },
|
|
290
|
+
...field.placeholder && { placeholder: field.placeholder.key },
|
|
291
|
+
...field.input?.maxLength !== void 0 && { maxLength: field.input.maxLength },
|
|
292
|
+
...field.kind === "phone" && { disableCountrySelector: phoneLocked },
|
|
293
|
+
...field.widget === "masked" && { masked: true },
|
|
294
|
+
...field.input?.keyboard === "numeric" && { numeric: true },
|
|
295
|
+
...autoComplete && { autoComplete },
|
|
296
|
+
...formatAs && { formatAs },
|
|
297
|
+
validation
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
/** The request body plan: static keys, the context keys resolved, then each field. */
|
|
301
|
+
function toSubmitPlan(definition) {
|
|
302
|
+
const context = {
|
|
303
|
+
country: definition.country,
|
|
304
|
+
source: definition.source
|
|
305
|
+
};
|
|
306
|
+
const resolvedContext = Object.fromEntries(Object.entries(definition.submit.context ?? {}).flatMap(([key, from]) => context[from] === void 0 ? [] : [[key, context[from]]]));
|
|
307
|
+
return {
|
|
308
|
+
static: {
|
|
309
|
+
...definition.submit.static,
|
|
310
|
+
...resolvedContext
|
|
311
|
+
},
|
|
312
|
+
country: definition.country ?? "",
|
|
313
|
+
fields: definition.fields.filter((field) => !field.payload?.omit).map((field) => ({
|
|
314
|
+
name: field.name,
|
|
315
|
+
key: field.payload?.key ?? field.name,
|
|
316
|
+
transforms: (field.payload?.transforms ?? []).map((transform) => ({
|
|
317
|
+
id: transform.id,
|
|
318
|
+
...typeof transform.params?.chars === "string" && { chars: transform.params.chars }
|
|
319
|
+
}))
|
|
320
|
+
}))
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
const preparedForms = /* @__PURE__ */ new WeakMap();
|
|
324
|
+
/**
|
|
325
|
+
* The served configuration on the forms kernel: the country's definition,
|
|
326
|
+
* overlaid with the served requiredness, checked, resolved and projected.
|
|
327
|
+
* `undefined` when the module can't render it: no `fields` (the flat
|
|
328
|
+
* dashboard shape), no source or country, no definition for the country, a
|
|
329
|
+
* mandatory input the definition doesn't know, no input to show, or an
|
|
330
|
+
* overlay that fails `checkSupport`, which would be a bug in the adapter.
|
|
331
|
+
*/
|
|
332
|
+
function prepareEkycPrefillForm(config) {
|
|
333
|
+
if (preparedForms.has(config)) return preparedForms.get(config) ?? void 0;
|
|
334
|
+
const prepared = prepare(config);
|
|
335
|
+
preparedForms.set(config, prepared ?? null);
|
|
336
|
+
return prepared;
|
|
337
|
+
}
|
|
338
|
+
function prepare(config) {
|
|
339
|
+
const { country, source, fields } = config;
|
|
340
|
+
if (!fields || !country || !source) return void 0;
|
|
341
|
+
const catalog = selectEkycPrefillDefinition(country);
|
|
342
|
+
if (!catalog) {
|
|
343
|
+
console.warn(`[ekyc-prefill] No form definition for country ${country}`);
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
const { definition, context, unknownMandatory } = toEkycPrefillResolution(catalog, config);
|
|
347
|
+
if (unknownMandatory.length > 0) return void 0;
|
|
348
|
+
const support = checkSupport(definition, EKYC_PREFILL_SUPPORTED_IDS);
|
|
349
|
+
if (!support.supported) {
|
|
350
|
+
console.warn("[ekyc-prefill] Unsupported form definition", support.problems);
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
const resolved = resolveForm(definition, context);
|
|
354
|
+
if (resolved.fields.length === 0) return void 0;
|
|
355
|
+
const [anyOf] = resolved.groupRules;
|
|
356
|
+
return {
|
|
357
|
+
country,
|
|
358
|
+
fields: resolved.fields.map((field) => projectField(field, country)),
|
|
359
|
+
anyOf: anyOf && {
|
|
360
|
+
fields: [...anyOf.fields],
|
|
361
|
+
message: anyOf.rule.message?.key ?? anyOf.rule.id
|
|
362
|
+
},
|
|
363
|
+
submit: toSubmitPlan(definition)
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
/** Formats a value as it is typed. */
|
|
367
|
+
function formatFieldValue(field, value) {
|
|
368
|
+
switch (field?.formatAs) {
|
|
369
|
+
case "cpf": return formatCPF(value);
|
|
370
|
+
case "ssn": return formatSSN(value);
|
|
371
|
+
case "name": return value ? cleanName(value) : value;
|
|
372
|
+
default: return value;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
const isBlank = (value) => (value ?? "").trim() === "";
|
|
376
|
+
const asEkycFields = (fields) => fields.map(({ name, type, label, displayLabel, required, validation }) => ({
|
|
377
|
+
name,
|
|
378
|
+
type,
|
|
379
|
+
label,
|
|
380
|
+
...displayLabel && { displayLabel },
|
|
381
|
+
required,
|
|
382
|
+
validation,
|
|
383
|
+
source: "user_input"
|
|
384
|
+
}));
|
|
385
|
+
/**
|
|
386
|
+
* A field's first failing rule. A phone the input itself reports as
|
|
387
|
+
* malformed fails as invalid.
|
|
388
|
+
*/
|
|
389
|
+
function validateField(prepared, values, name, invalidFormats = {}) {
|
|
390
|
+
const error = validateEkycField(values, name, asEkycFields(prepared.fields));
|
|
391
|
+
if (error) return error;
|
|
392
|
+
if (invalidFormats[name] && !isBlank(values[name])) return PHONE_INVALID_ERROR;
|
|
393
|
+
}
|
|
394
|
+
/** Every field's error. The "at least one of" rule is reported apart, by `isAnyOfMissing`. */
|
|
395
|
+
function validateForm(prepared, values, invalidFormats = {}) {
|
|
396
|
+
const errors = {};
|
|
397
|
+
for (const field of prepared.fields) {
|
|
398
|
+
const error = validateField(prepared, values, field.name, invalidFormats);
|
|
399
|
+
if (error) errors[field.name] = error;
|
|
400
|
+
}
|
|
401
|
+
return errors;
|
|
402
|
+
}
|
|
403
|
+
/** Whether the "at least one of" group has no member filled. */
|
|
404
|
+
function isAnyOfMissing(prepared, values) {
|
|
405
|
+
return !!prepared.anyOf && prepared.anyOf.fields.every((name) => isBlank(values[name]));
|
|
406
|
+
}
|
|
407
|
+
function stripChars(value, chars) {
|
|
408
|
+
const remove = new Set(chars ?? " -./");
|
|
409
|
+
return [...value].filter((char) => !remove.has(char)).join("");
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* The `POST /omni/externalVerification/ekyc-prefill` body: the static and
|
|
413
|
+
* context keys, then each filled field under its request key after its
|
|
414
|
+
* transforms. An empty field is left out.
|
|
415
|
+
*/
|
|
416
|
+
function buildSubmitBody(submit, values) {
|
|
417
|
+
const body = { ...submit.static };
|
|
418
|
+
for (const field of submit.fields) {
|
|
419
|
+
let value = (values[field.name] ?? "").trim();
|
|
420
|
+
if (value === "") continue;
|
|
421
|
+
for (const transform of field.transforms) if (transform.id === "e164") value = formatPhoneE164(value, submit.country);
|
|
422
|
+
else if (transform.id === "stripSeparators") value = stripChars(value, transform.chars);
|
|
423
|
+
body[field.key] = value;
|
|
424
|
+
}
|
|
425
|
+
return body;
|
|
426
|
+
}
|
|
427
|
+
//#endregion
|
|
428
|
+
//#region src/modules/ekyc-prefill/ekycPrefillServices.ts
|
|
429
|
+
/**
|
|
430
|
+
* Runs the eKYC Pre-fill lookup for the session. Throws an `IncodeApiError`
|
|
431
|
+
* on failure; its `status` is the body's status (4210 for a rejected phone)
|
|
432
|
+
* and `httpStatus` the HTTP one.
|
|
433
|
+
*/
|
|
434
|
+
async function submitEkycPrefill(body, signal) {
|
|
435
|
+
try {
|
|
436
|
+
const res = await api.post(endpoints.ekycPrefillSubmit, body, { signal });
|
|
437
|
+
if (!res.ok) throw res;
|
|
438
|
+
return res.data;
|
|
439
|
+
} catch (error) {
|
|
440
|
+
throw toIncodeApiError(endpoints.ekycPrefillSubmit, error);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
//#endregion
|
|
444
|
+
//#region src/modules/ekyc-prefill/ekycPrefillStateMachine.ts
|
|
445
|
+
/** The body status the backend answers a phone it rejects with. */
|
|
446
|
+
const PHONE_REJECTED_STATUS = 4210;
|
|
447
|
+
/** Shown when the backend rejects the request and no single field is to blame. */
|
|
448
|
+
const SUBMIT_REJECTED_KEY = "ekycPrefill.errors.checkInformation";
|
|
449
|
+
const CPF_INVALID_KEY = "verification.errors.invalidTaxId";
|
|
450
|
+
/** Loads the phone rules, rejecting when the load fails or times out. */
|
|
451
|
+
const requirePhoneRules = async () => {
|
|
452
|
+
if (!await loadPhoneValidation()) throw new Error("Failed to load the phone validation rules");
|
|
453
|
+
};
|
|
454
|
+
/** Only the `e164` transform needs the phone rules to build the body. */
|
|
455
|
+
const needsPhoneRules = (submit) => submit.fields.some((field) => field.transforms.some((transform) => transform.id === "e164"));
|
|
456
|
+
/**
|
|
457
|
+
* The HTTP and body statuses of a failed request. Read by shape rather than
|
|
458
|
+
* `instanceof IncodeApiError`, so a test or story double reaches each branch.
|
|
459
|
+
*/
|
|
460
|
+
const statusesOf = (error) => {
|
|
461
|
+
if (typeof error !== "object" || error === null) return {};
|
|
462
|
+
const { httpStatus, status } = error;
|
|
463
|
+
return {
|
|
464
|
+
...typeof httpStatus === "number" && { httpStatus },
|
|
465
|
+
...typeof status === "number" && { status }
|
|
466
|
+
};
|
|
467
|
+
};
|
|
468
|
+
const httpStatusOf = (error) => statusesOf(error).httpStatus;
|
|
469
|
+
const errorOf = (event) => event.error;
|
|
470
|
+
const ekycPrefillMachine = setup({
|
|
471
|
+
types: {
|
|
472
|
+
context: {},
|
|
473
|
+
events: {},
|
|
474
|
+
input: {}
|
|
475
|
+
},
|
|
476
|
+
actors: {
|
|
477
|
+
loadPhoneRules: fromPromise(async ({ input }) => {
|
|
478
|
+
if (input.hasPhone) await requirePhoneRules();
|
|
479
|
+
}),
|
|
480
|
+
submit: fromPromise(async ({ input, signal }) => {
|
|
481
|
+
if (needsPhoneRules(input.submit)) await requirePhoneRules();
|
|
482
|
+
return submitEkycPrefill(buildSubmitBody(input.submit, input.values), signal);
|
|
483
|
+
})
|
|
484
|
+
},
|
|
485
|
+
actions: {
|
|
486
|
+
applyForm: assign(({ context }) => ({ prepared: prepareEkycPrefillForm(context.config) })),
|
|
487
|
+
setPhoneRulesLoaded: assign({ phoneRulesLoaded: true }),
|
|
488
|
+
setPhoneRulesFailed: assign(({ event }) => {
|
|
489
|
+
const error = errorOf(event);
|
|
490
|
+
return {
|
|
491
|
+
phoneRulesFailed: true,
|
|
492
|
+
errorKind: "unavailable",
|
|
493
|
+
errorMessage: error instanceof Error ? error.message : String(error)
|
|
494
|
+
};
|
|
495
|
+
}),
|
|
496
|
+
setFieldValue: assign(({ context, event }) => {
|
|
497
|
+
const { name, value, isValid } = event;
|
|
498
|
+
const prepared = context.prepared;
|
|
499
|
+
const field = prepared.fields.find((f) => f.name === name);
|
|
500
|
+
const values = {
|
|
501
|
+
...context.values,
|
|
502
|
+
[name]: formatFieldValue(field, value)
|
|
503
|
+
};
|
|
504
|
+
const invalidFormats = { ...context.invalidFormats };
|
|
505
|
+
if (isValid === false) invalidFormats[name] = true;
|
|
506
|
+
else delete invalidFormats[name];
|
|
507
|
+
const errors = { ...context.errors };
|
|
508
|
+
delete errors[name];
|
|
509
|
+
return {
|
|
510
|
+
values,
|
|
511
|
+
errors,
|
|
512
|
+
invalidFormats,
|
|
513
|
+
submitError: void 0,
|
|
514
|
+
anyOfError: context.anyOfError && isAnyOfMissing(prepared, values)
|
|
515
|
+
};
|
|
516
|
+
}),
|
|
517
|
+
validateOneField: assign(({ context, event }) => {
|
|
518
|
+
const { name } = event;
|
|
519
|
+
const prepared = context.prepared;
|
|
520
|
+
const error = validateField(prepared, context.values, name, context.invalidFormats);
|
|
521
|
+
const errors = { ...context.errors };
|
|
522
|
+
if (error) errors[name] = error;
|
|
523
|
+
else delete errors[name];
|
|
524
|
+
const leftEmptyMember = !!prepared.anyOf?.fields.includes(name) && isAnyOfMissing(prepared, context.values);
|
|
525
|
+
return {
|
|
526
|
+
errors,
|
|
527
|
+
anyOfError: context.anyOfError || leftEmptyMember
|
|
528
|
+
};
|
|
529
|
+
}),
|
|
530
|
+
validateAll: assign(({ context }) => {
|
|
531
|
+
const prepared = context.prepared;
|
|
532
|
+
return {
|
|
533
|
+
errors: validateForm(prepared, context.values, context.invalidFormats),
|
|
534
|
+
anyOfError: isAnyOfMissing(prepared, context.values)
|
|
535
|
+
};
|
|
536
|
+
}),
|
|
537
|
+
applyRejection: assign(({ context, event }) => {
|
|
538
|
+
const error = errorOf(event);
|
|
539
|
+
const prepared = context.prepared;
|
|
540
|
+
const names = prepared.fields.map((field) => field.name);
|
|
541
|
+
if (statusesOf(error).status === PHONE_REJECTED_STATUS && names.includes("phone")) return { errors: {
|
|
542
|
+
...context.errors,
|
|
543
|
+
phone: PHONE_INVALID_ERROR
|
|
544
|
+
} };
|
|
545
|
+
const cpfField = prepared.fields.find((field) => field.formatAs === "cpf");
|
|
546
|
+
if (cpfField && names.length === 1) return { errors: {
|
|
547
|
+
...context.errors,
|
|
548
|
+
[cpfField.name]: { key: CPF_INVALID_KEY }
|
|
549
|
+
} };
|
|
550
|
+
return { submitError: SUBMIT_REJECTED_KEY };
|
|
551
|
+
}),
|
|
552
|
+
setSubmitError: assign(({ event }) => {
|
|
553
|
+
const error = errorOf(event);
|
|
554
|
+
return {
|
|
555
|
+
errorKind: httpStatusOf(error) === 409 ? "busy" : "unavailable",
|
|
556
|
+
errorMessage: error instanceof Error ? error.message : String(error)
|
|
557
|
+
};
|
|
558
|
+
}),
|
|
559
|
+
clearError: assign({
|
|
560
|
+
errorKind: void 0,
|
|
561
|
+
errorMessage: void 0,
|
|
562
|
+
phoneRulesFailed: false
|
|
563
|
+
})
|
|
564
|
+
},
|
|
565
|
+
guards: {
|
|
566
|
+
phoneRulesFailed: ({ context }) => context.phoneRulesFailed,
|
|
567
|
+
isAutoExecution: ({ context }) => context.config.autoExecution,
|
|
568
|
+
canRender: ({ context }) => !!prepareEkycPrefillForm(context.config),
|
|
569
|
+
isValid: ({ context }) => Object.keys(context.errors).length === 0 && !context.anyOfError && !!context.prepared,
|
|
570
|
+
isBadRequest: ({ event }) => httpStatusOf(errorOf(event)) === 400,
|
|
571
|
+
isForbidden: ({ event }) => httpStatusOf(errorOf(event)) === 403,
|
|
572
|
+
isLimitReached: ({ event }) => httpStatusOf(errorOf(event)) === 429
|
|
573
|
+
}
|
|
574
|
+
}).createMachine({
|
|
575
|
+
id: "ekycPrefill",
|
|
576
|
+
initial: "idle",
|
|
577
|
+
context: ({ input }) => ({
|
|
578
|
+
config: toEkycPrefillConfig(input?.config),
|
|
579
|
+
prepared: void 0,
|
|
580
|
+
values: {},
|
|
581
|
+
errors: {},
|
|
582
|
+
invalidFormats: {},
|
|
583
|
+
anyOfError: false,
|
|
584
|
+
phoneRulesLoaded: false,
|
|
585
|
+
phoneRulesFailed: false,
|
|
586
|
+
submitError: void 0,
|
|
587
|
+
errorKind: void 0,
|
|
588
|
+
errorMessage: void 0
|
|
589
|
+
}),
|
|
590
|
+
states: {
|
|
591
|
+
idle: { on: { LOAD: [
|
|
592
|
+
{
|
|
593
|
+
guard: "isAutoExecution",
|
|
594
|
+
target: "finished"
|
|
595
|
+
},
|
|
596
|
+
{
|
|
597
|
+
guard: "canRender",
|
|
598
|
+
target: "form",
|
|
599
|
+
actions: "applyForm"
|
|
600
|
+
},
|
|
601
|
+
{ target: "misconfigured" }
|
|
602
|
+
] } },
|
|
603
|
+
form: {
|
|
604
|
+
invoke: {
|
|
605
|
+
id: "loadPhoneRules",
|
|
606
|
+
src: "loadPhoneRules",
|
|
607
|
+
input: ({ context }) => ({ hasPhone: !!context.prepared?.fields.some((field) => field.type === "phone") }),
|
|
608
|
+
onDone: { actions: "setPhoneRulesLoaded" },
|
|
609
|
+
onError: {
|
|
610
|
+
target: "#ekycPrefill.error",
|
|
611
|
+
actions: "setPhoneRulesFailed"
|
|
612
|
+
}
|
|
613
|
+
},
|
|
614
|
+
initial: "inputting",
|
|
615
|
+
states: {
|
|
616
|
+
inputting: { on: {
|
|
617
|
+
SET_FIELD: { actions: "setFieldValue" },
|
|
618
|
+
VALIDATE_FIELD: { actions: "validateOneField" },
|
|
619
|
+
SUBMIT: "validating"
|
|
620
|
+
} },
|
|
621
|
+
validating: {
|
|
622
|
+
entry: "validateAll",
|
|
623
|
+
always: [{
|
|
624
|
+
guard: "isValid",
|
|
625
|
+
target: "#ekycPrefill.submitting"
|
|
626
|
+
}, { target: "inputting" }]
|
|
627
|
+
}
|
|
628
|
+
},
|
|
629
|
+
on: { CLOSE: "closed" }
|
|
630
|
+
},
|
|
631
|
+
submitting: { invoke: {
|
|
632
|
+
id: "submit",
|
|
633
|
+
src: "submit",
|
|
634
|
+
input: ({ context }) => ({
|
|
635
|
+
submit: context.prepared.submit,
|
|
636
|
+
values: context.values
|
|
637
|
+
}),
|
|
638
|
+
onDone: { target: "finished" },
|
|
639
|
+
onError: [
|
|
640
|
+
{
|
|
641
|
+
guard: "isLimitReached",
|
|
642
|
+
target: "limitReached"
|
|
643
|
+
},
|
|
644
|
+
{
|
|
645
|
+
guard: "isBadRequest",
|
|
646
|
+
target: "form.inputting",
|
|
647
|
+
actions: "applyRejection"
|
|
648
|
+
},
|
|
649
|
+
{
|
|
650
|
+
guard: "isForbidden",
|
|
651
|
+
target: "misconfigured"
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
target: "error",
|
|
655
|
+
actions: "setSubmitError"
|
|
656
|
+
}
|
|
657
|
+
]
|
|
658
|
+
} },
|
|
659
|
+
/**
|
|
660
|
+
* The lookup could not run (409, 503, a network failure), or the phone
|
|
661
|
+
* rules did not load: offer a retry of whichever failed.
|
|
662
|
+
*/
|
|
663
|
+
error: { on: {
|
|
664
|
+
RETRY: [{
|
|
665
|
+
guard: "phoneRulesFailed",
|
|
666
|
+
target: "form",
|
|
667
|
+
actions: "clearError"
|
|
668
|
+
}, {
|
|
669
|
+
target: "submitting",
|
|
670
|
+
actions: "clearError"
|
|
671
|
+
}],
|
|
672
|
+
CLOSE: "closed"
|
|
673
|
+
} },
|
|
674
|
+
/** The lookup limit is reached; it does not reset within the session, so the flow moves on. */
|
|
675
|
+
limitReached: { on: {
|
|
676
|
+
CONTINUE: "finished",
|
|
677
|
+
CLOSE: "closed"
|
|
678
|
+
} },
|
|
679
|
+
/** The configuration can't be rendered, or the session's flow doesn't allow the lookup. */
|
|
680
|
+
misconfigured: { on: { CLOSE: "closed" } },
|
|
681
|
+
finished: { type: "final" },
|
|
682
|
+
closed: { type: "final" }
|
|
683
|
+
}
|
|
684
|
+
});
|
|
685
|
+
//#endregion
|
|
686
|
+
export { toEkycPrefillConfig as i, isAnyOfMissing as n, validateForm as r, ekycPrefillMachine as t };
|