@voltom.io/sdk 1.0.4 → 1.0.5

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.
Files changed (38) hide show
  1. package/dist/assets/locales/ar.json +32 -29
  2. package/dist/assets/locales/ch.json +32 -29
  3. package/dist/assets/locales/de.json +32 -29
  4. package/dist/assets/locales/en.json +6 -3
  5. package/dist/assets/locales/es.json +31 -28
  6. package/dist/assets/locales/fr.json +31 -28
  7. package/dist/assets/locales/it.json +31 -28
  8. package/dist/assets/locales/ja.json +32 -29
  9. package/dist/assets/locales/pt.json +32 -29
  10. package/dist/assets/locales/ru.json +20 -17
  11. package/dist/assets/locales/zh.json +32 -29
  12. package/dist/sdk/{PoseSilhouette-CTZ5kqI_.js → PoseSilhouette-Bbwmry4Z.js} +1 -1
  13. package/dist/sdk/{PoseSuccess-CxL2ugaZ.js → PoseSuccess-C3aBF88E.js} +1 -1
  14. package/dist/sdk/eyeLevelCamera-DY4onSBz.js +65 -0
  15. package/dist/sdk/facegate.d.ts +4 -0
  16. package/dist/sdk/facegate.dist.js +1 -1
  17. package/dist/sdk/facegate.js +1 -1
  18. package/dist/sdk/facekey.browser-CVJiBw1f.js +2 -0
  19. package/dist/sdk/facekey.d.ts +11 -14
  20. package/dist/sdk/facekey.dist.js +5 -5
  21. package/dist/sdk/facekey.js +1 -1
  22. package/dist/sdk/{media-KU3CWepq.js → media-BRKPXpu3.js} +1 -1
  23. package/dist/sdk/presentation-B-TOKUZ3.js +8 -0
  24. package/dist/sdk/presentation-BsnbDv0i.js +2 -0
  25. package/dist/sdk/verify.d.ts +28 -27
  26. package/dist/sdk/verify.dist.js +6 -6
  27. package/dist/sdk/verify.js +1 -1
  28. package/dist/sdk/view-Bfg8u_hZ.js +2 -0
  29. package/dist/sdk/view-CHSkN6gO.js +3 -0
  30. package/dist/sdk/view-DmGKdc3M.js +3 -0
  31. package/package.json +3 -3
  32. package/dist/sdk/facekey.browser-D_vfob8H.js +0 -2
  33. package/dist/sdk/poseGuidance-DLg3Dm3T.js +0 -65
  34. package/dist/sdk/presentation-BCIQkuw0.js +0 -2
  35. package/dist/sdk/presentation-D9v4ITH0.js +0 -8
  36. package/dist/sdk/view-CsOmx3ht.js +0 -3
  37. package/dist/sdk/view-Dgrm0mpZ.js +0 -3
  38. package/dist/sdk/view-WiNYUW9A.js +0 -2
@@ -1,2 +1,2 @@
1
1
  /*! Copyright (c) 2026 VOLTOM. All rights reserved. Proprietary software. See LICENSE at https://voltom.io/license. */
2
- import{E as e,Q as t,et as n,q as r,s as i,t as a}from"./poseGuidance-DLg3Dm3T.js";import{E as o,a as s,f as c,h as l,i as u,l as d,m as f,o as p,s as m,t as h,u as g}from"./media-KU3CWepq.js";import{n as _}from"./facekey.browser-D_vfob8H.js";var v=()=>({active:n(!1),phase:n(`idle`),prompt:n(``),completed:n(0),total:n(1),outcome:n(null),captures:n([])}),y=e=>{if(typeof e.clientKey!=`string`||e.clientKey.length<8)throw Error(f.INVALID_OPTIONS);return e},b=e=>{if(typeof e.action!=`string`||e.action.length<1||e.action.length>255||typeof e.onPass!=`function`||typeof e.onReject!=`function`)throw Error(f.INVALID_OPTIONS);return e},x=e=>{if(typeof e!=`string`||e.length<32||e.length>128)throw Error(f.INVALID_SERVICE_RESPONSE);return e},{detectPictureFaces:S,loadFaceDetector:C}=_,w=3e4,T=e=>new Promise(t=>setTimeout(t,e)),E=async({frame:t,neutral:n,pose:r})=>{let o=await S(t,{blendshapes:!0}),s=o.length===1?o[0]:null;if(!s)return{alignment:null,code:null,prompt:`faceNotFound`,ready:!1};let c={pitch:s.pitch,yaw:s.yaw,roll:s.roll},l=s.boundingRect.height/Math.min(t.width,t.height),u=s.boundingRect.x+s.boundingRect.width/2,d=s.boundingRect.y+s.boundingRect.height/2,f=Math.hypot(u-t.width/2,d-t.height/2)<=Math.min(t.width,t.height)*.12;if(l<.5)return{alignment:c,code:null,prompt:`faceTooSmall`,ready:!1};if(!f)return{alignment:c,code:null,prompt:`centerFace`,ready:!1};let p=a({alignment:c,blendshapes:s.blendshapes,neutral:n,pose:r,options:e});if(p.code){let e=i({pose:r,code:p.code});return{alignment:c,code:p.code,prompt:e.corrective??e.primary,ready:!1}}return{alignment:c,code:null,prompt:i({pose:r,code:null}).primary,ready:!0}},D=class{options;display=v();handles=new Set;controller=null;view=null;prepared=!1;running=!1;disposed=!1;constructor(e){this.options=Object.freeze(y(e))}async caniuse(){return await h()}async prepare(){if(this.disposed)throw Error(f.SDK_NOT_READY);if(!this.prepared){if(await c({language:this.options.language}),await r({filenames:[`fd.ort`,`fe.ort`,`fl.ort`,`fmu.ort`,`ort-wasm-simd-threaded.mjs`,`ort-wasm-simd-threaded.wasm`]}),this.disposed)throw Error(f.SDK_NOT_READY);if(await C({faceDetector:`standard`}),!this.view){let{createFaceGateView:e}=await import(`./view-WiNYUW9A.js`);if(this.disposed)throw Error(f.SDK_NOT_READY);this.view=e({options:this.options,display:this.display,onCancel:()=>this.stop()})}if(this.disposed)throw Error(f.SDK_NOT_READY);this.prepared=!0}}arm(e,t){if(this.disposed||!this.prepared)throw Error(f.SDK_NOT_READY);let n=b(t),r,i=()=>{this.runGate(r)};return r={control:e,options:n,detach:()=>e.removeEventListener(`click`,i)},e.addEventListener(`click`,i),this.handles.add(r),r}disarm(e){e.detach(),this.handles.delete(e)}async request({path:e,body:t,signal:n}){let r=await fetch(`${(this.options.apiUrl??`https://api.voltom.io`).replace(/\/$/,``)}/facegate/${e}`,{method:`POST`,headers:{authorization:`Bearer ${this.options.clientKey}`,"content-type":`application/json`},body:JSON.stringify(t),signal:n}),i=await r.json().catch(()=>null);if(!r.ok)throw Error(typeof i?.code==`string`?i.code:f.INVALID_SERVICE_RESPONSE);return i}async capture({video:e,poses:n,signal:r}){let{translate:a}=g({language:this.options.language}),o=[],c=null;for(let[l,f]of n.entries()){let n=0;for(t(()=>{this.display.phase.value=`capturing`,this.display.completed.value=l,this.display.prompt.value=a(i({pose:f,code:null}).primary)});n<3;){await d({video:e,signal:r}),r.throwIfAborted();let t=await createImageBitmap(e);try{let e=await E({frame:t,neutral:c,pose:f});if(r.throwIfAborted(),n=e.ready?n+1:0,this.display.prompt.value=a(e.prompt),f===`faceStraight`&&!c&&e.ready&&(c=e.alignment),n>=3){let e=await u({frame:t});o.push(await s({image:e}))}}finally{t.close()}}this.display.completed.value=l+1}return o}async runGate(e){if(this.disposed||this.running)return;this.running=!0;let n=new AbortController;this.controller=n;let r=n.signal,i=e.options,a=()=>n.abort(new DOMException(f.FACEGATE_ABORTED,`AbortError`)),o=setTimeout(()=>n.abort(new DOMException(f.FACEGATE_TIMEOUT,`TimeoutError`)),w);i.signal?.addEventListener(`abort`,a,{once:!0}),i.signal?.aborted&&n.abort();let s=null;t(()=>{this.display.active.value=!0,this.display.phase.value=`capturing`,this.display.outcome.value=null,this.display.completed.value=0,this.display.total.value=1,this.display.prompt.value=``}),this.view?.open();try{let e=this.view?.video;if(!e)throw Error(f.INVALID_OPTIONS);await p({facingMode:`user`,video:e,signal:r}),r.throwIfAborted();let t=await Promise.all([i.subjectId?.(),i.context?.()]),n=await this.request({path:`challenge`,body:{action:i.action,subjectId:t[0],context:t[1]},signal:r});s=x(n.token),this.display.total.value=n.poses.length;let a=await this.capture({video:e,poses:n.poses,signal:r});r.throwIfAborted(),this.display.phase.value=`checking`,this.display.prompt.value=g({language:this.options.language}).translate(`checkingFaceMatch`);let o=await this.request({path:`verify`,body:{token:n.token,poses:n.poses,faces:a},signal:r});this.display.outcome.value=o.outcome,this.display.phase.value=o.outcome===`pass`?`pass`:`reject`,this.display.prompt.value=``,await T(950),this.view?.close(),o.outcome===`pass`?await i.onPass(n.token):i.onReject({outcome:o.outcome,code:o.code})}catch(e){let t=r.aborted?l({error:r.reason,fallback:f.FACEGATE_ABORTED}):l({error:e,fallback:f.SERVICE_UNAVAILABLE});if(t!==f.FACEGATE_ABORTED&&(this.display.outcome.value=`error`,this.display.phase.value=`reject`,this.display.prompt.value=``,await T(950)),this.view?.close(),s)try{await this.request({path:`abort`,body:{token:s,code:t},signal:AbortSignal.timeout(1e4)})}catch{}i.onReject({outcome:`error`,code:t})}finally{clearTimeout(o),i.signal?.removeEventListener(`abort`,a);let e=this.view?.video;e&&m({video:e}),this.display.active.value=!1,this.controller=null,this.running=!1}}stop(){this.controller&&this.controller.abort(new DOMException(f.FACEGATE_ABORTED,`AbortError`))}dispose(){if(!this.disposed){this.disposed=!0,this.stop();for(let e of this.handles)e.detach();this.handles.clear(),this.view?.close()}}getState(){return{active:this.display.active.value,phase:this.display.phase.value,prompt:this.display.prompt.value,completed:this.display.completed.value,total:this.display.total.value,outcome:this.display.outcome.value}}};o({moduleUrl:import.meta.url});var O=D;export{D as VoltomFaceGate,O as default};
2
+ import{O as e,Y as t,et as n,l as r,n as i,nt as a,r as o,t as s}from"./eyeLevelCamera-DY4onSBz.js";import{D as c,a as l,c as u,d,g as f,h as p,i as m,p as h,s as g,t as _,u as v}from"./media-BRKPXpu3.js";import{n as y}from"./facekey.browser-CVJiBw1f.js";var b=()=>({active:a(!1),phase:a(`idle`),prompt:a(``),completed:a(0),total:a(1),outcome:a(null),captures:a([])}),x=e=>{if(typeof e.clientKey!=`string`||e.clientKey.length<8||e.requireEyeLevelCamera!==void 0&&typeof e.requireEyeLevelCamera!=`boolean`)throw Error(p.INVALID_OPTIONS);return{...e,requireEyeLevelCamera:e.requireEyeLevelCamera??!1}},S=e=>{if(typeof e.action!=`string`||e.action.length<1||e.action.length>255||typeof e.onPass!=`function`||typeof e.onReject!=`function`)throw Error(p.INVALID_OPTIONS);return e},C=e=>{if(typeof e!=`string`||e.length<32||e.length>128)throw Error(p.INVALID_SERVICE_RESPONSE);return e},{detectPictureFaces:w,loadFaceDetector:T}=y,E=3e4,D=e=>new Promise(t=>setTimeout(t,e)),O=async({frame:t,neutral:n,pose:a,requireEyeLevelCamera:c})=>{let l=await w(t,{blendshapes:!0}),u=l.length===1?l[0]:null;if(!u)return{alignment:null,code:null,prompt:`faceNotFound`,ready:!1};let d={pitch:u.pitch,yaw:u.yaw,roll:u.roll},f=u.boundingRect.height/Math.min(t.width,t.height),p=u.boundingRect.x+u.boundingRect.width/2,m=u.boundingRect.y+u.boundingRect.height/2,h=Math.hypot(p-t.width/2,m-t.height/2)<=Math.min(t.width,t.height)*.12;if(f<.5)return{alignment:d,code:null,prompt:`faceTooSmall`,ready:!1};if(!h)return{alignment:d,code:null,prompt:`centerFace`,ready:!1};let g=i({pitch:u.pitch,pose:a,requireEyeLevelCamera:c,options:e});if(g)return{alignment:d,code:g,prompt:s(),ready:!1};let _=o({alignment:d,blendshapes:u.blendshapes,neutral:n,pose:a,options:e});if(_.code){let e=r({pose:a,code:_.code});return{alignment:d,code:_.code,prompt:e.corrective??e.primary,ready:!1}}return{alignment:d,code:null,prompt:r({pose:a,code:null}).primary,ready:!0}},k=class{options;display=b();handles=new Set;controller=null;view=null;prepared=!1;running=!1;disposed=!1;constructor(e){this.options=Object.freeze(x(e))}async caniuse(){return await _()}async prepare(){if(this.disposed)throw Error(p.SDK_NOT_READY);if(!this.prepared){if(await h({language:this.options.language}),await t({filenames:[`fd.ort`,`fe.ort`,`fl.ort`,`fmu.ort`,`ort-wasm-simd-threaded.mjs`,`ort-wasm-simd-threaded.wasm`]}),this.disposed)throw Error(p.SDK_NOT_READY);if(await T({faceDetector:`standard`}),!this.view){let{createFaceGateView:e}=await import(`./view-Bfg8u_hZ.js`);if(this.disposed)throw Error(p.SDK_NOT_READY);this.view=e({options:this.options,display:this.display,onCancel:()=>this.stop()})}if(this.disposed)throw Error(p.SDK_NOT_READY);this.prepared=!0}}arm(e,t){if(this.disposed||!this.prepared)throw Error(p.SDK_NOT_READY);let n=S(t),r,i=()=>{this.runGate(r)};return r={control:e,options:n,detach:()=>e.removeEventListener(`click`,i)},e.addEventListener(`click`,i),this.handles.add(r),r}disarm(e){e.detach(),this.handles.delete(e)}async request({path:e,body:t,signal:n}){let r=await fetch(`${(this.options.apiUrl??`https://api.voltom.io`).replace(/\/$/,``)}/facegate/${e}`,{method:`POST`,headers:{authorization:`Bearer ${this.options.clientKey}`,"content-type":`application/json`},body:JSON.stringify(t),signal:n}),i=await r.json().catch(()=>null);if(!r.ok)throw Error(typeof i?.code==`string`?i.code:p.INVALID_SERVICE_RESPONSE);return i}async capture({video:e,poses:t,signal:i}){let{translate:a}=d({language:this.options.language}),o=[],s=null;for(let[c,u]of t.entries()){let t=0;for(n(()=>{this.display.phase.value=`capturing`,this.display.completed.value=c,this.display.prompt.value=a(r({pose:u,code:null}).primary)});t<3;){await v({video:e,signal:i}),i.throwIfAborted();let n=await createImageBitmap(e);try{let e=await O({frame:n,neutral:s,pose:u,requireEyeLevelCamera:this.options.requireEyeLevelCamera??!1});if(i.throwIfAborted(),t=e.ready?t+1:0,this.display.prompt.value=a(e.prompt),u===`faceStraight`&&e.ready&&(s=e.alignment),t>=3){let e=await m({frame:n});o.push(await l({image:e}))}}finally{n.close()}}this.display.completed.value=c+1}return o}async runGate(e){if(this.disposed||this.running)return;this.running=!0;let t=new AbortController;this.controller=t;let r=t.signal,i=e.options,a=()=>t.abort(new DOMException(p.FACEGATE_ABORTED,`AbortError`)),o=setTimeout(()=>t.abort(new DOMException(p.FACEGATE_TIMEOUT,`TimeoutError`)),E);i.signal?.addEventListener(`abort`,a,{once:!0}),i.signal?.aborted&&t.abort();let s=null;n(()=>{this.display.active.value=!0,this.display.phase.value=`capturing`,this.display.outcome.value=null,this.display.completed.value=0,this.display.total.value=1,this.display.prompt.value=``}),this.view?.open();try{let e=this.view?.video;if(!e)throw Error(p.INVALID_OPTIONS);await g({facingMode:`user`,video:e,signal:r}),r.throwIfAborted();let t=await Promise.all([i.subjectId?.(),i.context?.()]),n=await this.request({path:`challenge`,body:{action:i.action,subjectId:t[0],context:t[1]},signal:r});s=C(n.token),this.display.total.value=n.poses.length;let a=await this.capture({video:e,poses:n.poses,signal:r});r.throwIfAborted(),this.display.phase.value=`checking`,this.display.prompt.value=d({language:this.options.language}).translate(`checkingFaceMatch`);let o=await this.request({path:`verify`,body:{token:n.token,poses:n.poses,faces:a},signal:r});this.display.outcome.value=o.outcome,this.display.phase.value=o.outcome===`pass`?`pass`:`reject`,this.display.prompt.value=``,await D(950),this.view?.close(),o.outcome===`pass`?await i.onPass(n.token):i.onReject({outcome:o.outcome,code:o.code})}catch(e){let t=r.aborted?f({error:r.reason,fallback:p.FACEGATE_ABORTED}):f({error:e,fallback:p.SERVICE_UNAVAILABLE});if(t!==p.FACEGATE_ABORTED&&(this.display.outcome.value=`error`,this.display.phase.value=`reject`,this.display.prompt.value=``,await D(950)),this.view?.close(),s)try{await this.request({path:`abort`,body:{token:s,code:t},signal:AbortSignal.timeout(1e4)})}catch{}i.onReject({outcome:`error`,code:t})}finally{clearTimeout(o),i.signal?.removeEventListener(`abort`,a);let e=this.view?.video;e&&u({video:e}),this.display.active.value=!1,this.controller=null,this.running=!1}}stop(){this.controller&&this.controller.abort(new DOMException(p.FACEGATE_ABORTED,`AbortError`))}dispose(){if(!this.disposed){this.disposed=!0,this.stop();for(let e of this.handles)e.detach();this.handles.clear(),this.view?.close()}}getState(){return{active:this.display.active.value,phase:this.display.phase.value,prompt:this.display.prompt.value,completed:this.display.completed.value,total:this.display.total.value,outcome:this.display.outcome.value}}};c({moduleUrl:import.meta.url});var A=k;export{k as VoltomFaceGate,A as default};
@@ -0,0 +1,2 @@
1
+ /*! Copyright (c) 2026 VOLTOM. All rights reserved. Proprietary software. See LICENSE at https://voltom.io/license. */
2
+ import{V as e,g as t,h as n,m as r,p as i,z as a}from"./eyeLevelCamera-DY4onSBz.js";var o=e({runtime:a}),s=r({runtime:a}),c=t({runtime:a}),l=n({runtime:a,imageFromImageBitmap:o}),u=i({runtime:a,...s,...c,...l,faceDetection:l});export{l as n,u as r,c as t};
@@ -13,10 +13,13 @@ export type FaceKeyUnlock = {
13
13
 
14
14
  export type FaceKeyCapability = FaceKeyOperation;
15
15
 
16
+ export type VoltomBrowserSupport = { supported: boolean; unsupportedFeatures: string[] };
17
+
16
18
  export type FaceKeyOperationOptions = { signal?: AbortSignal; debug?: boolean };
17
19
 
18
20
  export type VoltomFaceKeyOptions = {
19
21
  clientKey: string;
22
+ requireEyeLevelCamera?: boolean;
20
23
  apiUrl?: string;
21
24
  debug?: boolean;
22
25
  language?: "ar" | "ch" | "de" | "en" | "es" | "fr" | "it" | "ja" | "pt" | "zh";
@@ -28,20 +31,12 @@ export type VoltomFaceKeyOptions = {
28
31
  export type FaceKeyIdentity = { userId: string };
29
32
 
30
33
  export type FaceKeyInstruction = {
31
- pose: FaceKeyPose;
32
- rejection:
33
- | "FACEKEY_LOWER_HEAD"
34
- | "FACEKEY_LOWER_HEAD_LESS"
35
- | "FACEKEY_RAISE_HEAD"
36
- | "FACEKEY_RAISE_HEAD_LESS"
37
- | "FACEKEY_TILT_HEAD_LEFT"
38
- | "FACEKEY_TILT_HEAD_LESS"
39
- | "FACEKEY_TILT_HEAD_RIGHT"
40
- | "FACEKEY_TURN_HEAD_LEFT"
41
- | "FACEKEY_TURN_HEAD_LESS"
42
- | "FACEKEY_TURN_HEAD_RIGHT"
43
- | "FACEKEY_SMILE_REQUIRED"
44
- | "FACEKEY_WINK_LEFT_REQUIRED"
34
+ framing:
35
+ | "FACE_NOT_DETECTED"
36
+ | "FACE_IN_POLYGON"
37
+ | "FACE_TOO_SMALL"
38
+ | "FACE_NOT_CENTERED"
39
+ | "FACE_CAMERA_ALIGNMENT_REQUIRED"
45
40
  | null;
46
41
  retry: string | null;
47
42
  };
@@ -59,7 +54,9 @@ export type VoltomFaceKeyState = {
59
54
 
60
55
  export declare class VoltomFaceKey {
61
56
  constructor(options: VoltomFaceKeyOptions);
57
+ preload(): Promise<void>;
62
58
  prepare(): Promise<void>;
59
+ caniuse(): Promise<VoltomBrowserSupport>;
63
60
  faceEnroll(input: FaceKeyInput, options?: FaceKeyOperationOptions): Promise<FaceKeyIdentity>;
64
61
  faceUnlock(input: FaceKeyInput & { userId: string }, options?: FaceKeyOperationOptions): Promise<FaceKeyUnlock>;
65
62
  stop(): void;