@voltom.io/sdk 0.0.0-stage → 1.0.2

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.
@@ -0,0 +1,2 @@
1
+ /*! Copyright (c) 2026 VOLTOM. All rights reserved. Proprietary software. See LICENSE at https://voltom.io/license. */
2
+ import{$ as e,G as t,J as n,K as r,X as i,_ as a,c as o,dt as s,et as c,i as l,j as u,k as d,n as f,nt as p,q as m,r as h,rt as g,s as _,t as v,v as y}from"./faceMatch.shared-D6B1I2T0.js";import{n as b,t as x}from"./presentation-Jz2euuHa.js";var S=u({runtime:d}),C=f({runtime:d}),w=l({runtime:d}),T=h({runtime:d,imageFromImageBitmap:S}),E=v({runtime:d,...C,...w,...T,faceDetection:T}),D=e=>{if(typeof e.token!=`string`||e.token.length<32||e.token.length>128||e.userId!==void 0&&(typeof e.userId!=`string`||e.userId.length<1||e.userId.length>255))throw Error(c.INVALID_OPTIONS);return e},O=e=>e.length===512&&e.every(e=>Number.isFinite(e))&&Math.abs(Math.hypot(...e)-1)<.001?e:null,{detectDocumentBox:k,loadDocumentBoxDetector:A}=w,{detectPictureFaces:j,loadFaceDetector:M}=T,{imageBitmap:N,loadFaceMatch:P,preparedFaceEmbeddings:F,prepareFace:I,warmupFaceMatch:L}=E,R=({face:e})=>e?{left:e.blendshapes.eyeBlinkLeft??0,right:e.blendshapes.eyeBlinkRight??0}:null,z=({face:e,frame:t})=>e.boundingRect.height/Math.min(t.width,t.height)<.5?`FACE_TOO_SMALL`:null,B=({face:e,frame:t})=>{let n=e.boundingRect.x+e.boundingRect.width/2,r=e.boundingRect.y+e.boundingRect.height/2,i=Math.min(t.width,t.height);return Math.hypot(n-t.width/2,r-t.height/2)<=i*.08},V=async({frame:e,pose:t,signal:n})=>{let r=await j(e);n.throwIfAborted();let i=r.length===1?r[0]:null,s=i?await k(e):null;n.throwIfAborted();let c=!!(i&&s&&a({face:i,polygon:s.polygon})),l=i?z({face:i,frame:e}):null,u=!!(i&&B({face:i,frame:e})),d=i?o({...i,pose:t,options:y}):null,f=`Keep one face in view`;i&&(f=(c?`In polygon`:null)??l??(u?d:`Center your face in the circle`));let p=d;return u||(p=`FACE_NOT_CENTERED`),l&&(p=`FACE_TOO_SMALL`),c&&(p=`FACE_IN_POLYGON`),i||(p=`FACE_NOT_DETECTED`),{faces:r,face:i,faceInPolygon:c,framing:l,centered:u,poseRejection:d,reason:f,code:p}},H=async({capture:e,pose:t,signal:n,language:r})=>{let i=await N({blob:e});try{n.throwIfAborted();let e=await V({frame:i,pose:t,signal:n}),{face:a,poseRejection:o}=e,s=R({face:a}),l=o&&e.reason===o?b({pose:t,rejection:o,language:r}):e.reason;if(!a||l)return{vector:null,reason:l,eyeScores:s};let u=I({alignment:`eyes-nose-mouth`,face:a,frame:i}),d=u?await F({face:u}):null;if(n.throwIfAborted(),!d)return{vector:null,reason:c.FACE_NOT_USABLE,eyeScores:s};let f=O(d.grayscale);return{vector:f,reason:f?null:c.INVALID_MODEL_OUTPUT,eyeScores:s}}finally{i.close()}},U=class{options;view=null;useUi;display=x();events=new EventTarget;controller=null;operationId=``;modelsReady=null;prepared=!1;disposed=!1;subscriptions=new Set;constructor(e){if(this.useUi=e.ui??!e.video,!this.useUi&&!e.video)throw Error(c.INVALID_OPTIONS);this.options=Object.freeze({...e,capabilities:Object.freeze([...e.capabilities??[`enroll`,`unlock`,`forget`]])})}async prepare(){if(this.disposed)throw Error(c.SDK_NOT_READY);if(this.prepared)return;if(await e({language:this.options.language}),this.useUi&&!this.view){let{createFaceKeyView:e}=await import(`./view-vxhVZZc1.js`);if(this.disposed)throw Error(c.SDK_NOT_READY);this.view=e({options:this.options,display:this.display,events:this.events,onStop:()=>this.stop()})}if(!this.modelsReady){let e=this.options.capabilities.some(e=>e!==`forget`)?Promise.all([A(),M({faceDetector:`standard`}),P()]).then(async()=>{let e=document.createElement(`canvas`);e.width=640,e.height=480;let t=await createImageBitmap(e);try{await Promise.all([j(t),k(t),L()])}finally{t.close()}}):Promise.resolve();this.modelsReady=e}let t=this.modelsReady;try{if(await t,this.disposed)throw Error(c.SDK_NOT_READY);this.prepared=!0}catch(e){throw this.modelsReady===t&&(this.modelsReady=null),e}}async request({path:e,input:t,body:n,signal:r}){let i={authorization:`Bearer ${this.options.clientKey}`,"content-type":`application/json`},a=await fetch(`${(this.options.apiUrl??`https://api.voltom.io`).replace(/\/$/,``)}/facekey/${e}`,{method:`POST`,headers:i,body:JSON.stringify(n??t),signal:r}),o=await a.json();if(r.throwIfAborted(),!a.ok)throw Error(typeof o.code==`string`?o.code:c.INVALID_SERVICE_RESPONSE);return o}async capture({poses:e,signal:a,expiresAt:o,operation:s,input:l}){let u=this.useUi?this.view?.requiredVideo():this.options.video;if(!u)throw Error(c.INVALID_OPTIONS);let d=[];this.display.progress.value={completed:0,total:e.length};let f=null,h={userId:l.userId??``,matched:!1,matches:[],reason:null},g=l.token;a.throwIfAborted();let v=await m({facingMode:`user`,video:u,signal:a});a.throwIfAborted(),this.display.facingMode.value=v,this.display.phase.value=`capturing`;for(let[n,m]of e.entries()){let v=0,y=null;for(p(()=>{this.display.match.value=null,this.display.phase.value=`capturing`,this.display.instruction.value={pose:m,rejection:null,retry:null}});v<3;){if(await i({video:u,signal:a}),a.throwIfAborted(),Date.now()>=Date.parse(o))throw Error(c.FACEKEY_TOKEN_INVALID);if(u.readyState<HTMLMediaElement.HAVE_CURRENT_DATA)continue;let b=await createImageBitmap(u);try{let i=await V({frame:b,pose:m,signal:a}),{reason:u,code:x}=i;v=u===null?v+1:0;let S={...i,frame:b,operation:s,pose:m,stable:v};if(this.view?.collectCaptureDebug(S),this.display.instruction.value={pose:m,rejection:x,retry:y},v===3){let i=await t({frame:b});try{if(s===`unlock`){this.display.phase.value=`checking`;let t={token:g,userId:h.userId,poses:[m],faces:[await r({image:i})]},o=await this.request({path:`unlock/step`,input:{...l,token:g},body:t,signal:a});if(o.userId!==h.userId||o.matched&&(o.matches.length!==1||o.matches[0].pose!==m||!o.matches[0].matched))throw Error(c.INVALID_SERVICE_RESPONSE);if(this.display.match.value={accepted:o.matched,reason:o.reason,score:o.matches.length?o.matches[0].score:null},this.view?.collectCaptureDebug({...S,force:!0,reason:o.reason}),!o.matched){if(o.complete||!o.token)throw Error(c.INVALID_SERVICE_RESPONSE);g=o.token,v=0,y=`Face not recognized. Try this pose again.`,p(()=>{this.display.phase.value=`capturing`,this.display.instruction.value={pose:m,rejection:x,retry:y}}),await this.showFeedback({matched:!1,signal:a});continue}if(h={userId:o.userId,matched:o.complete,matches:[...h.matches,...o.matches],reason:o.reason},o.complete!==(n===e.length-1))throw Error(c.INVALID_SERVICE_RESPONSE);if(!o.complete){if(!o.token)throw Error(c.INVALID_SERVICE_RESPONSE);g=o.token}}else{let e=await H({capture:i,pose:m,signal:a,language:this.options.language}),t=e.vector;if(a.throwIfAborted(),Date.now()>=Date.parse(o))throw Error(c.FACEKEY_TOKEN_INVALID);let n=f&&t?_({first:f,second:t}):null,r=!!(t&&(n===null||n>.5)),s=e.reason??(r?null:c.POSE_IDENTITY_MISMATCH);if(this.display.match.value={accepted:r,reason:s,reference:!f&&r,score:n},this.view?.collectCaptureDebug({...S,force:!0,reason:s}),!t||!r){v=0,y=t?`Face does not match. Try this pose again.`:`Face not usable. Try this pose again.`,p(()=>{this.display.phase.value=`capturing`,this.display.instruction.value={pose:m,rejection:x,retry:y}}),t&&await this.showFeedback({matched:!1,signal:a});continue}f||=t}d.push(i)}catch(e){let t=e instanceof Error?e.message:`Capture failed`;throw this.display.match.value={accepted:!1,reason:t,score:null},this.view?.collectCaptureDebug({...S,force:!0,reason:t}),e}}}finally{b.close()}}this.display.progress.value={completed:n+1,total:e.length},await this.showFeedback({matched:!0,signal:a})}return n({video:u}),{captures:d,unlock:h}}async showFeedback({matched:e,signal:t}){t.throwIfAborted();let n=this.operationId;p(()=>{this.display.failures.value=e?0:this.display.failures.value+1,this.display.feedback.value={matched:e,animating:!0}});let r=Promise.withResolvers(),i=setTimeout(()=>r.resolve(),500),a=()=>r.resolve();t.addEventListener(`abort`,a,{once:!0});try{await r.promise,t.throwIfAborted()}finally{clearTimeout(i),t.removeEventListener(`abort`,a),this.operationId===n&&(this.display.feedback.value=e?null:{matched:!1,animating:!1})}}async run({operation:e,input:t,externalSignal:i,debug:a}){if(this.disposed||!this.prepared)throw Error(c.SDK_NOT_READY);if(!this.options.capabilities.includes(e))throw Error(c.SDK_CAPABILITY_NOT_CONFIGURED);if(this.controller)throw Error(c.INVALID_OPTIONS);let o=D(t);if(e!==`enroll`&&!o.userId)throw Error(c.INVALID_OPTIONS);let s=new AbortController;this.controller=s;let l=s.signal,u=()=>s.abort();i?.addEventListener(`abort`,u,{once:!0}),i?.aborted&&u();let d=[];this.operationId=crypto.randomUUID();try{if(e===`forget`)return await this.request({path:e,input:o,signal:l});p(()=>{this.display.operation.value=e,this.display.phase.value=`loading`,this.display.instruction.value=null,this.display.feedback.value=null,this.display.failures.value=0,this.display.error.value=null,this.display.debug.value=[],this.display.debugEnabled.value=a??this.options.debug??!1,this.display.match.value=null,this.display.progress.value={completed:0,total:1},this.display.facingMode.value=null}),this.view?.open();let t=await this.request({path:`challenge`,input:o,signal:l});if(t.operation!==e||o.userId&&t.userId!==o.userId)throw Error(c.FACEKEY_TOKEN_INVALID);let n=await this.capture({poses:t.poses,signal:l,expiresAt:t.expiresAt,operation:e,input:{...o,userId:t.userId}});d.push(...n.captures),l.throwIfAborted();let i=n.unlock;if(e===`enroll`){this.display.phase.value=`processing`;let n={token:o.token,userId:t.userId,poses:t.poses,faces:await Promise.all(d.map(e=>r({image:e})))};i=await this.request({path:e,input:o,body:n,signal:l})}let s=!(`matched`in i)||i.matched===!0;return this.display.phase.value=s?`success`:`failure`,await this.showFeedback({matched:s,signal:l}),i}catch(e){throw this.view?.dialog?.open&&p(()=>{this.display.phase.value=`failure`,this.display.error.value=e}),e}finally{i?.removeEventListener(`abort`,u),this.display.debugEnabled.value=this.options.debug??!1,d.length=0;let e=this.useUi?this.view?.dialog?.open?this.view.requiredVideo():null:this.options.video;e&&n({video:e}),this.view?.close(),this.controller=null}}async faceEnroll(e,{signal:t,debug:n}={}){return await this.run({operation:`enroll`,input:e,externalSignal:t,debug:n})}async faceUnlock(e,{signal:t,debug:n}={}){return await this.run({operation:`unlock`,input:e,externalSignal:t,debug:n})}async faceForget(e,{signal:t,debug:n}={}){return await this.run({operation:`forget`,input:e,externalSignal:t,debug:n})}stop(){this.controller&&this.controller.abort(new DOMException(c.VERIFICATION_CANCELLED,`AbortError`));let e=this.useUi?this.view?.dialog?.open?this.view.requiredVideo():null:this.options.video;e&&n({video:e}),this.view?.close()}dispose(){if(!this.disposed){this.disposed=!0,this.stop();for(let e of this.subscriptions)e();this.subscriptions.clear(),this.events=new EventTarget}}getState(){return{operation:this.display.operation.value,phase:this.display.phase.value,instruction:this.display.instruction.value,feedback:this.display.feedback.value,error:this.display.error.value,progress:this.display.progress.value,match:this.display.match.value,debug:this.display.debug.value}}subscribe(e){if(this.disposed)throw Error(c.SDK_NOT_READY);let t=g(()=>e(this.getState()));return this.subscriptions.add(t),()=>{t(),this.subscriptions.delete(t)}}};s({moduleUrl:import.meta.url});var W=U;export{U as VoltomFaceKey,W as default};
@@ -0,0 +1,2 @@
1
+ /*! Copyright (c) 2026 VOLTOM. All rights reserved. Proprietary software. See LICENSE at https://voltom.io/license. */
2
+ var e={facePoses:{faceStraight:{arrow:`•`,primary:`lookStraight`},faceUp:{arrow:`↑`,primary:`lookUp`},faceDown:{arrow:`↓`,primary:`lookDown`},faceLeft:{arrow:`←`,primary:`lookLeft`},faceRight:{arrow:`→`,primary:`lookRight`},faceSmile:{arrow:`◡`,primary:`smile`},faceWinkLeft:{arrow:`-•`,primary:`winkLeft`},faceTiltLeft:{arrow:`⤹`,primary:`tiltLeft`},faceTiltRight:{arrow:`⤵`,primary:`tiltRight`}},poseRejections:{FACE_ROLL_TILT_LEFT:`tiltLeft`,FACE_ROLL_TILT_RIGHT:`tiltRight`,FACE_ROLL_TILT_LESS:`tiltLess`,FACE_YAW_TURN_LEFT:`lookLeft`,FACE_YAW_TURN_RIGHT:`lookRight`,FACE_YAW_TURN_LESS:`turnLess`,FACE_PITCH_LOOK_UP:`lookUp`,FACE_PITCH_LOOK_DOWN:`lookDown`,FACE_PITCH_RAISE_LESS:`raiseLess`,FACE_PITCH_LOWER_LESS:`lowerLess`,FACE_SMILE_REQUIRED:`smile`,FACE_WINK_LEFT_REQUIRED:`winkLeft`,FACEKEY_LOWER_HEAD:`lookDown`,FACEKEY_LOWER_HEAD_LESS:`lowerLess`,FACEKEY_RAISE_HEAD:`lookUp`,FACEKEY_RAISE_HEAD_LESS:`raiseLess`,FACEKEY_SMILE_REQUIRED:`smile`,FACEKEY_TILT_HEAD_LEFT:`tiltLeft`,FACEKEY_TILT_HEAD_LESS:`tiltLess`,FACEKEY_TILT_HEAD_RIGHT:`tiltRight`,FACEKEY_TURN_HEAD_LEFT:`lookLeft`,FACEKEY_TURN_HEAD_LESS:`turnLess`,FACEKEY_TURN_HEAD_RIGHT:`lookRight`,FACEKEY_WINK_LEFT_REQUIRED:`winkLeft`}},t=({pose:t})=>{let n=e.facePoses[t];return{...n,primary:n.primary}},n=({code:t})=>e.poseRejections[t];export{n,t};
@@ -0,0 +1,8 @@
1
+ /*! Copyright (c) 2026 VOLTOM. All rights reserved. Proprietary software. See LICENSE at https://voltom.io/license. */
2
+ import{A as e,B as t,C as n,D as r,E as i,F as a,G as o,I as s,L as c,M as l,O as u,P as d,R as f,S as p,T as m,U as h,V as g,X as _,_ as v,b as y,et as b,f as x,ft as S,i as C,it as w,j as T,k as E,m as D,n as O,o as k,r as A,t as j,w as M,x as ee,y as N,z as P}from"./faceMatch.shared-D6B1I2T0.js";var te=({box:e,image:t})=>{let n=Math.max(0,Math.floor(e.left)),r=Math.max(0,Math.floor(e.top)),i=Math.min(t.width,Math.ceil(e.right)),a=Math.min(t.height,Math.ceil(e.bottom)),o=Math.max(1,i-n),s=Math.max(1,a-r),c=new Uint8ClampedArray(o*s*4);for(let e=0;e<s;e+=1){let i=((r+e)*t.width+n)*4,a=e*o*4;c.set(t.data.subarray(i,i+o*4),a)}return{data:c,height:s,width:o}},ne=({height:e,image:t,width:n})=>{let r=new Uint8ClampedArray(n*e*4),i=t.width/n,a=t.height/e;for(let o=0;o<e;o+=1){let e=Math.min(t.height-1,Math.floor((o+.5)*a));for(let a=0;a<n;a+=1){let s=Math.min(t.width-1,Math.floor((a+.5)*i)),c=(e*t.width+s)*4,l=(o*n+a)*4;r[l]=t.data[c]??0,r[l+1]=t.data[c+1]??0,r[l+2]=t.data[c+2]??0,r[l+3]=255}}return{data:r,height:e,width:n}},re=.3,ie=.6,ae=12,oe=3,se=async({session:e,tensor:n})=>{let r=performance.now();try{let t=await e.run({[e.inputNames[0]]:n}),r=t[e.outputNames[0]];if(!r){for(let e of Object.values(t))e.dispose();throw Error(P.INVALID_MODEL_OUTPUT)}for(let e of Object.values(t))e!==r&&e.dispose();return r}catch(e){throw Error(t({error:e,fallback:P.INFERENCE_FAILED}),{cause:e})}finally{s({category:`inference`,duration:performance.now()-r,key:`ocr`}),n.dispose()}},ce=({text:e})=>e.normalize(`NFKC`).replace(/\r\n?/gu,`
3
+ `).replace(/[\t\f\v ]+/gu,` `).replace(/ *\n */gu,`
4
+ `).trim(),le=({pixels:e,runtime:t})=>{let n=Math.max(32,Math.ceil(e.width/32)*32),r=Math.max(32,Math.ceil(e.height/32)*32),i=new Float32Array(3*n*r),a=[.485,.456,.406],o=[.229,.224,.225];for(let e=0;e<3;e+=1)i.fill((1-(a[e]??0))/(o[e]??1),e*n*r,(e+1)*n*r);for(let t=0;t<e.height;t+=1)for(let s=0;s<e.width;s+=1){let c=(t*e.width+s)*4,l=t*n+s;for(let t=0;t<3;t+=1){let s=(e.data[c+t]??0)/255;i[t*n*r+l]=(s-(a[t]??0))/(o[t]??1)}}return{height:r,tensor:new t.Tensor(`float32`,i,[1,3,r,n]),width:n}},ue=({height:e,scores:t,width:n})=>{let r=new Uint8Array(n*e),i=[],a=new Int32Array(n*e);for(let o=0;o<t.length;o+=1){if(r[o]||(t[o]??0)<re)continue;let s=0,c=1,l=o%n,u=l,d=Math.floor(o/n),f=d,p=0,m=0;for(a[0]=o,r[o]=1;s<c;){let i=a[s]??0;s+=1;let o=i%n,h=Math.floor(i/n);l=Math.min(l,o),u=Math.max(u,o),d=Math.min(d,h),f=Math.max(f,h),p+=t[i]??0,m+=1;for(let i=-1;i<=1;i+=1)for(let s=-1;s<=1;s+=1){let l=o+s,u=h+i;if(l<0||l>=n||u<0||u>=e)continue;let d=u*n+l;r[d]||(t[d]??0)<re||(r[d]=1,a[c]=d,c+=1)}}let h=u-l+1,g=f-d+1;if(m<ae||h<oe||g<oe||p/m<ie)continue;let _=h*.25,v=g*.35;i.push({bottom:f+1+v,left:l-_,right:u+1+_,score:p/m,top:d-v})}return i},de=({boxes:e})=>e.sort((e,t)=>{let n=e.bottom-e.top,r=t.bottom-t.top,i=Math.max(n,r)*.6;return Math.abs(e.top-t.top)<=i?e.left-t.left:e.top-t.top}),fe=async({pixels:e,runtime:t,session:n})=>{let r=le({pixels:e,runtime:t}),i=await se({session:n,tensor:r.tensor});try{let e=Number(i.dims.at(-2)),t=Number(i.dims.at(-1)),n=ue({height:e,scores:i.data,width:t}),a=r.width/t,o=r.height/e;return de({boxes:n.map(({bottom:e,left:t,right:n,top:r})=>({bottom:e*o,left:t*a,right:n*a,top:r*o}))})}finally{i.dispose()}},pe=({pixels:e,runtime:t,model:n})=>{let r=n.recognitionHeight,i=Math.max(1,Math.round(e.width/e.height*r)),a=Math.max(32,Math.ceil(i/32)*32),o=ne({height:r,image:e,width:i}),s=new Float32Array(3*a*r);for(let e=0;e<r;e+=1)for(let t=0;t<i;t+=1){let c=(e*i+t)*4,l=e*a+t,u=o.data[c],d=o.data[c+1],f=o.data[c+2],p=u*.299+d*.587+f*.114;s[l]=((n.channels===`grayscale`?p:f)/255-.5)/.5,s[a*r+l]=((n.channels===`grayscale`?p:d)/255-.5)/.5,s[2*a*r+l]=((n.channels===`grayscale`?p:u)/255-.5)/.5}return new t.Tensor(`float32`,s,[1,3,r,a])},me=({text:e})=>{let t=[],n=``;for(let r of e)/[a-zA-Z0-9 :*./%+-]/u.test(r)?n+=r:(n&&t.push(n),t.push(r),n=``);return n&&t.push(n),t.reverse().join(``)},he=({dictionary:e,output:t,reverse:n})=>{let r=Number(t.dims.at(-1)),i=Number(t.dims.at(-2)),a=e[0]===``?[...e]:[``,...e];if(a.length===r-1&&a.push(` `),a.length!==r)throw Error(P.OCR_DICTIONARY_MISMATCH);let o=-1,s=``;for(let e=0;e<i;e+=1){let n=e*r,i=0,c=t.data[n]??-1/0;for(let e=1;e<r;e+=1){let r=t.data[n+e]??-1/0;r<=c||(i=e,c=r)}i!==0&&i!==o&&(s+=a[i]??``),o=i}let c=s.trim();return n?me({text:c}):c},ge=({lines:e})=>e.filter((t,n)=>{let r=t.box.width*t.box.height;return!e.some((e,i)=>{if(i===n||!e.text.endsWith(t.text))return!1;let a=e.box.width*e.box.height;if(a<r||e.text.length===t.text.length&&a===r&&i>n)return!1;let o=Math.max(0,Math.min(t.box.x+t.box.width,e.box.x+e.box.width)-Math.max(t.box.x,e.box.x)),s=Math.max(0,Math.min(t.box.y+t.box.height,e.box.y+e.box.height)-Math.max(t.box.y,e.box.y));return r>0&&o*s>=r*.95})}),_e=async({adapter:e,model:t})=>{let[n,r,i]=await Promise.all([e.session(t.detection),e.session(t.recognition),e.load(t.dictionary)]),a=new TextDecoder().decode(i).replace(/\r/gu,``).split(`
5
+ `);for(;a.at(-1)===``;)a.pop();return{model:t.id,assets:[t.detection,t.recognition,t.dictionary],recognize:async({image:i})=>{let o=await e.decode(i),s=await fe({pixels:o,runtime:e.runtime,session:n}),c=[];for(let n of s){let i=pe({pixels:te({box:n,image:o}),runtime:e.runtime,model:t}),s=await se({session:r,tensor:i}),l;try{l=he({dictionary:a,output:s,reverse:t.reverseArabic})}finally{s.dispose()}if(!l)continue;let u={height:Math.max(0,Math.min(o.height,n.bottom)-Math.max(0,n.top)),width:Math.max(0,Math.min(o.width,n.right)-Math.max(0,n.left)),x:Math.max(0,n.left),y:Math.max(0,n.top)};c.push({angle:0,box:u,confidence:null,text:l,words:[{box:u,confidence:null,text:l}]})}let l=ge({lines:c}),u=ce({text:l.map(e=>e.text).join(`
6
+ `)});return{engine:t.id,height:o.height,lines:l,text:u,width:o.width}}}},F=`odm.ort`,ve={tiny:{id:`tiny`,detection:`od.ort`,recognition:`or.ort`,dictionary:`ot.txt`,recognitionHeight:48,channels:`grayscale`,reverseArabic:!1},small:{id:`small`,detection:`ods.ort`,recognition:`ors.ort`,dictionary:`ots.txt`,recognitionHeight:48,channels:`grayscale`,reverseArabic:!1},japanese:{id:`japanese`,detection:F,recognition:`orj.ort`,dictionary:`otj.txt`,recognitionHeight:48,channels:`bgr`,reverseArabic:!1},"chinese-simplified":{id:`chinese-simplified`,detection:F,recognition:`orcs.ort`,dictionary:`otcs.txt`,recognitionHeight:48,channels:`bgr`,reverseArabic:!1},"chinese-traditional":{id:`chinese-traditional`,detection:F,recognition:`orct.ort`,dictionary:`otct.txt`,recognitionHeight:48,channels:`bgr`,reverseArabic:!1},cyrillic:{id:`cyrillic`,detection:F,recognition:`orc.ort`,dictionary:`otc.txt`,recognitionHeight:48,channels:`bgr`,reverseArabic:!1},arabic:{id:`arabic`,detection:F,recognition:`ora.ort`,dictionary:`ota.txt`,recognitionHeight:48,channels:`bgr`,reverseArabic:!0}},ye={eng:`eng`,en:`eng`,english:`eng`,latin:`latin`,deu:`latin`,de:`latin`,fra:`latin`,fr:`latin`,ita:`latin`,it:`latin`,por:`latin`,pt:`latin`,spa:`latin`,es:`latin`,jpn:`jpn`,ja:`jpn`,japan:`jpn`,chi_sim:`chi_sim`,zh:`chi_sim`,"zh-cn":`chi_sim`,"zh-hans":`chi_sim`,chi_tra:`chi_tra`,ch:`chi_tra`,"zh-tw":`chi_tra`,"zh-hant":`chi_tra`,rus:`rus`,ru:`rus`,ara:`ara`,ar:`ara`},I=({language:e})=>{let t=ye[e.trim().toLowerCase()];if(!t)throw Error(P.OCR_LANGUAGE_UNSUPPORTED);return t},be={eng:`tiny`,latin:`tiny`,jpn:`japanese`,chi_sim:`chinese-simplified`,chi_tra:`chinese-traditional`,rus:`cyrillic`,ara:`arabic`},xe=({language:e,engine:t=`auto`})=>{let n=I({language:e}),r=ve[t===`auto`?be[n]:t];if(!r)throw Error(P.OCR_MODEL_UNSUPPORTED);return r},Se=({adapter:e,environment:t})=>{let n=new Map,r=async r=>{if(r.environment!==t)throw Error(P.OCR_ENVIRONMENT_MISMATCH);let i=xe(r),a=n.get(i.id);a||(a=_e({adapter:e,model:i}),n.set(i.id,a));try{return await a}catch(e){throw n.get(i.id)===a&&n.delete(i.id),e}};return{getOcr:r,ocr:async({image:e,language:n=`eng`,engine:i})=>await(await r({environment:t,language:n,engine:i})).recognize({image:e})}},Ce=async({cache:e,key:t,load:n})=>{let r=e.get(t);r||(r=n(),e.set(t,r));try{return await r}catch(n){throw e.get(t)===r&&e.delete(t),n}},we=new Map,{getOcr:Te,ocr:Ee}=Se({adapter:{decode:async t=>{if(!(t instanceof Blob)&&!(t instanceof Uint8Array))return t;let n=t instanceof Uint8Array?new Blob([t]):t,r=await E.createImageBitmap(n);try{return e({frame:r})}finally{r.close()}},load:async e=>await Ce({cache:we,key:e,load:async()=>{try{let t=await fetch(c({filename:e}));if(!t.ok)throw Error(P.MODEL_LOAD_FAILED);return new Uint8Array(await t.arrayBuffer())}catch(e){throw Error(P.MODEL_LOAD_FAILED,{cause:e})}}}),session:async e=>await d({filename:e}),runtime:f},environment:`browser`}),De=.24,Oe=.7,ke=.16,L=({data:e,height:t,text:n,width:r})=>{let i=new Uint8Array(r*t);for(let t=0;t<i.length;t+=1){let n=t*4;i[t]=Math.round((e[n]??0)*.299+(e[n+1]??0)*.587+(e[n+2]??0)*.114)}let a=[];for(let e=0;e<t;e+=1)for(let n=0;n<r;n+=1){let o=e*r+n,s=i[o]??0;n+1<r&&a.push(s>=(i[o+1]??0)),e+1<t&&a.push(s>=(i[o+r]??0))}let o=new Uint8Array(Math.ceil(a.length/8));for(let[e,t]of a.entries())t&&(o[Math.floor(e/8)]|=1<<e%8);let s=[];for(let e=0;e<8;e+=1)for(let n=0;n<8;n+=1){let a=0,o=0;for(let s=Math.floor(e*t/8);s<Math.floor((e+1)*t/8);s+=1)for(let e=Math.floor(n*r/8);e<Math.floor((n+1)*r/8);e+=1)a+=i[s*r+e]??0,o+=1;s.push(o?a/o:0)}let c=s.reduce((e,t)=>e+t,0)/s.length,l=new Uint8Array(Math.ceil(s.length/8));for(let[e,t]of s.entries())t>=c&&(l[Math.floor(e/8)]|=1<<e%8);return{edgeHash:o,appearanceHash:l,textTokens:[...new Set(n.toUpperCase().normalize(`NFKC`).split(/[^\p{L}\d]+/u).filter(e=>e.length>=3))]}},R=({value:e})=>{let t=0,n=e;for(;n;)t+=n&1,n>>>=1;return t},z=({front:e,current:t})=>{if(!e||!t||e.edgeHash.length!==t.edgeHash.length||e.appearanceHash.length!==t.appearanceHash.length)return{distinct:!1,imageDistance:null,textOverlap:null};let n=e.edgeHash.reduce((e,n,r)=>e+R({value:n^(t.edgeHash[r]??0)}),0)/(e.edgeHash.length*8),r=e.appearanceHash.reduce((e,n,r)=>e+R({value:n^(t.appearanceHash[r]??0)}),0)/(e.appearanceHash.length*8),i=t.textTokens.filter(t=>e.textTokens.includes(t)).length,a=Math.min(e.textTokens.length,t.textTokens.length),o=e.textTokens.length>=3&&t.textTokens.length>=3?i/a:null;return{distinct:n>=De&&r>=ke&&(o===null||o<Oe),imageDistance:n,textOverlap:o}},Ae=({text:e})=>{let t=e.toUpperCase().normalize(`NFKC`).split(`
7
+ `).map(e=>e.replace(/\s+/g,``)),n=t.findIndex(e=>e.startsWith(`P<`)&&e.length>=44&&(e.match(/</g)||[]).length>=2);if(n>=0&&t.slice(n+1).find(e=>/^[A-Z0-9<]{44}$/u.test(e)))return!0;let r=t.findIndex(e=>/^[A-Z0-9]<[A-Z]{3}/u.test(e)&&e.length>=30);return r<0?!1:t.slice(r+1).filter(e=>/^[A-Z0-9<]{30}$/u.test(e)).length>=2},je={A:`AUT`,B:`BEL`,BG:`BGR`,CY:`CYP`,CZ:`CZE`,D:`DEU`,DK:`DNK`,E:`ESP`,EST:`EST`,F:`FRA`,FIN:`FIN`,GR:`GRC`,H:`HUN`,HR:`HRV`,I:`ITA`,IRL:`IRL`,L:`LUX`,LT:`LTU`,LV:`LVA`,M:`MLT`,NL:`NLD`,P:`PRT`,PL:`POL`,RO:`ROU`,S:`SWE`,SK:`SVK`,SLO:`SVN`},B=({line:e,start:t,end:n})=>{let r=[],i=0;for(let a of e.words){let o=e.text.indexOf(a.text,i);if(o<0||!a.text.length)continue;i=o+a.text.length;let s=Math.max(t,o),c=Math.min(n,i);c<=s||r.push({...a.box,x:a.box.x+a.box.width*(s-o)/a.text.length,width:a.box.width*(c-s)/a.text.length})}if(!r.length)return{...e.box,x:e.box.x+e.box.width*t/e.text.length,width:e.box.width*(n-t)/e.text.length};let a=Math.min(...r.map(e=>e.x)),o=Math.min(...r.map(e=>e.y));return{x:a,y:o,width:Math.max(...r.map(e=>e.x+e.width))-a,height:Math.max(...r.map(e=>e.y+e.height))-o}},Me=({line:e})=>{let t=e.text;if(!t.trim()||e.confidence!==null&&e.confidence<=0)return[];if(/^\s*\d{1,2}[./-]\d{1,2}[./-]\d{2,4}\s*$/u.test(t))return[{text:t.trim(),box:e.box,label:null}];let n=[...t.matchAll(/(?:^|\s)(4[a-d]|1[0-4]|[1-9])(?:[.:)]\s*|\s+|$|(?=\d{1,2}[./-]\d))/giu)];if(!n.length)return[{text:t,box:e.box,label:null}];let r=[],i=n[0].index;i>0&&r.push({text:t.slice(0,i).trim(),box:B({line:e,start:0,end:i}),label:null});for(let[i,a]of n.entries()){let o=a.index+a[0].indexOf(a[1]),s=n[i+1]?.index??t.length,c=t.slice(a.index+a[0].length,s).trim(),l=B({line:e,start:o,end:s});r.push({text:c,box:l,label:a[1].toLowerCase()})}return r},V=({label:e,fragments:t})=>{let n=t.filter(t=>t.label===e);if(n.length!==1)return null;let r=n[0],i=r.box.height,a=r.text?[r]:[],o=t.filter(e=>e.label&&e!==r);for(let e of t){if(e.label||!e.text)continue;let t=e.box.y-r.box.y,n=Math.abs(t)<Math.max(i,e.box.height)*.5,s=t>=i*.5&&t<=i*2.5;(n||s)&&(e.box.x<r.box.x-i*.5||n&&r.text||o.some(t=>{let n=Math.abs(t.box.y-r.box.y)<i*.5&&t.box.x>r.box.x&&e.box.x>=t.box.x-i*.25,a=t.box.y>r.box.y+i*.5&&t.box.y<=e.box.y+e.box.height*.5&&Math.abs(t.box.x-r.box.x)<i*3;return n||a})||o.some(n=>{let a=e.box.y-n.box.y,o=a>=-i*.5&&a<=i*2.5&&e.box.x>=n.box.x-i*.5,s=Math.abs(t)+Math.abs(e.box.x-r.box.x),c=Math.abs(a)+Math.abs(e.box.x-n.box.x);return o&&c<=s})||a.push(e))}return a.sort((e,t)=>Math.abs(e.box.y-t.box.y)<i*.5?e.box.x-t.box.x:e.box.y-t.box.y),a.map(e=>e.text).join(` `).trim()||null},H=({text:e,allowTwoDigitYear:t=!1})=>{if(!e)return null;let n=e.match(/^(?:(\d{1,2})([./-])(\d{1,2})\2(\d{2,4})|(\d{4})-(\d{2})-(\d{2}))$/u);if(!n)return null;let r=n[4]??n[5],i=Number(n[3]??n[6]),a=Number(n[1]??n[7]),o=Number(r);if(r.length===2){if(!t)return null;let e=new Date,n=e.getUTCFullYear(),r=e.getUTCMonth()+1,s=e.getUTCDate(),c=[1900+o,2e3+o].filter(e=>{let t=n-e-+(r<i||r===i&&s<a);return t>=16&&t<=100});if(c.length!==1)return null;o=c[0]}return o<1e3||i<1||i>12||a<1||a>new Date(Date.UTC(o,i,0)).getUTCDate()?null:`${o}-${String(i).padStart(2,`0`)}-${String(a).padStart(2,`0`)}`},Ne=({ocr:e,image:t})=>{let n=new Set;for(let i of e.lines)for(let e of i.words.length?i.words:[i]){let i=je[e.text.trim().toUpperCase()],{x:a,y:o,width:s,height:c}=e.box;if(e.confidence!==null&&e.confidence<=0||!i||a<0||o<0||a+s>t.width*.3||o+c>t.height*.35)continue;let l=Math.max(s,c);r({...t,xStart:Math.max(0,a-l)/t.width,xEnd:Math.min(t.width,a+s+l)/t.width,yStart:Math.max(0,o-l)/t.height,yEnd:Math.min(t.height,o+c+l)/t.height,predicate:(e,t,n)=>n>45&&n>e*1.08&&n>t*1.04})>=.15&&n.add(i)}return n.size===1?[...n][0]:null},U=({ocr:e,image:t})=>{if(u(e))return null;let n=e.lines.flatMap(e=>Me({line:e})),r=new Set(n.map(e=>e.label));if(!(r.has(`1`)||r.has(`2`))||![`3`,`4a`,`4b`,`5`].some(e=>r.has(e)))return null;let i=V({label:`1`,fragments:n}),a=V({label:`2`,fragments:n}),o=i&&/\p{L}/u.test(i)?i:null,s=a&&/\p{L}/u.test(a)?a:null,c=V({label:`3`,fragments:n})?.match(/^(\d{1,2}[./-]\d{1,2}[./-]\d{2,4}|\d{4}-\d{2}-\d{2})(?:\s+(.+))?$/u),l=H({allowTwoDigitYear:!0,text:c?c[1]:null}),d=c&&c[2]?.trim()||null,f=H({text:V({label:`4a`,fragments:n})}),p=H({text:V({label:`4b`,fragments:n})}),m=V({label:`4c`,fragments:n}),h=V({label:`5`,fragments:n}),g=Ne({ocr:e,image:t});return[o,s,l,d,f,p,m,h,g].some(Boolean)?ee.parse({document:{source:`OCR`,type:`DRV`,issuing_country:g,issuing_authority:m,number:h,issue_date:f,expiry_date:p,optional_data:null},holder:{first_name:s,last_name:o,middle_name:null,birth_date:l,birth_place:d,sex:null,nationality:null,personal_number:null},address:null,raw_data:{mrz_lines:[],aamva_version:null}}):null},W=null,Pe=()=>globalThis.window===void 0?`zxing-wasm/reader`:c({filename:`zxing-wasm/reader/index.js`}),Fe=async()=>{let e=await import(Pe());return globalThis.window!==void 0&&e.setZXingModuleOverrides({locateFile:e=>c({filename:`zxing-wasm/reader/${e}`})}),e},Ie=async()=>{W??=Fe();try{return await W}catch(e){throw W=null,e}},Le=async()=>{await(await Ie()).prepareZXingModule({fireImmediately:!0})},Re=async({image:e})=>{let t=await(await Ie()).readBarcodes(e,{formats:[`PDF417`],tryHarder:!0});for(let e of t)try{let t=y(e.text);return{type:`aamva`,code:e.text,payload:t}}catch{}return null},ze=({runtime:e,detector:t,alignment:n,text:r,readImage:a})=>{let o=async({image:i,language:o,engine:s,scanBarcodes:c=!1})=>{let l=i instanceof Blob?i:new Blob([i]),u=await e.createImageBitmap(l);try{let i=await t.analyzeDocument({frame:u});if(!i.detection)throw Error(P.DOCUMENT_NOT_FOUND);let l=await n.orientDocumentFrame({frame:u,polygon:i.detection.polygon,orientation:i.detection.orientation});if(!l)throw Error(P.IMAGE_PROCESSING_FAILED);try{let t=m({image:a({frame:u}),polygon:i.detection.polygon,sourceOrientation:l.orientation.rotation}),n=await r.readRectifiedText({frame:l.frame,language:o,engine:s,image:t});if(!n)throw Error(P.DOCUMENT_TEXT_NOT_READABLE);let d=a({frame:l.frame}),f=null;if(c){let t=e.createImageData(d.width,d.height);t.data.set(d.data),f=await Re({image:t})}return{ocr:n,codes:[N({result:n}),f].filter(e=>e!==null),pixels:d,signature:L({...a({frame:l.frame,width:32,height:32}),text:n.text}),blurry:i.isBlurry}}finally{l.frame.close()}}finally{u.close()}};return{classifyDocument:async({document_front:e,document_back:t,language:n,engine:r})=>{let a=await o({image:e,language:n,engine:r}),s=i({image:a.pixels,text:a.ocr.text,codes:a.codes});if(!s)throw Error(P.DOCUMENT_NOT_RECOGNIZED);let c=s.europeanDrivingLicense?U({ocr:a.ocr,image:a.pixels}):null,l=p({document:s.document})&&t?await o({image:t,language:s.europeanDrivingLicense?`latin`:n,engine:s.europeanDrivingLicense?`tiny`:r,scanBarcodes:!0}):null,u=M({classification:{...s,identity:c},front:a,back:l}),d=[...u.reasons],f=l?l.blurry:!1;return(a.blurry||f)&&d.push(P.DOCUMENT_BLURRY),l&&!z({front:a.signature,current:l.signature}).distinct&&d.push(P.DOCUMENT_BACK_NOT_DISTINCT),{identity:c,...s,...u,reasons:d,valid:d.length===0,document_front:a.ocr,document_back:l?l.ocr:null}},detectDocument:async({image:e,language:t})=>{let n=await o({image:e,language:t,scanBarcodes:!0}),r=i({image:n.pixels,text:n.ocr.text,codes:n.codes});if(!r)throw Error(P.DOCUMENT_NOT_RECOGNIZED);let a=n.codes.find(e=>e.type===`mrz`),s=n.codes.find(e=>e.type===`aamva`),c=!!s||r.document===`id`&&!!a;return{identity:!c&&r.europeanDrivingLicense?U({ocr:n.ocr,image:n.pixels}):null,document_type:r.document===`driving_license`?`drv`:r.document,document_side:c?`back`:`front`,mrz_code:a?a.code:null,ammva_code:s?s.code:null}},extractDocumentCodes:async({images:e})=>{let t=[];for(let n of e){let e=await o({image:n,scanBarcodes:!0});t.push(...e.codes)}return[...new Map(t.map(e=>[`${e.type}:${e.code}`,e])).values()]}}},G=8,Be=.16,Ve=({x:e,y:t,width:n,height:r})=>{let i=e/n,a=t/r;return i<.2||i>=.8||a<.2||a>=.8},He=({value:e})=>{let t=0,n=e;for(;n;)t+=n&1,n>>>=1;return t},Ue=({image:e})=>{let t=[];for(let n=0;n<G;n+=1)for(let r=0;r<G;r+=1){let i=0,a=0,o=Math.floor(n*e.height/G),s=Math.floor((n+1)*e.height/G),c=Math.floor(r*e.width/G),l=Math.floor((r+1)*e.width/G);for(let t=o;t<s;t+=1)for(let n=c;n<l;n+=1){if(!Ve({height:e.height,width:e.width,x:n,y:t}))continue;let r=(t*e.width+n)*4;i+=(e.data[r]??0)*.299+(e.data[r+1]??0)*.587+(e.data[r+2]??0)*.114,a+=1}t.push(a?i/a:0)}let n=t.reduce((e,t)=>e+t,0)/t.length,r=new Uint8Array(Math.ceil(t.length/8));for(let[e,i]of t.entries())i>=n&&(r[Math.floor(e/8)]|=1<<e%8);return{appearanceHash:r}},We=({first:e,second:t})=>{if(e.appearanceHash.length!==t.appearanceHash.length)return{distance:1,matched:!1};let n=e.appearanceHash.reduce((e,n,r)=>e+He({value:n^(t.appearanceHash[r]??0)}),0)/(e.appearanceHash.length*8);return{distance:n,matched:n<=Be}},Ge=({candidate:e,identity:t})=>[{missing:!t?.holder.last_name,pattern:/^\s*1[.:)]\s+\p{L}/u},{missing:!t?.holder.first_name,pattern:/^\s*2[.:)]\s+\p{L}/u},{missing:!t?.holder.birth_date,pattern:/^\s*3[.:)]\s+\d{1,2}[./-]\d{1,2}[./-]\d{2,4}/u},{missing:!t?.document.number,pattern:/^\s*5[.:)]\s+[A-Z0-9]/u}].flatMap(({missing:t,pattern:n})=>{if(!t)return[];let r=e.lines.find(e=>n.test(e.text));return r?[r]:[]}),Ke=({runtime:e,orientDocumentFrame:t,getOcr:r})=>{let a=`auto`,o=T({runtime:e}),s=async({engine:t=a,language:n=`eng`}={})=>{await r({environment:e.environment,engine:t,language:n})},c=async({classificationImage:t,engine:s=a,frame:c,language:l,image:u})=>{if(c.width<200||c.height<100)return null;let d=u??m({image:o({frame:c}),polygon:[{x:0,y:0},{x:c.width,y:0},{x:c.width,y:c.height},{x:0,y:c.height}]}),f=await(await r({environment:e.environment,engine:`tiny`,language:`latin`})).recognize({image:d}),p=N({result:f}),h=t??o({frame:c}),g=i({image:h,text:f.text,codes:p?[p]:[]}),_=g&&(g.document===`passport`||g.europeanDrivingLicense);if(g?.europeanDrivingLicense){let t=U({ocr:f,image:h});if(!n({identity:t})){let a=await(await r({environment:e.environment,engine:`small`,language:`latin`})).recognize({image:d}),o=U({ocr:a,image:h}),s=i({image:h,text:a.text,codes:[]});if(s?.europeanDrivingLicense&&n({identity:o}))f=a;else if(s?.europeanDrivingLicense){let e=Ge({candidate:a,identity:t});if(e.length){let t=[...f.lines,...e];f={...f,lines:t,text:t.map(e=>e.text).join(`
8
+ `)}}}}}else if(!_){let t=I({language:l??`eng`}),n=await r({environment:e.environment,engine:s,language:t});n.model!==`tiny`&&(f=await n.recognize({image:d}))}let v=c.width/f.width,y=c.height/f.height,b=({x:e,y:t,width:n,height:r})=>({x:e*v,y:t*y,width:n*v,height:r*y});return{...f,width:c.width,height:c.height,lines:f.lines.map(e=>({...e,box:b(e.box),words:e.words.map(e=>({...e,box:b(e.box)}))}))}},l=async e=>await c(e)??{height:e.frame.height,lines:[],text:``,width:e.frame.width};return{loadTextDetector:s,readRectifiedText:c,detectRectifiedText:l,detectDocumentText:async({engine:e=a,frame:n,language:r,polygon:i})=>{let o=await t({frame:n,polygon:i});if(!o)return{height:0,lines:[],rotation:0,text:``,width:0};try{return{...await l({engine:e,frame:o.frame,language:r}),rotation:o.orientation.rotation}}finally{o.frame.close()}}}},qe=({runtime:e,documentAlignment:t,rectifiedDocumentFace:r,orientDocumentFrame:o,restoreRectifiedFace:c,analyzeDocument:u,faceDetection:d,faceMatch:f,textDetection:p})=>{let h=T({runtime:e}),g=({frame:t,text:n})=>{let r=e.createCanvas(32,32),i=r.getContext(`2d`,{willReadFrequently:!0});if(!i)throw Error(P.IMAGE_PROCESSING_FAILED);i.drawImage(t,0,0,r.width,r.height);let{data:a}=i.getImageData(0,0,r.width,r.height);return l({canvas:r}),L({data:a,height:32,text:n,width:32})},_=({current:e,front:t})=>{let n=z({current:e.signature,front:t}),r=[],i=e.signature?.textTokens.length??0,a=Ae({text:e.text.text})||e.text.lines.length>=2&&i>=2;return e.detection||r.push(P.DOCUMENT_NOT_FOUND),e.documentAnalysis.isBlurry&&r.push(P.DOCUMENT_BLURRY),e.hasPictureFace&&r.push(P.DOCUMENT_BACK_CONTAINS_FACE),a||r.push(P.DOCUMENT_TEXT_NOT_READABLE),n.distinct||r.push(P.DOCUMENT_BACK_NOT_DISTINCT),{distinct:n.distinct,imageDistance:n.imageDistance,reasons:r,textOverlap:n.textOverlap,valid:r.length===0}},v=({alignment:e,detection:t,documentAnalysis:n,faceContained:r,requiresFace:i,text:a})=>{let o=[];return t||o.push(P.DOCUMENT_NOT_FOUND),n.isBlurry&&o.push(P.DOCUMENT_BLURRY),i&&!r&&o.push(P.DOCUMENT_FACE_NOT_CONTAINED),(!a.text||a.lines.length<2)&&o.push(P.DOCUMENT_TEXT_NOT_READABLE),!i||e.faceAreaValid&&e.faceDimensionsValid||o.push(P.DOCUMENT_FACE_GEOMETRY_INVALID),i&&(e.faceAdjacentTextLineCount<2||!e.textParallel||e.textSide!==`right`)&&o.push(P.DOCUMENT_TEXT_ALIGNMENT_INVALID),o},y=async({classification:e,codes:i,ocr:a,options:o,documentAnalysis:s,document:l,text:u,prepareForMatch:p})=>{let m=s.detection,h=o.requiresFace??!0,_={boundingRect:{height:l.height,width:l.width,x:0,y:0},polygon:[{x:0,y:0},{x:l.width,y:0},{x:l.width,y:l.height},{x:0,y:l.height}]},y=h?await d.detectDocumentFaces({detection:_,frame:l.frame}):{faces:[],pictureFaces:[],hasPictureFace:await d.detectDocumentFacePresence({detection:_,frame:l.frame})},b=y.pictureFaces.map(e=>c({document:l,face:e})),x=g({frame:l.frame,text:u.text}),S=i.find(e=>e.type===`mrz`)??null,C=null;for(let g of y.faces.length?y.faces:[null]){let _=g?c({document:l,face:g}):null,w=g?r({face:g}):null,T=h&&m?d.faceIsInsideDocument({detection:m,face:_})&&b.every(e=>d.faceIsInsideDocument({detection:m,face:e})):!1,E=t({documentSize:{height:u.height,width:u.width},face:w,lines:u.lines,maxAngleDifference:o.maxDocumentTextAngleDifference,maxFaceAreaRatio:o.maxDocumentFaceAreaRatio,maxFaceHeightRatio:o.maxDocumentFaceHeightRatio,maxFaceWidthRatio:o.maxDocumentFaceWidthRatio,minFaceAreaRatio:o.minDocumentFaceAreaRatio,minFaceHeightRatio:o.minDocumentFaceHeightRatio,minFaceWidthRatio:o.minDocumentFaceWidthRatio}),D=v({alignment:E,detection:m,documentAnalysis:s,faceContained:T,requiresFace:h,text:u});h&&!e&&D.push(P.DOCUMENT_NOT_RECOGNIZED),e?.europeanDrivingLicense&&!n({identity:e.identity})&&D.push(P.DOCUMENT_VALIDATION_FAILED);let O=D.length===0,k=null,A=null;if(h&&O&&g){let e=f.prepareFace({alignment:o.alignment??`eyes-nose-mouth`,face:g,frame:l.frame});if(!e)O=!1,D.push(P.FACE_NOT_USABLE);else if(p){let t=await f.preparedFaceArtifacts({face:e});k=t?.embeddings??null,A=t?.images??null,t||(O=!1,D.push(P.INVALID_MODEL_OUTPUT))}}let j={identity:e?e.identity:null,orientation:l.orientation,ocr:a,mrz:S,alignment:E,detection:m,documentAnalysis:s,documentKind:e?e.document:null,europeanDrivingLicense:e?e.europeanDrivingLicense:!1,codes:i,documentToSource:l.toSource,embeddings:k,images:A,face:_,faceContained:T,hasPictureFace:y.hasPictureFace??b.length>0,failureReasons:D,pictureFaces:b,signature:x,text:u,valid:O};if(j.valid)return j;C??=j}if(!C)throw Error(P.INTERNAL_ERROR);return C},b=async({frame:n,options:r,documentAnalysis:c,prepareForMatch:l=!1})=>{let u=c.detection;if(!u){let e={height:0,lines:[],text:``,width:0},n=t({documentSize:{height:e.height,width:e.width},face:null,lines:e.lines,maxAngleDifference:r.maxDocumentTextAngleDifference,maxFaceAreaRatio:r.maxDocumentFaceAreaRatio,maxFaceHeightRatio:r.maxDocumentFaceHeightRatio,maxFaceWidthRatio:r.maxDocumentFaceWidthRatio,minFaceAreaRatio:r.minDocumentFaceAreaRatio,minFaceHeightRatio:r.minDocumentFaceHeightRatio,minFaceWidthRatio:r.minDocumentFaceWidthRatio});return{identity:null,orientation:null,ocr:null,mrz:null,codes:[],europeanDrivingLicense:!1,alignment:n,detection:u,documentAnalysis:c,documentKind:null,documentToSource:null,embeddings:null,face:null,faceContained:!1,failureReasons:v({alignment:n,detection:u,documentAnalysis:c,faceContained:!1,requiresFace:r.requiresFace??!0,text:e}),images:null,pictureFaces:[],hasPictureFace:!1,signature:null,text:e,valid:!1}}let d=await o({frame:n,polygon:u.polygon,orientation:u.orientation});if(!d)throw Error(P.IMAGE_PROCESSING_FAILED);try{let t=performance.now(),o=m({image:h({frame:n}),polygon:u.polygon,sourceOrientation:d.orientation.rotation}),f=r.requiresFace===!1?`back`:`front`;s({category:`stages`,key:`ocr.prepare.${f}`,duration:performance.now()-t});let g=h({frame:d.frame}),_=await p.readRectifiedText({classificationImage:g,engine:r.ocrEngine,frame:d.frame,language:r.language,image:o}),v=_??{height:d.height,lines:[],text:``,width:d.width},b=_?N({result:_}):null,x=null;if(r.requiresFace===!1){let t=e.createImageData(g.width,g.height);t.data.set(g.data),x=await a({key:`barcode.back`,operation:()=>Re({image:t})})}let S=[b,x].filter(e=>e!==null),C=i({image:g,text:v.text,codes:S}),w=r.requiresFace!==!1&&C?.europeanDrivingLicense&&_?U({ocr:_,image:g}):null,T=C?{...C,identity:w}:null;return await y({ocr:_,classification:T,codes:S,options:r,documentAnalysis:c,document:d,prepareForMatch:l,text:v})}finally{d.frame.close()}},x=async({frame:e,options:t,prepareForMatch:n=!1})=>{let r=await u({frame:e,minDocumentBoxRatio:t.minDocumentBoxRatio});return await b({frame:e,options:t,documentAnalysis:r,prepareForMatch:n})},S=({analysis:e,isBack:t,front:n})=>{if(!e.ocr)return[P.DOCUMENT_TEXT_NOT_READABLE];if(t&&!n)return[P.CAPTURES_INCOMPLETE];if(!t&&!e.documentKind)return[P.DOCUMENT_NOT_RECOGNIZED];let r={ocr:e.ocr,codes:e.codes},i=t&&n?n:{document:e.documentKind,europeanDrivingLicense:e.europeanDrivingLicense,identity:e.identity};return M({classification:i,front:t&&n?n:r,back:t?r:null}).reasons.filter(e=>t||e!==P.DOCUMENT_BACK_REQUIRED)};return{validateDocumentBack:_,analyzeDocumentFrame:x,hasValidDocumentSideData:e=>S(e).length===0,documentSideFailureReasons:S}},Je=({runtime:e,document:t,readImage:n})=>async({image:r,timings:i})=>{let a=await e.createImageBitmap(new Blob([r]));try{let r=performance.now(),o=await t.analyzeDocument({frame:a});if(i&&(i.documentBoxDetectionMs=performance.now()-r),!o.detection)throw Error(P.DOCUMENT_NOT_FOUND);let{polygon:s,orientation:c}=o.detection,u=m({image:n({frame:a}),polygon:s,sourceOrientation:c?.rotation}),d=e.createCanvas(u.width,u.height);try{let t=d.getContext(`2d`);if(!t)throw Error(P.IMAGE_PROCESSING_FAILED);let n=e.createImageData(u.width,u.height);n.data.set(u.data),t.putImageData(n,0,0);let r=await d.convertToBlob({type:`image/png`});return new Uint8Array(await r.arrayBuffer())}finally{l({canvas:d})}}finally{a.close()}},{alignment:Ye,document:K,face:q,text:Xe,match:J,flow:Ze,classify:Qe,prepareOcrImage:$e,warmup:et}=(({runtime:e,getOcr:t})=>{let n=T({runtime:e}),r=O({runtime:e}),i=C({runtime:e}),a=A({runtime:e,imageFromImageBitmap:n}),o=Ke({runtime:e,getOcr:t,...r}),s=j({runtime:e,...r,...i,...a,faceDetection:a});return{alignment:r,document:i,face:a,text:o,match:s,flow:qe({runtime:e,...r,...i,faceDetection:a,faceMatch:s,textDetection:o}),classify:ze({runtime:e,detector:i,alignment:r,text:o,readImage:n}),prepareOcrImage:Je({runtime:e,document:i,readImage:n}),warmup:async()=>{await Promise.all([a.loadFaceDetector({faceDetector:`standard`}),s.loadFaceMatch(),i.loadDocumentBoxDetector(),i.loadDocumentOrientationDetector(),o.loadTextDetector({engine:`tiny`,language:`latin`}),Le()])}}})({runtime:E,getOcr:Te}),{classifyDocument:tt,detectDocument:nt,extractDocumentCodes:rt}=Qe,{detectDocumentOrientation:it,loadDocumentOrientationDetector:at}=K,ot=[`faceStraight`,`faceUp`,`faceDown`,`faceLeft`,`faceRight`],Y=[`faceStraight`,`faceUp`,`faceLeft`,`faceRight`],X=[...ot,`faceSmile`,`faceWinkLeft`,`faceTiltLeft`,`faceTiltRight`];g(X);var Z={faceStraight:`face_straight`,faceUp:`face_up`,faceDown:`face_down`,faceLeft:`face_left`,faceRight:`face_right`,faceSmile:`face_smile`,faceWinkLeft:`face_wink_left`,faceTiltLeft:`face_tilt_left`,faceTiltRight:`face_tilt_right`};g(Z),ot.map(e=>Z[e]),Y.map(e=>Z[e]);var st=async()=>{let e=await fetch(S({filename:`faceMeshLines.json`}));if(!e.ok)throw Error(b.INVALID_SERVICE_RESPONSE);return await e.json()},ct=async()=>{await st()},{transformPoint:lt}=Ye,ut=[`tessellation`,`contours`,`faceOval`,`lips`,`leftEye`,`rightEye`,`leftEyebrow`,`rightEyebrow`,`leftIris`,`rightIris`],dt=async({color:e,context:t,result:n})=>{let r=await st();t.beginPath();for(let e of ut)for(let{start:i,end:a}of r[e]){let e=n.mesh.landmarks[i],r=n.mesh.landmarks[a];e&&r&&(t.moveTo(e.x,e.y),t.lineTo(r.x,r.y))}t.strokeStyle=e,t.lineWidth=1,t.stroke()},ft=({color:e,context:t,line:n,toSource:r})=>{if(!n.text)return;let{x:i,y:a,width:o,height:s}=n.box,c=[{x:i,y:a},{x:i+o,y:a},{x:i+o,y:a+s},{x:i,y:a+s}].map(e=>lt({homography:r,point:e})),l=c[0],u=c[1],d=c[3];if(!l||!u||!d)return;let f=Math.hypot(u.x-l.x,u.y-l.y),p=Math.hypot(d.x-l.x,d.y-l.y),m=Math.max(8,Math.min(16,p*.7)),h=Math.max(0,f-4),g=Math.atan2(u.y-l.y,u.x-l.x);t.beginPath(),t.moveTo(l.x,l.y);for(let e of c.slice(1))t.lineTo(e.x,e.y);t.closePath(),t.strokeStyle=e,t.lineWidth=1,t.stroke(),t.save(),t.clip(),t.translate(l.x+2,l.y+2),t.rotate(g),t.font=`${m}px sans-serif`,t.textBaseline=`top`,t.lineWidth=3,t.strokeStyle=`#020617`,t.strokeText(n.text,0,0,h),t.fillStyle=e,t.fillText(n.text,0,0,h),t.restore()},pt=async({element:e,meshLineColor:t,overlayColor:n=`transparent`,result:r})=>{let i=e.getContext(`2d`);if(!i)throw Error(b.IMAGE_PROCESSING_FAILED);let a=r?.mesh.width??e.width,o=r?.mesh.height??e.height;e.width!==a&&(e.width=a),e.height!==o&&(e.height=o),h({element:e}),n!==`transparent`&&(i.fillStyle=n,i.fillRect(0,0,a,o)),r&&await dt({color:t,context:i,result:r})},mt=async({documentFaceBoxColor:e,documentFaceMeshColor:t,documentBoxColor:n,element:r,detection:i,face:a,height:o,ocrLines:s=[],ocrToSource:c=null,overlayColor:l=`transparent`,textColor:u,width:d})=>{let f=r.getContext(`2d`);if(f&&d&&o){if(r.width!==d&&(r.width=d),r.height!==o&&(r.height=o),h({element:r}),l!==`transparent`&&(f.fillStyle=l,f.fillRect(0,0,d,o)),i){f.strokeStyle=n,f.lineWidth=3,f.beginPath();for(let[e,t]of i.polygon.entries())e?f.lineTo(t.x,t.y):f.moveTo(t.x,t.y);f.closePath(),f.stroke()}if(a&&(f.strokeStyle=e,f.lineWidth=2,f.strokeRect(a.boundingRect.x,a.boundingRect.y,a.boundingRect.width,a.boundingRect.height),await dt({color:t,context:f,result:a})),c)for(let e of s)ft({color:u,context:f,line:e,toSource:c})}},{detectPictureFaces:ht}=q,Q=({face:e,name:t})=>e.blendshapes[t]??0,gt=({face:e,frame:t})=>e.boundingRect.height/t.height<.4?`FACE_TOO_SMALL`:null,_t=({face:e,pose:t})=>{if(t===`faceSmile`)return Q({face:e,name:`mouthSmileLeft`})>=.5&&Q({face:e,name:`mouthSmileRight`})>=.5;if(t===`faceWinkLeft`)return x({blendshapes:e.blendshapes,pose:t});throw Error(b.INVALID_POSES)},vt=({face:e,pose:t,options:n})=>{let r=D[t],i=r?.roll,a=r?.yaw,o=r?.pitch;return i===void 0&&e.roll<-n.maxRoll?`FACE_ROLL_TILT_LEFT`:i===void 0&&e.roll>n.maxRoll?`FACE_ROLL_TILT_RIGHT`:a===void 0&&e.yaw<n.minYaw?`FACE_YAW_TURN_LEFT`:a===void 0&&e.yaw>n.maxYaw?`FACE_YAW_TURN_RIGHT`:o===void 0&&e.pitch<n.minPitch?`FACE_PITCH_LOOK_DOWN`:o===void 0&&e.pitch>n.maxPitch?`FACE_PITCH_LOOK_UP`:i!==void 0&&e.roll<i-5?i<0?`FACE_ROLL_TILT_LESS`:`FACE_ROLL_TILT_LEFT`:i!==void 0&&e.roll>i+5?i<0?`FACE_ROLL_TILT_RIGHT`:`FACE_ROLL_TILT_LESS`:a!==void 0&&e.yaw<a-5?a<0?`FACE_YAW_TURN_LESS`:`FACE_YAW_TURN_LEFT`:a!==void 0&&e.yaw>a+5?a<0?`FACE_YAW_TURN_RIGHT`:`FACE_YAW_TURN_LESS`:o!==void 0&&e.pitch<o-5?o<0?`FACE_PITCH_RAISE_LESS`:`FACE_PITCH_LOOK_DOWN`:o!==void 0&&e.pitch>o+5?o<0?`FACE_PITCH_LOOK_UP`:`FACE_PITCH_LOWER_LESS`:t===`faceSmile`&&!_t({face:e,pose:t})?`FACE_SMILE_REQUIRED`:t===`faceWinkLeft`&&!_t({face:e,pose:t})?`FACE_WINK_LEFT_REQUIRED`:null},yt=({face:e,pose:t,options:n})=>vt({face:e,pose:t,options:n})===null,bt=async({capture:e,pose:t,options:n,poseOptions:r})=>{let i=await J.imageBitmap({blob:e});try{let e=await ht(i),a=e.length===1?e[0]:null;if(!a||!yt({face:a,pose:t,options:r}))return null;let o=J.prepareFace({alignment:n.alignment,face:a,frame:i});return o?await J.preparedFaceArtifacts({face:o}):null}finally{i.close()}},{detectDocumentBox:xt}=K,{detectFace:St}=q,Ct=({view:e,display:t,isActive:n,notifyCapturesChanged:r})=>{let i=e.ref,a=({state:e})=>e.faceSequence[e.poseIndex]??`faceStraight`,s=({face:e,frame:n})=>{let r=e.boundingRect.x+e.boundingRect.width/2,i=e.boundingRect.y+e.boundingRect.height/2,a=(t.cameraFacingMode.value===`user`?n.width-r:r)/n.width,o=i/n.height;return a<.4?`FACE_CENTER_MOVE_RIGHT`:a>.6?`FACE_CENTER_MOVE_LEFT`:o<.4?`FACE_CENTER_MOVE_DOWN`:o>.6?`FACE_CENTER_MOVE_UP`:null},c=async({frame:c,session:l,state:u,options:d})=>{let f=performance.now(),p=null,m=!1;try{p=await St(c);let e=p?await xt(c):null;if(m=!!(p&&e&&v({face:p,polygon:e.polygon})),!n({flow:`face`,session:l,state:u}))return!1;if(d.showFaceOverlay&&await pt({element:i.mesh,meshLineColor:d.faceMeshColor,overlayColor:d.faceOverlayColor,result:p}),!p){u.poseStableFrames=0;let e=a({state:u});return t.feedback.value={flow:`face`,code:`FACE_NOT_DETECTED`,pose:e},!1}if(m)return u.poseStableFrames=0,t.feedback.value={flow:`face`,code:`FACE_IN_POLYGON`,pose:a({state:u})},!1;let f=a({state:u}),h=gt({face:p,frame:c});if(h)return u.poseStableFrames=0,t.feedback.value={flow:`face`,code:h,pose:f},!1;let g=s({face:p,frame:c});if(g)return u.poseStableFrames=0,t.feedback.value={flow:`face`,code:g,pose:f},!1;let _=vt({face:p,pose:f,options:d});if(_)return u.poseStableFrames=0,t.feedback.value={flow:`face`,code:_,pose:f},!1;if(u.poseStableFrames+=1,u.poseStableFrames<d.requiredFaceStableFrames)return t.feedback.value={flow:`face`,code:`FACE_STABILITY_REQUIRED`,pose:f},!1;t.feedback.value={flow:`face`,code:null,pose:f};let y=await o({frame:c}),x=await bt({capture:y,pose:f,options:u.matchOptions,poseOptions:d});if(!n({flow:`face`,session:l,state:u}))return!1;if(!x)return u.poseStableFrames=0,!1;let S=Ue({image:J.readImage({frame:c,width:32,height:32})}),C=u.previousPoseBackgroundSignature;if(C&&!We({first:C,second:S}).matched)throw Error(b.POSE_BACKGROUND_MISMATCH);let w=u.faceEmbeddings.faceStraight;if(w&&k({first:w,second:x.embeddings})<=u.matchOptions.threshold)throw Error(b.POSE_IDENTITY_MISMATCH);let T=f;return u.captures[T]=y,u.preparedCaptures[T]=x.images,u.faceEmbeddings[T]=x.embeddings,u.previousPoseBackgroundSignature=S,r({state:u}),u.poseIndex+=1,u.poseStableFrames=0,u.poseIndex===u.faceSequence.length?(t.feedback.value=null,!0):(t.feedback.value={flow:`face`,pose:a({state:u}),code:null},!1)}finally{n({flow:`face`,session:l,state:u})&&e.collectFaceDebug({face:p,faceInPolygon:m,processingTimeMilliseconds:performance.now()-f,state:u}),c.close()}};return{runFaceLoop:async({session:e,state:r,options:a})=>{for(;n({flow:`face`,session:e,state:r});){if(await _({video:i.video}),!n({flow:`face`,session:e,state:r}))return;let o=await createImageBitmap(i.video);if(await c({frame:o,session:e,state:r,options:a})){r.flow=null,t.debug.value=[];return}}}}},$=({captures:e,state:t})=>t.faceSequence.every(n=>!!(e[n]&&t.preparedCaptures[n]&&t.faceEmbeddings[n])),wt=({captures:e,state:t})=>{if(!$({captures:e,state:t}))throw Error(b.CAPTURES_INCOMPLETE);let n=[...t.faceSequence];return{faces:n.map(t=>e[t]).filter(e=>!!e),poses:n,embeddings:n.map(e=>t.faceEmbeddings[e]).filter(e=>!!e)}},Tt=[`faceStraight`,`faceUp`,`faceLeft`,`faceRight`],Et=({sequence:e})=>{let t=[...e];for(let e=t.length-1;e>0;--e){let n=Math.floor(Math.random()*(e+1));[t[e],t[n]]=[t[n],t[e]]}return t},Dt=({mode:e,poses:t,posesCount:n,randomize:r})=>{let i=e===`hard`?[...Y]:Tt,a=t===`all`?[...X]:t??i;if(!a.length)throw Error(b.INVALID_POSES);let o=[...new Set(a)];if(o.length!==a.length||o.some(e=>!X.includes(e))||o[0]!==`faceStraight`||e===`hard`&&Y.some(e=>!o.includes(e)))throw Error(b.INVALID_POSES);let s=r?[`faceStraight`,...Et({sequence:o.slice(1)})]:o,c=e===`hard`||t===`all`?s.length:n??5;if(!Number.isInteger(c)||c<1)throw Error(b.INVALID_POSES);return s.slice(0,Math.min(c,s.length))},Ot=()=>({activity:w(null),error:w(null),retry:w(null),feedback:w(null),cameraSize:w(null),cameraFacingMode:w(null),debug:w([]),debugEnabled:w(!1)});export{Xe as _,$ as a,ct as c,Y as d,K as f,J as g,at as h,wt as i,Z as l,Ze as m,Ct as n,Dt as o,q as p,Q as r,mt as s,Ot as t,X as u,Le as v,z as y};
@@ -0,0 +1,2 @@
1
+ /*! Copyright (c) 2026 VOLTOM. All rights reserved. Proprietary software. See LICENSE at https://voltom.io/license. */
2
+ import{Z as e,it as t}from"./faceMatch.shared-D6B1I2T0.js";import{n,t as r}from"./feedback-Cs09W_hs.js";var i=({pose:t,rejection:i,language:a})=>{let{translate:o}=e({language:a});return o(i?n({code:i}):r({pose:t}).primary)},a=()=>({operation:t(`enroll`),phase:t(`loading`),instruction:t(null),progress:t({completed:0,total:1}),feedback:t(null),failures:t(0),error:t(null),debug:t([]),debugEnabled:t(!1),match:t(null),facingMode:t(null)});export{i as n,a as t};
@@ -0,0 +1,7 @@
1
+ import type VoltomVerifyType from "../verify.js";
2
+
3
+ declare global {
4
+ var VoltomVerify: typeof VoltomVerifyType;
5
+ }
6
+
7
+ export {};
@@ -0,0 +1,197 @@
1
+ export type Mode = "fast" | "hard";
2
+
3
+ export type Pose =
4
+ | "faceStraight"
5
+ | "faceUp"
6
+ | "faceDown"
7
+ | "faceLeft"
8
+ | "faceRight"
9
+ | "faceSmile"
10
+ | "faceWinkLeft"
11
+ | "faceTiltLeft"
12
+ | "faceTiltRight";
13
+
14
+ export type Language = "ar" | "ch" | "de" | "en" | "es" | "fr" | "it" | "ja" | "pt" | "zh";
15
+
16
+ export type OcrEngine =
17
+ | "auto"
18
+ | "tiny"
19
+ | "small"
20
+ | "japanese"
21
+ | "chinese-simplified"
22
+ | "chinese-traditional"
23
+ | "cyrillic"
24
+ | "arabic";
25
+
26
+ export type FaceDetectorName = "high" | "standard" | "low";
27
+
28
+ export type VerificationCapability = "verifyHuman" | "verifyDocument" | "matchID" | "matchPicture";
29
+
30
+ export type VerificationOperationOptions = {
31
+ mode?: Mode;
32
+ poses?: Pose[] | "all";
33
+ posesCount?: number;
34
+ randomizeFaceSequence?: boolean;
35
+ showFaceOverlay?: boolean;
36
+ showDocumentOverlay?: boolean;
37
+ showTextOverlay?: boolean;
38
+ debug?: boolean;
39
+ signal?: AbortSignal;
40
+ };
41
+
42
+ export type VoltomOptions = {
43
+ root?: HTMLElement;
44
+ video?: HTMLVideoElement;
45
+ ui?: boolean;
46
+ mode?: Mode;
47
+ language?: Language;
48
+ ocrEngine?: OcrEngine;
49
+ faceDetector?: FaceDetectorName;
50
+ clientKey: string;
51
+ apiUrl?: string;
52
+ threshold: number;
53
+ poses?: Pose[] | "all";
54
+ posesCount?: number;
55
+ randomizeFaceSequence?: boolean;
56
+ requiredFaceStableFrames: number;
57
+ requiredDocumentStableFrames: number;
58
+ maxPitch: number;
59
+ minPitch: number;
60
+ maxYaw: number;
61
+ minYaw: number;
62
+ maxRoll: number;
63
+ minDocumentFaceAreaRatio: number;
64
+ maxDocumentFaceAreaRatio: number;
65
+ minDocumentFaceWidthRatio: number;
66
+ maxDocumentFaceWidthRatio: number;
67
+ minDocumentFaceHeightRatio: number;
68
+ maxDocumentFaceHeightRatio: number;
69
+ minDocumentBoxRatio: number;
70
+ maxDocumentTextAngleDifference: number;
71
+ showDocumentOverlay: boolean;
72
+ showFaceOverlay: boolean;
73
+ faceOverlayColor: string;
74
+ faceMeshColor: string;
75
+ documentOverlayColor: string;
76
+ documentBoxColor: string;
77
+ documentFaceBoxColor: string;
78
+ documentFaceMeshColor: string;
79
+ showTextOverlay: boolean;
80
+ textColor: string;
81
+ debug: boolean;
82
+ capabilities?: VerificationCapability[];
83
+ };
84
+
85
+ export type VoltomBrowserSupport = { supported: boolean; unsupportedFeatures: string[] };
86
+
87
+ export type VoltomCaptures = Partial<Record<Pose | "documentFront" | "documentBack", Blob>>;
88
+
89
+ export type FaceImages = { rgb: Blob; greyscale: Blob };
90
+
91
+ export type VoltomPreparedCaptures = Partial<Record<keyof VoltomCaptures | "picture", FaceImages>>;
92
+
93
+ export type IdentityPayload = {
94
+ document: {
95
+ source: "MRZ" | "AAMVA" | "OCR";
96
+ type: "PASSPORT" | "ID" | "VISA" | "DRV" | "PERMIT" | null;
97
+ issuing_country: string | null;
98
+ number: string | null;
99
+ issuing_authority: string | null;
100
+ issue_date: string | null;
101
+ expiry_date: string | null;
102
+ optional_data: string | null;
103
+ };
104
+ holder: {
105
+ first_name: string | null;
106
+ last_name: string | null;
107
+ middle_name: string | null;
108
+ birth_place: string | null;
109
+ birth_date: string | null;
110
+ sex: "M" | "F" | "X" | null;
111
+ nationality: string | null;
112
+ personal_number: string | null;
113
+ };
114
+ address: {
115
+ full: string | null;
116
+ street: string | null;
117
+ city: string | null;
118
+ state_province: string | null;
119
+ postal_code: string | null;
120
+ } | null;
121
+ raw_data: { mrz_lines: string[]; aamva_version: string | null };
122
+ };
123
+
124
+ export type DocumentCode = { code: string; payload: IdentityPayload; type: "mrz" | "aamva" | "ocr" };
125
+
126
+ export type OcrLine = {
127
+ angle: number;
128
+ box: { height: number; width: number; x: number; y: number };
129
+ confidence: number | null;
130
+ text: string;
131
+ words: { box: { height: number; width: number; x: number; y: number }; confidence: number | null; text: string }[];
132
+ };
133
+
134
+ export type OcrResult = { engine: string; height: number; lines: OcrLine[]; text: string; width: number };
135
+
136
+ export type ClassifiedDocument = {
137
+ document: "passport" | "id" | "visa" | "driving_license";
138
+ europeanDrivingLicense: boolean;
139
+ identity: IdentityPayload | null;
140
+ valid: boolean;
141
+ reasons: string[];
142
+ codes: DocumentCode[];
143
+ document_front: OcrResult;
144
+ document_back: OcrResult | null;
145
+ };
146
+
147
+ export type VoltomCaptureResult = {
148
+ identity: IdentityPayload | null;
149
+ captures: VoltomCaptures;
150
+ documentCodes: DocumentCode[];
151
+ preparedCaptures: VoltomPreparedCaptures;
152
+ document?: ClassifiedDocument;
153
+ };
154
+
155
+ export type VoltomVerificationResult = {
156
+ verificationId: string;
157
+ mode: Mode;
158
+ flow: "human" | "document" | "match_id" | "match_picture";
159
+ outcome: "completed" | "failed";
160
+ matched: boolean | null;
161
+ score: number | null;
162
+ threshold: number | null;
163
+ reason: string | null;
164
+ code: string | null;
165
+ identity: IdentityPayload | null;
166
+ completedAt: string | null;
167
+ createdAt: string;
168
+ };
169
+
170
+ export type VerificationPresentationState = {
171
+ activity: { message: string } | "matching" | null;
172
+ error: unknown | null;
173
+ retryAvailable: boolean;
174
+ feedback:
175
+ | { flow: "face"; pose: Pose; code: string | null }
176
+ | { flow: "document"; target: "front" | "back" | "passport"; code: string | null }
177
+ | null;
178
+ debug: { label: string; valid?: boolean; value: string }[];
179
+ };
180
+
181
+ declare class VoltomVerify {
182
+ constructor(options: VoltomOptions);
183
+ prepare(): Promise<void>;
184
+ caniuse(): Promise<VoltomBrowserSupport>;
185
+ verifyHuman(settings?: VerificationOperationOptions): Promise<VoltomVerificationResult>;
186
+ verifyDocument(settings?: VerificationOperationOptions): Promise<VoltomVerificationResult>;
187
+ matchID(settings?: VerificationOperationOptions): Promise<VoltomVerificationResult>;
188
+ matchPicture(picture: Blob, settings?: VerificationOperationOptions): Promise<VoltomVerificationResult>;
189
+ forgetHuman(): void;
190
+ forgetDocument(): void;
191
+ stop(): void;
192
+ dispose(): void;
193
+ getState(): VerificationPresentationState;
194
+ subscribe(listener: (state: VerificationPresentationState) => void): () => void;
195
+ }
196
+
197
+ export default VoltomVerify;