@smileid/usesmileid 12.3.1-SNAPSHOT.71 → 12.3.1-SNAPSHOT.73

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.
@@ -1 +1 @@
1
- "use strict";import{JobType as e}from"../../core/models/job_type";import{UseSmileIDBuilderException as i}from"./use_smile_id_builder_exception";import{UseSmileIDErrorCode as r}from"./use_smile_id_error_code";export class InvalidJobTypeScreenConfigException extends i{errorCode=r.Builder.InvalidJobTypeScreenConfig;constructor(n){super({message:n.message,suggestedFix:n.suggestedFix??"Adjust the screens block to match the configured jobType."})}static forJob(n){const t=jobTypeName(n.jobType);return new InvalidJobTypeScreenConfigException({message:`Invalid configuration for ${t}: ${n.reason}`,suggestedFix:n.suggestedFix})}}const c=new Map([[e.biometricKyc,"BiometricKyc"],[e.smartSelfieAuthentication,"SmartSelfieAuthentication"],[e.smartSelfieEnrollment,"SmartSelfieEnrollment"],[e.enhancedKyc,"EnhancedKyc"],[e.documentVerification,"DocumentVerification"],[e.bvn,"BVN"],[e.enhancedDocumentVerification,"EnhancedDocumentVerification"],[e.residencyDocumentVerification,"ResidencyDocumentVerification"],[e.unknown,"Unknown"]]);export function jobTypeName(o){return c.get(o)??"Unknown"}
1
+ "use strict";import{JobType as e}from"../../core/models/job_type";import{UseSmileIDBuilderException as i}from"./use_smile_id_builder_exception";import{UseSmileIDErrorCode as r}from"./use_smile_id_error_code";export class InvalidJobTypeScreenConfigException extends i{errorCode=r.Builder.InvalidJobTypeScreenConfig;constructor(n){super({message:n.message,suggestedFix:n.suggestedFix??"Adjust the screens block to match the configured jobType."})}static forJob(n){const t=jobTypeName(n.jobType);return new InvalidJobTypeScreenConfigException({message:`Invalid configuration for ${t}: ${n.reason}`,suggestedFix:n.suggestedFix})}}const c=new Map([[e.biometricKyc,"BiometricKyc"],[e.smartSelfieAuthentication,"SmartSelfieAuthentication"],[e.smartSelfieEnrollment,"SmartSelfieEnrollment"],[e.enhancedKyc,"EnhancedKyc"],[e.documentVerification,"DocumentVerification"],[e.bvn,"BVN"],[e.enhancedDocumentVerification,"EnhancedDocumentVerification"],[e.residencyDocumentVerification,"ResidencyDocumentVerification"],[e.unknownProduct,"UnknownProduct"],[e.unknown,"Unknown"]]);export function jobTypeName(o){return c.get(o)??"Unknown"}
@@ -18,6 +18,14 @@ export declare const JobType: {
18
18
  * a mandatory supporting visa capture, submitted as one job.
19
19
  */
20
20
  readonly residencyDocumentVerification: 16;
21
+ /**
22
+ * A job whose product your backend chooses. The flow captures whatever
23
+ * its screens configure, with none of a product's rules, and hands the job
24
+ * back for you to forward to that product's endpoint. Valid only with
25
+ * `config.skipApiSubmission = true`: Smile ID has no endpoint for it, so the
26
+ * SDK never submits it.
27
+ */
28
+ readonly unknownProduct: -2;
21
29
  /**
22
30
  * Sentinel used when no job type has been configured, or when the
23
31
  * server returns a value not recognised by this SDK version. Update
@@ -1 +1 @@
1
- "use strict";export const JobType={biometricKyc:1,smartSelfieAuthentication:2,smartSelfieEnrollment:4,enhancedKyc:5,documentVerification:6,bvn:7,enhancedDocumentVerification:11,residencyDocumentVerification:16,unknown:-1};export function jobTypeFromValue(e){return Object.values(JobType).find(n=>n===e)??JobType.unknown}export function requiresSelfie(e){return e===JobType.biometricKyc||e===JobType.smartSelfieAuthentication||e===JobType.smartSelfieEnrollment}export function requiresDocument(e){return e===JobType.biometricKyc||e===JobType.documentVerification||e===JobType.enhancedDocumentVerification||e===JobType.residencyDocumentVerification}
1
+ "use strict";export const JobType={biometricKyc:1,smartSelfieAuthentication:2,smartSelfieEnrollment:4,enhancedKyc:5,documentVerification:6,bvn:7,enhancedDocumentVerification:11,residencyDocumentVerification:16,unknownProduct:-2,unknown:-1};export function jobTypeFromValue(e){return Object.values(JobType).find(n=>n===e)??JobType.unknown}export function requiresSelfie(e){return e===JobType.biometricKyc||e===JobType.smartSelfieAuthentication||e===JobType.smartSelfieEnrollment}export function requiresDocument(e){return e===JobType.biometricKyc||e===JobType.documentVerification||e===JobType.enhancedDocumentVerification||e===JobType.residencyDocumentVerification}
@@ -1,5 +1,5 @@
1
1
  import type { PartnerConfig } from "../../core/models/network_config";
2
- import type { BiometricKycRequest, DocumentVerificationRequest, EnhancedDocumentVerificationRequest, ResidencyDocumentVerificationRequest, EnhancedKycRequest, SmartSelfieAuthenticationRequest, SmartSelfieEnrollmentRequest } from "../model/job_request";
2
+ import type { BiometricKycRequest, DocumentVerificationRequest, EnhancedDocumentVerificationRequest, ResidencyDocumentVerificationRequest, EnhancedKycRequest, SmartSelfieAuthenticationRequest, SmartSelfieEnrollmentRequest, UnknownProductRequest } from "../model/job_request";
3
3
  import type { JobSubmissionResponse } from "../model/job_submission_response";
4
4
  import { type BridgeSubmissions } from "./bridge_submissions";
5
5
  /**
@@ -50,6 +50,14 @@ export declare class SmileIDAPI {
50
50
  documentVerification(request: DocumentVerificationRequest): Promise<JobSubmissionResponse>;
51
51
  enhancedDocumentVerification(request: EnhancedDocumentVerificationRequest): Promise<JobSubmissionResponse>;
52
52
  residencyDocumentVerification(request: ResidencyDocumentVerificationRequest): Promise<JobSubmissionResponse>;
53
+ /**
54
+ * An unknown product's captures. Only the sealing client takes them, and
55
+ * the client that sends refuses them: the job only runs with
56
+ * `skipApiSubmission`, and the partner forwards it to the product's own
57
+ * endpoint. Its path is never requested, and neither the request signature
58
+ * nor the package covers the path.
59
+ */
60
+ unknownProduct(request: UnknownProductRequest): Promise<JobSubmissionResponse>;
53
61
  private _postDocumentVerification;
54
62
  /**
55
63
  * Build the selfie + liveness portion of a multipart form. No
@@ -1 +1 @@
1
- "use strict";import{isEmptyConsent as f}from"../../core/models/params";import{userDetailsPayloadToWire as l}from"../model/user_details_payload";import{NetworkResponseParseException as s}from"../../core/exception";import{LivenessFrameCountException as p}from"../../core/exception";import{JobForm as d}from"../model/job_form";import{BridgeSealed as m}from"./bridge_submissions";export class SmileIDAPI{_partnerConfig;_bridge;_sealing;_warmed=!1;constructor(e,i,n=!1){this._partnerConfig=e,this._bridge=i,this._sealing=n}warmUpConnection(){if(!this._warmed){this._warmed=!0;try{this._bridge.warm()}catch{}}}async smartSelfieEnrollment(e){const i=this._buildSelfieForm(e);return a(i,e),this._appendPartnerConfigParts(i),this._appendConsentAndMetadata(i,e.consent,e.metadata),this._post("/v3/registration",i)}async smartSelfieAuthentication(e){const i=this._buildSelfieForm(e);return i.field("user_id",e.userId),a(i,e),this._appendPartnerConfigParts(i),this._appendConsentAndMetadata(i,e.consent,e.metadata),this._post("/v3/authentication",i)}async enhancedKyc(e){const i=new d;return this._appendIdFields(i,e.params),a(i,e),e.params.bankCode&&i.field("bank_code",e.params.bankCode),e.params.mobileOperator&&i.field("operator",e.params.mobileOperator),this._appendPartnerConfigParts(i),this._appendConsentAndMetadata(i,e.consent,e.metadata),this._post("/v3/enhanced_kyc",i)}async biometricKyc(e){const i=e.params.useEnrolledImage,n=this._buildSelfieForm(e);return this._appendIdFields(n,e.params),a(n,e),i&&n.field("use_enrolled_image","true"),this._appendPartnerConfigParts(n),this._appendConsentAndMetadata(n,e.consent,e.metadata),this._post("/v3/biometric_kyc",n)}async documentVerification(e){return this._postDocumentVerification(e,"/v3/document_verification")}async enhancedDocumentVerification(e){return this._postDocumentVerification(e,"/v3/enhanced_document_verification")}async residencyDocumentVerification(e){return this._postDocumentVerification(e,"/v3/residency_document_verification")}async _postDocumentVerification(e,i){const n=this._buildSelfieForm(e);return n.file("document",e.frontDocument),"backDocument"in e&&e.backDocument&&n.file("document_back",e.backDocument),"visaDocument"in e&&n.file("visa",e.visaDocument),e.country&&n.field("country",e.country),e.idType&&n.field("id_type",e.idType),a(n,e),this._appendPartnerConfigParts(n),this._appendConsentAndMetadata(n,e.consent,e.metadata),this._post(i,n)}_buildSelfieForm(e){SmileIDAPI._validateLivenessCount(e.livenessImages,e.expectedLivenessImageCount);const i=new d;i.file("selfie_image",e.selfieImage);for(const n of e.livenessImages)i.file("liveness_images",n);return i}static _validateLivenessCount(e,i){if(e.length!==i)throw new p({expected:i,actual:e.length})}_appendIdFields(e,i){i.idType&&e.field("id_type",i.idType),i.idNumber&&e.field("id_number",i.idNumber),i.country&&e.field("country",i.country)}_appendPartnerConfigParts(e){const i=this._partnerConfig.callbackUrl;i&&e.field("callback_url",i);const n=this._partnerConfig.partnerParams;n&&Object.keys(n).length>0&&e.json("partner_params",n)}_appendConsentAndMetadata(e,i,n){i!==void 0&&f(i)?e.json("consent",{}):i!==void 0&&e.json("consent",{granted:i.granted,granted_at:i.grantedAt,notice_language:i.noticeLanguage,notice_privacy_policy_url:i.noticePrivacyPolicyUrl}),e.json("metadata",n.toEntries())}async _post(e,i){if(this._sealing)throw new m(await this._bridge.seal(e,i));return _(await this._bridge.submit(e,i))}}function _(t){if(t==null||typeof t!="object"||Array.isArray(t))throw new s({message:"SmileIDAPI: server returned an empty or non-object response body."});const e=t,i=(r,c)=>{if(typeof r!="string")throw new s({message:`SmileIDAPI: response is missing the required string field '${c}'.`});return r},n={jobId:i(e.job_id??e.jobId,"job_id"),userId:i(e.user_id??e.userId,"user_id"),status:i(e.status,"status"),message:i(e.message,"message")},o=e.created_at??e.createdAt;return typeof o=="string"&&o.length>0?{...n,createdAt:o}:n}function a(t,e){const i=e.userDetails;i!==void 0&&t.json("user_details",l(i))}
1
+ "use strict";import{isEmptyConsent as f}from"../../core/models/params";import{userDetailsPayloadToWire as l}from"../model/user_details_payload";import{NetworkResponseParseException as d}from"../../core/exception";import{LivenessFrameCountException as m}from"../../core/exception";import{InvalidFieldValueException as p}from"../../core/exception";import{JobForm as s}from"../model/job_form";import{BridgeSealed as _}from"./bridge_submissions";export class SmileIDAPI{_partnerConfig;_bridge;_sealing;_warmed=!1;constructor(e,n,i=!1){this._partnerConfig=e,this._bridge=n,this._sealing=i}warmUpConnection(){if(!this._warmed){this._warmed=!0;try{this._bridge.warm()}catch{}}}async smartSelfieEnrollment(e){const n=this._buildSelfieForm(e);return a(n,e),this._appendPartnerConfigParts(n),this._appendConsentAndMetadata(n,e.consent,e.metadata),this._post("/v3/registration",n)}async smartSelfieAuthentication(e){const n=this._buildSelfieForm(e);return n.field("user_id",e.userId),a(n,e),this._appendPartnerConfigParts(n),this._appendConsentAndMetadata(n,e.consent,e.metadata),this._post("/v3/authentication",n)}async enhancedKyc(e){const n=new s;return this._appendIdFields(n,e.params),a(n,e),e.params.bankCode&&n.field("bank_code",e.params.bankCode),e.params.mobileOperator&&n.field("operator",e.params.mobileOperator),this._appendPartnerConfigParts(n),this._appendConsentAndMetadata(n,e.consent,e.metadata),this._post("/v3/enhanced_kyc",n)}async biometricKyc(e){const n=e.params.useEnrolledImage,i=this._buildSelfieForm(e);return this._appendIdFields(i,e.params),a(i,e),n&&i.field("use_enrolled_image","true"),this._appendPartnerConfigParts(i),this._appendConsentAndMetadata(i,e.consent,e.metadata),this._post("/v3/biometric_kyc",i)}async documentVerification(e){return this._postDocumentVerification(e,"/v3/document_verification")}async enhancedDocumentVerification(e){return this._postDocumentVerification(e,"/v3/enhanced_document_verification")}async residencyDocumentVerification(e){return this._postDocumentVerification(e,"/v3/residency_document_verification")}async unknownProduct(e){if(!this._sealing)throw new p({fieldName:"jobType",reason:"an unknown product is only sealed, never submitted"});e.expectedLivenessImageCount!==void 0&&SmileIDAPI._validateLivenessCount(e.livenessImages,e.expectedLivenessImageCount);const n=new s;e.selfieImage&&n.file("selfie_image",e.selfieImage);for(const i of e.livenessImages)n.file("liveness_images",i);return e.frontDocument&&n.file("document",e.frontDocument),e.backDocument&&n.file("document_back",e.backDocument),a(n,e),this._appendPartnerConfigParts(n),this._appendConsentAndMetadata(n,e.consent,e.metadata),this._post(g,n)}async _postDocumentVerification(e,n){const i=this._buildSelfieForm(e);return i.file("document",e.frontDocument),"backDocument"in e&&e.backDocument&&i.file("document_back",e.backDocument),"visaDocument"in e&&i.file("visa",e.visaDocument),e.country&&i.field("country",e.country),e.idType&&i.field("id_type",e.idType),a(i,e),this._appendPartnerConfigParts(i),this._appendConsentAndMetadata(i,e.consent,e.metadata),this._post(n,i)}_buildSelfieForm(e){SmileIDAPI._validateLivenessCount(e.livenessImages,e.expectedLivenessImageCount);const n=new s;n.file("selfie_image",e.selfieImage);for(const i of e.livenessImages)n.file("liveness_images",i);return n}static _validateLivenessCount(e,n){if(e.length!==n)throw new m({expected:n,actual:e.length})}_appendIdFields(e,n){n.idType&&e.field("id_type",n.idType),n.idNumber&&e.field("id_number",n.idNumber),n.country&&e.field("country",n.country)}_appendPartnerConfigParts(e){const n=this._partnerConfig.callbackUrl;n&&e.field("callback_url",n);const i=this._partnerConfig.partnerParams;i&&Object.keys(i).length>0&&e.json("partner_params",i)}_appendConsentAndMetadata(e,n,i){n!==void 0&&f(n)?e.json("consent",{}):n!==void 0&&e.json("consent",{granted:n.granted,granted_at:n.grantedAt,notice_language:n.noticeLanguage,notice_privacy_policy_url:n.noticePrivacyPolicyUrl}),e.json("metadata",i.toEntries())}async _post(e,n){if(this._sealing)throw new _(await this._bridge.seal(e,n));return u(await this._bridge.submit(e,n))}}const g="/v3/unknown_product";function u(t){if(t==null||typeof t!="object"||Array.isArray(t))throw new d({message:"SmileIDAPI: server returned an empty or non-object response body."});const e=t,n=(r,c)=>{if(typeof r!="string")throw new d({message:`SmileIDAPI: response is missing the required string field '${c}'.`});return r},i={jobId:n(e.job_id??e.jobId,"job_id"),userId:n(e.user_id??e.userId,"user_id"),status:n(e.status,"status"),message:n(e.message,"message")},o=e.created_at??e.createdAt;return typeof o=="string"&&o.length>0?{...i,createdAt:o}:i}function a(t,e){const n=e.userDetails;n!==void 0&&t.json("user_details",l(n))}
@@ -6,7 +6,9 @@ import type { SealedJobRequest } from "./sealed_job_request";
6
6
  * own backend: send the job type's `/v3` request with `headers` as request
7
7
  * headers, the images as their usual form parts, and `encryptedPackage`,
8
8
  * `packageNonce` and `packageTag` as the `encrypted_package`, `package_nonce`
9
- * and `package_tag` form fields.
9
+ * and `package_tag` form fields. A `JobType.unknownProduct` job goes to the
10
+ * endpoint of the product you choose, with that product's own fields, such as
11
+ * `country` and `id_type`, sent beside the package.
10
12
  *
11
13
  * Everything else the SDK would have sent (the consent record, the metadata,
12
14
  * the signature and the other `smileid-*` headers) travels inside
@@ -1 +1 @@
1
- "use strict";import{JobType as t}from"../../core/models/job_type";export function capturedJobFrom(e,a,c){const n=m(e),i=r([n.selfieImage,...n.livenessImages,n.frontDocument,n.backDocument,n.visaDocument]);return Object.freeze({jobType:e.jobType,sessionId:a,...i!==void 0?{sessionDirectory:i}:{},...n.selfieImage!==void 0?{selfieImage:n.selfieImage}:{},livenessImages:Object.freeze([...n.livenessImages]),...n.frontDocument!==void 0?{frontDocument:n.frontDocument}:{},...n.backDocument!==void 0?{backDocument:n.backDocument}:{},...n.visaDocument!==void 0?{visaDocument:n.visaDocument}:{},headers:c.headers,encryptedPackage:c.encryptedPackage,packageNonce:c.packageNonce,packageTag:c.packageTag})}function m(e){switch(e.jobType){case t.smartSelfieEnrollment:case t.smartSelfieAuthentication:case t.biometricKyc:return{selfieImage:e.selfieImage,livenessImages:e.livenessImages};case t.documentVerification:case t.enhancedDocumentVerification:return{selfieImage:e.selfieImage,livenessImages:e.livenessImages,frontDocument:e.frontDocument,...e.backDocument!==void 0?{backDocument:e.backDocument}:{}};case t.residencyDocumentVerification:return{selfieImage:e.selfieImage,livenessImages:e.livenessImages,frontDocument:e.frontDocument,visaDocument:e.visaDocument};case t.enhancedKyc:case t.bvn:return{livenessImages:[]}}}function o(e){const a=e.lastIndexOf("/");if(a<=0)return;const c=e.slice(0,a);return/^[a-z][a-z0-9+.-]*:\/*$/i.test(c)?void 0:c}const f="UseSmileID";function r(e){const a=new Set(e.filter(s=>s!==void 0).map(o));if(a.size!==1)return;const[c]=a;if(c===void 0)return;const n=o(c);return n?.slice(n.lastIndexOf("/")+1)===f?c:void 0}
1
+ "use strict";import{JobType as a}from"../../core/models/job_type";export function capturedJobFrom(e,o,c){const n=m(e),i=r([n.selfieImage,...n.livenessImages,n.frontDocument,n.backDocument,n.visaDocument]);return Object.freeze({jobType:e.jobType,sessionId:o,...i!==void 0?{sessionDirectory:i}:{},...n.selfieImage!==void 0?{selfieImage:n.selfieImage}:{},livenessImages:Object.freeze([...n.livenessImages]),...n.frontDocument!==void 0?{frontDocument:n.frontDocument}:{},...n.backDocument!==void 0?{backDocument:n.backDocument}:{},...n.visaDocument!==void 0?{visaDocument:n.visaDocument}:{},headers:c.headers,encryptedPackage:c.encryptedPackage,packageNonce:c.packageNonce,packageTag:c.packageTag})}function m(e){switch(e.jobType){case a.smartSelfieEnrollment:case a.smartSelfieAuthentication:case a.biometricKyc:return{selfieImage:e.selfieImage,livenessImages:e.livenessImages};case a.documentVerification:case a.enhancedDocumentVerification:return{selfieImage:e.selfieImage,livenessImages:e.livenessImages,frontDocument:e.frontDocument,...e.backDocument!==void 0?{backDocument:e.backDocument}:{}};case a.residencyDocumentVerification:return{selfieImage:e.selfieImage,livenessImages:e.livenessImages,frontDocument:e.frontDocument,visaDocument:e.visaDocument};case a.unknownProduct:return{...e.selfieImage!==void 0?{selfieImage:e.selfieImage}:{},livenessImages:e.livenessImages,...e.frontDocument!==void 0?{frontDocument:e.frontDocument}:{},...e.backDocument!==void 0?{backDocument:e.backDocument}:{}};case a.enhancedKyc:case a.bvn:return{livenessImages:[]}}}function t(e){const o=e.lastIndexOf("/");if(o<=0)return;const c=e.slice(0,o);return/^[a-z][a-z0-9+.-]*:\/*$/i.test(c)?void 0:c}const f="UseSmileID";function r(e){const o=new Set(e.filter(s=>s!==void 0).map(t));if(o.size!==1)return;const[c]=o;if(c===void 0)return;const n=t(c);return n?.slice(n.lastIndexOf("/")+1)===f?c:void 0}
@@ -160,4 +160,21 @@ export type ResidencyDocumentVerificationRequest = BaseJobRequest & {
160
160
  /** See `SmartSelfieEnrollmentRequest.expectedLivenessImageCount`. */
161
161
  readonly expectedLivenessImageCount: number;
162
162
  };
163
- export type JobRequest = SmartSelfieEnrollmentRequest | SmartSelfieAuthenticationRequest | EnhancedKycRequest | BvnRequest | BiometricKycRequest | DocumentVerificationRequest | EnhancedDocumentVerificationRequest | ResidencyDocumentVerificationRequest;
163
+ /**
164
+ * Whatever the flow's screens captured, for the partner's backend to forward
165
+ * to the product it chooses: a selfie with its liveness stills, a document's
166
+ * sides, or both. It carries none of a product's own fields; the partner adds
167
+ * those when forwarding. Only ever sealed, never submitted.
168
+ */
169
+ export type UnknownProductRequest = BaseJobRequest & {
170
+ readonly jobType: typeof JobType.unknownProduct;
171
+ readonly selfieImage?: string;
172
+ readonly livenessImages: readonly string[];
173
+ readonly frontDocument?: string;
174
+ readonly backDocument?: string;
175
+ /** Omitted when the token binds every required field, or reduced to the unbound remainder. */
176
+ readonly userDetails?: UserDetailsPayload;
177
+ /** See `SmartSelfieEnrollmentRequest.expectedLivenessImageCount`; absent when no selfie was captured. */
178
+ readonly expectedLivenessImageCount?: number;
179
+ };
180
+ export type JobRequest = SmartSelfieEnrollmentRequest | SmartSelfieAuthenticationRequest | EnhancedKycRequest | BvnRequest | BiometricKycRequest | DocumentVerificationRequest | EnhancedDocumentVerificationRequest | ResidencyDocumentVerificationRequest | UnknownProductRequest;
@@ -1 +1 @@
1
- "use strict";import{failure as c,success as l}from"../../core/models/result";import{JobType as t}from"../../core/models/job_type";import{InvalidFieldValueException as f}from"../../core/exception/job_validation_exceptions";import{UseSmileIDException as d}from"../../core/exception/use_smile_id_exception";import{NetworkUnknownException as o}from"../../core/exception/use_smile_id_network_exception";import{PayloadCompressionRunner as m}from"../compression/payload_compression_runner";import{BridgeSealed as _}from"../api/bridge_submissions";function p(i){const e=[],n=(a,s)=>{s!==void 0&&s>0&&e.push({name:a,value:String(s)})};return n("selfie_original_size",i.selfieOriginalMb),n("selfie_final_compressed_size",i.selfieFinalMb),n("document_front_original_size",i.frontOriginalMb),n("document_front_final_compressed_size",i.frontFinalMb),n("document_back_original_size",i.backOriginalMb),n("document_back_final_compressed_size",i.backFinalMb),n("document_visa_original_size",i.visaOriginalMb),n("document_visa_final_compressed_size",i.visaFinalMb),e}export class UseSmileIDRepositoryImpl{_api;_captureApi;constructor(e,n){this._api=e,this._captureApi=n}async seal(e,n){if(e.jobType===t.bvn)return c(new f({fieldName:"jobType",reason:"BVN submission is not yet supported"}));const a=this._captureApi;if(!a)return c(new o({message:"No capture client to seal the request through"}));const s=await this._compressed(e,n);try{return await UseSmileIDRepositoryImpl._send(a,s),c(new o({message:"The capture client sent the request instead of sealing it"}))}catch(r){return r instanceof _?l(r.sealed):c(u(r))}}async submit(e,n){if(e.jobType===t.bvn)return c(new f({fieldName:"jobType",reason:"BVN submission is not yet supported"}));const a=await this._compressed(e,n);try{return l(await UseSmileIDRepositoryImpl._send(this._api,a))}catch(s){return c(u(s))}}async _compressed(e,n){try{const a=await this._compressPayload(e,n),s=a?p(a):[];if(s.length>0)return{...e,metadata:e.metadata.withAdditionalEntries(s)}}catch{}return e}async _compressPayload(e,n){const a=JSON.stringify(e.metadata.toEntries()).length;switch(e.jobType){case t.smartSelfieEnrollment:case t.smartSelfieAuthentication:case t.biometricKyc:return m.compress({selfieImage:e.selfieImage,livenessImages:e.livenessImages,metadataBytes:a,sdkConfig:n});case t.documentVerification:case t.enhancedDocumentVerification:return m.compress({selfieImage:e.selfieImage,livenessImages:e.livenessImages,frontDocument:e.frontDocument,backDocument:e.backDocument,metadataBytes:a,sdkConfig:n});case t.residencyDocumentVerification:return m.compress({selfieImage:e.selfieImage,livenessImages:e.livenessImages,frontDocument:e.frontDocument,visaDocument:e.visaDocument,metadataBytes:a,sdkConfig:n});default:return}}static _send(e,n){switch(n.jobType){case t.smartSelfieEnrollment:return e.smartSelfieEnrollment(n);case t.smartSelfieAuthentication:return e.smartSelfieAuthentication(n);case t.enhancedKyc:return e.enhancedKyc(n);case t.biometricKyc:return e.biometricKyc(n);case t.documentVerification:return e.documentVerification(n);case t.enhancedDocumentVerification:return e.enhancedDocumentVerification(n);case t.residencyDocumentVerification:return e.residencyDocumentVerification(n)}}}function u(i){return i instanceof d?i:new o({message:i instanceof Error?i.message:String(i),cause:i})}
1
+ "use strict";import{failure as c,success as l}from"../../core/models/result";import{JobType as i}from"../../core/models/job_type";import{InvalidFieldValueException as m}from"../../core/exception/job_validation_exceptions";import{UseSmileIDException as d}from"../../core/exception/use_smile_id_exception";import{NetworkUnknownException as u}from"../../core/exception/use_smile_id_network_exception";import{PayloadCompressionRunner as s}from"../compression/payload_compression_runner";import{BridgeSealed as p}from"../api/bridge_submissions";function _(t){const e=[],n=(a,o)=>{o!==void 0&&o>0&&e.push({name:a,value:String(o)})};return n("selfie_original_size",t.selfieOriginalMb),n("selfie_final_compressed_size",t.selfieFinalMb),n("document_front_original_size",t.frontOriginalMb),n("document_front_final_compressed_size",t.frontFinalMb),n("document_back_original_size",t.backOriginalMb),n("document_back_final_compressed_size",t.backFinalMb),n("document_visa_original_size",t.visaOriginalMb),n("document_visa_final_compressed_size",t.visaFinalMb),e}export class UseSmileIDRepositoryImpl{_api;_captureApi;constructor(e,n){this._api=e,this._captureApi=n}async seal(e,n){if(e.jobType===i.bvn)return c(new m({fieldName:"jobType",reason:"BVN submission is not yet supported"}));const a=this._captureApi;if(!a)return c(new u({message:"No capture client to seal the request through"}));const o=await this._compressed(e,n);try{return await UseSmileIDRepositoryImpl._send(a,o),c(new u({message:"The capture client sent the request instead of sealing it"}))}catch(r){return r instanceof p?l(r.sealed):c(f(r))}}async submit(e,n){if(e.jobType===i.bvn)return c(new m({fieldName:"jobType",reason:"BVN submission is not yet supported"}));if(e.jobType===i.unknownProduct)return c(new m({fieldName:"jobType",reason:"an unknown product is only sealed, never submitted"}));const a=await this._compressed(e,n);try{return l(await UseSmileIDRepositoryImpl._send(this._api,a))}catch(o){return c(f(o))}}async _compressed(e,n){try{const a=await this._compressPayload(e,n),o=a?_(a):[];if(o.length>0)return{...e,metadata:e.metadata.withAdditionalEntries(o)}}catch{}return e}async _compressPayload(e,n){const a=JSON.stringify(e.metadata.toEntries()).length;switch(e.jobType){case i.smartSelfieEnrollment:case i.smartSelfieAuthentication:case i.biometricKyc:return s.compress({selfieImage:e.selfieImage,livenessImages:e.livenessImages,metadataBytes:a,sdkConfig:n});case i.documentVerification:case i.enhancedDocumentVerification:return s.compress({selfieImage:e.selfieImage,livenessImages:e.livenessImages,frontDocument:e.frontDocument,backDocument:e.backDocument,metadataBytes:a,sdkConfig:n});case i.residencyDocumentVerification:return s.compress({selfieImage:e.selfieImage,livenessImages:e.livenessImages,frontDocument:e.frontDocument,visaDocument:e.visaDocument,metadataBytes:a,sdkConfig:n});case i.unknownProduct:return s.compress({selfieImage:e.selfieImage,livenessImages:e.livenessImages,frontDocument:e.frontDocument,backDocument:e.backDocument,metadataBytes:a,sdkConfig:n});default:return}}static _send(e,n){switch(n.jobType){case i.smartSelfieEnrollment:return e.smartSelfieEnrollment(n);case i.smartSelfieAuthentication:return e.smartSelfieAuthentication(n);case i.enhancedKyc:return e.enhancedKyc(n);case i.biometricKyc:return e.biometricKyc(n);case i.documentVerification:return e.documentVerification(n);case i.enhancedDocumentVerification:return e.enhancedDocumentVerification(n);case i.residencyDocumentVerification:return e.residencyDocumentVerification(n);case i.unknownProduct:return e.unknownProduct(n)}}}function f(t){return t instanceof d?t:new u({message:t instanceof Error?t.message:String(t),cause:t})}
@@ -1 +1 @@
1
- "use strict";import{EMPTY_CONSENT as I}from"../../core/models/params";import{JobType as c}from"../../core/models/job_type";import{MissingJobTypeException as w,MissingRequiredFieldException as r}from"../../core/exception/job_validation_exceptions";import{InvalidFieldValueException as E}from"../../core/exception/invalid_field_value_exception";import{configurationMetadataEntries as C}from"../../metadata/metadata_configuration_mappers";import{numSamplesOverride as N}from"../../data/model/sdk_config";import{bindsUserDetails as k,isIdFieldBoundByToken as S,isTokenConsentComplete as V}from"../../data/model/token_payload";import{isUserDetailsPayloadEmpty as _,userDetailsPayloadFrom as L}from"../../data/model/user_details_payload";import{EnhancedSmartSelfieConfig as x,FaceCaptureDefaults as j}from"@smileid/usesmileid_bridge";import{captureTelemetryEntries as F,documentImageOriginEntries as K}from"./flow_navigation_manager_analytics";const A=Object.freeze({granted:!1,grantedAt:"",noticeLanguage:"",noticePrivacyPolicyUrl:""});export function assembleJob(e){const n=e._configuration,s=n.network?.config?.jobType??c.unknown,d=V(e._resolvedTokenPayload?.consent)?void 0:e._captured.consentInformation??n.consentInformation??(n.config?.skipApiSubmission===!0?I:A),f=d!==void 0?{consent:d}:{},D=e._metadataProvider.make(e.resolvedSdkConfig),b=[...K(e),...F(e),...C(n)],l=D.withAdditionalEntries(b);switch(s){case c.smartSelfieEnrollment:{const t=p(e),i=m(e,n);return{jobType:c.smartSelfieEnrollment,selfieImage:t.selfiePath,livenessImages:t.livenessPaths,...i!==void 0?{userDetails:i}:{},...f,metadata:l,enhanced:!1,expectedLivenessImageCount:y(e)}}case c.smartSelfieAuthentication:{const t=p(e),i=m(e,n),o=U(e,n);return{jobType:c.smartSelfieAuthentication,selfieImage:t.selfiePath,livenessImages:t.livenessPaths,...i!==void 0?{userDetails:i}:{},userId:o,...f,metadata:l,enhanced:!1,expectedLivenessImageCount:y(e)}}case c.biometricKyc:{const t=p(e),i=n.biometricKYCParams;if(!i)throw new r({fieldName:"biometricKYCParams"});const o=m(e,n);return{jobType:c.biometricKyc,selfieImage:t.selfiePath,livenessImages:t.livenessPaths,params:{...i,...v(e,i)},...o!==void 0?{userDetails:o}:{},...f,metadata:l,expectedLivenessImageCount:y(e)}}case c.documentVerification:{const t=p(e),i=h(e),o=n.documentVerificationParams;if(!o)throw new r({fieldName:"documentVerificationParams"});const a=m(e,n);return{jobType:c.documentVerification,...P(e,t,i),country:u(e,o.country,"country"),...o.idType?{idType:u(e,o.idType,"idType")}:{},...a!==void 0?{userDetails:a}:{},...f,metadata:l,expectedLivenessImageCount:y(e)}}case c.enhancedDocumentVerification:{const t=p(e),i=h(e),o=n.enhancedDocumentVerificationParams;if(!o)throw new r({fieldName:"enhancedDocumentVerificationParams"});const a=m(e,n);return{jobType:c.enhancedDocumentVerification,...P(e,t,i),country:u(e,o.country,"country"),idType:u(e,o.idType,"idType"),...a!==void 0?{userDetails:a}:{},...f,metadata:l,expectedLivenessImageCount:y(e)}}case c.residencyDocumentVerification:{const t=p(e),i=h(e),o=n.residencyDocumentVerificationParams;if(!o)throw new r({fieldName:"residencyDocumentVerificationParams"});const a=M(e);if(!a)throw new r({fieldName:"visaDocument"});const T=m(e,n);return{jobType:c.residencyDocumentVerification,selfieImage:t.selfiePath,livenessImages:t.livenessPaths,frontDocument:i,visaDocument:a,country:u(e,o.country,"country"),idType:u(e,o.idType,"idType"),...T!==void 0?{userDetails:T}:{},...f,metadata:l,expectedLivenessImageCount:y(e)}}case c.enhancedKyc:{const t=n.enhancedKYCParams;if(!t)throw new r({fieldName:"enhancedKYCParams"});const i=m(e,n);return{jobType:c.enhancedKyc,params:{...t,...v(e,t)},...i!==void 0?{userDetails:i}:{},...f,metadata:l}}case c.bvn:throw new E({fieldName:"jobType",reason:"BVN submission is not yet supported"});case c.unknown:default:throw new w}}function p(e){const{selfiePath:n,livenessPaths:s}=e._captured;if(!n)throw new r({fieldName:"selfieImage"});return{selfiePath:n,livenessPaths:s}}function u(e,n,s){if(S(e._resolvedTokenPayload,s))return"";if(!n.trim())throw new r({fieldName:s});return n}function v(e,n){return{idType:u(e,n.idType,"idType"),idNumber:u(e,n.idNumber,"idNumber"),country:u(e,n.country,"country")}}function m(e,n){const s=e._resolvedTokenPayload,d=n.userDetails?L(n.userDetails,s):void 0;return d&&!_(d)?d:k(s)?void 0:{}}function U(e,n){const s=n.userId?.trim();if(!s)throw new r({fieldName:"userId"});return s}function h(e){const{frontDocumentPath:n}=e._captured;if(!n)throw new r({fieldName:"frontDocument"});return n}function P(e,n,s){const{backDocumentPath:d}=e._captured;return{selfieImage:n.selfiePath,livenessImages:n.livenessPaths,frontDocument:s,...d?{backDocument:d}:{}}}function M(e){return e._captured.visaDocumentPath}function y(e){if(e.enhancedLivenessEnabled)return x.EXPECTED_LIVENESS_IMAGE_COUNT;const s=N(e.resolvedSdkConfig);return s!==void 0?s-1:j.numSamples-1}
1
+ "use strict";import{EMPTY_CONSENT as I}from"../../core/models/params";import{JobType as o}from"../../core/models/job_type";import{MissingJobTypeException as w,MissingRequiredFieldException as u}from"../../core/exception/job_validation_exceptions";import{InvalidFieldValueException as E}from"../../core/exception/invalid_field_value_exception";import{configurationMetadataEntries as C}from"../../metadata/metadata_configuration_mappers";import{numSamplesOverride as k}from"../../data/model/sdk_config";import{bindsUserDetails as N,isIdFieldBoundByToken as S,isTokenConsentComplete as V}from"../../data/model/token_payload";import{isUserDetailsPayloadEmpty as _,userDetailsPayloadFrom as L}from"../../data/model/user_details_payload";import{EnhancedSmartSelfieConfig as x,FaceCaptureDefaults as j}from"@smileid/usesmileid_bridge";import{captureTelemetryEntries as F,documentImageOriginEntries as K}from"./flow_navigation_manager_analytics";const A=Object.freeze({granted:!1,grantedAt:"",noticeLanguage:"",noticePrivacyPolicyUrl:""});export function assembleJob(e){const t=e._configuration,c=t.network?.config?.jobType??o.unknown,d=V(e._resolvedTokenPayload?.consent)?void 0:e._captured.consentInformation??t.consentInformation??(t.config?.skipApiSubmission===!0?I:A),f=d!==void 0?{consent:d}:{},D=e._metadataProvider.make(e.resolvedSdkConfig),b=[...K(e),...F(e),...C(t)],l=D.withAdditionalEntries(b);switch(c){case o.smartSelfieEnrollment:{const n=y(e),i=m(e,t);return{jobType:o.smartSelfieEnrollment,selfieImage:n.selfiePath,livenessImages:n.livenessPaths,...i!==void 0?{userDetails:i}:{},...f,metadata:l,enhanced:!1,expectedLivenessImageCount:p(e)}}case o.smartSelfieAuthentication:{const n=y(e),i=m(e,t),s=U(e,t);return{jobType:o.smartSelfieAuthentication,selfieImage:n.selfiePath,livenessImages:n.livenessPaths,...i!==void 0?{userDetails:i}:{},userId:s,...f,metadata:l,enhanced:!1,expectedLivenessImageCount:p(e)}}case o.biometricKyc:{const n=y(e),i=t.biometricKYCParams;if(!i)throw new u({fieldName:"biometricKYCParams"});const s=m(e,t);return{jobType:o.biometricKyc,selfieImage:n.selfiePath,livenessImages:n.livenessPaths,params:{...i,...T(e,i)},...s!==void 0?{userDetails:s}:{},...f,metadata:l,expectedLivenessImageCount:p(e)}}case o.documentVerification:{const n=y(e),i=P(e),s=t.documentVerificationParams;if(!s)throw new u({fieldName:"documentVerificationParams"});const r=m(e,t);return{jobType:o.documentVerification,...v(e,n,i),country:a(e,s.country,"country"),...s.idType?{idType:a(e,s.idType,"idType")}:{},...r!==void 0?{userDetails:r}:{},...f,metadata:l,expectedLivenessImageCount:p(e)}}case o.enhancedDocumentVerification:{const n=y(e),i=P(e),s=t.enhancedDocumentVerificationParams;if(!s)throw new u({fieldName:"enhancedDocumentVerificationParams"});const r=m(e,t);return{jobType:o.enhancedDocumentVerification,...v(e,n,i),country:a(e,s.country,"country"),idType:a(e,s.idType,"idType"),...r!==void 0?{userDetails:r}:{},...f,metadata:l,expectedLivenessImageCount:p(e)}}case o.residencyDocumentVerification:{const n=y(e),i=P(e),s=t.residencyDocumentVerificationParams;if(!s)throw new u({fieldName:"residencyDocumentVerificationParams"});const r=M(e);if(!r)throw new u({fieldName:"visaDocument"});const h=m(e,t);return{jobType:o.residencyDocumentVerification,selfieImage:n.selfiePath,livenessImages:n.livenessPaths,frontDocument:i,visaDocument:r,country:a(e,s.country,"country"),idType:a(e,s.idType,"idType"),...h!==void 0?{userDetails:h}:{},...f,metadata:l,expectedLivenessImageCount:p(e)}}case o.enhancedKyc:{const n=t.enhancedKYCParams;if(!n)throw new u({fieldName:"enhancedKYCParams"});const i=m(e,t);return{jobType:o.enhancedKyc,params:{...n,...T(e,n)},...i!==void 0?{userDetails:i}:{},...f,metadata:l}}case o.unknownProduct:{const{selfiePath:n,livenessPaths:i,frontDocumentPath:s,backDocumentPath:r}=e._captured,h=m(e,t);return{jobType:o.unknownProduct,...n?{selfieImage:n}:{},livenessImages:n?i:[],...s?{frontDocument:s}:{},...r?{backDocument:r}:{},...h!==void 0?{userDetails:h}:{},...f,metadata:l,...n?{expectedLivenessImageCount:p(e)}:{}}}case o.bvn:throw new E({fieldName:"jobType",reason:"BVN submission is not yet supported"});case o.unknown:default:throw new w}}function y(e){const{selfiePath:t,livenessPaths:c}=e._captured;if(!t)throw new u({fieldName:"selfieImage"});return{selfiePath:t,livenessPaths:c}}function a(e,t,c){if(S(e._resolvedTokenPayload,c))return"";if(!t.trim())throw new u({fieldName:c});return t}function T(e,t){return{idType:a(e,t.idType,"idType"),idNumber:a(e,t.idNumber,"idNumber"),country:a(e,t.country,"country")}}function m(e,t){const c=e._resolvedTokenPayload,d=t.userDetails?L(t.userDetails,c):void 0;return d&&!_(d)?d:N(c)?void 0:{}}function U(e,t){const c=t.userId?.trim();if(!c)throw new u({fieldName:"userId"});return c}function P(e){const{frontDocumentPath:t}=e._captured;if(!t)throw new u({fieldName:"frontDocument"});return t}function v(e,t,c){const{backDocumentPath:d}=e._captured;return{selfieImage:t.selfiePath,livenessImages:t.livenessPaths,frontDocument:c,...d?{backDocument:d}:{}}}function M(e){return e._captured.visaDocumentPath}function p(e){if(e.enhancedLivenessEnabled)return x.EXPECTED_LIVENESS_IMAGE_COUNT;const c=k(e.resolvedSdkConfig);return c!==void 0?c-1:j.numSamples-1}
@@ -1 +1 @@
1
- "use strict";import{jsx as t}from"react/jsx-runtime";import{useEffect as a}from"react";import{DocumentSide as d}from"@smileid/usesmileid_bridge";import{UseSmileIDProcessingScreen as m}from"../../screen/use_smile_id_processing_screen";import{flowShowAttribution as f}from"../config/attribution_resolver";import{UseSmileIDOrchestratedScreenHost as p}from"./use_smile_id_orchestrated_screen_host";import{ProcessingCancelledException as g,UseSmileIDException as l}from"../../../core/exception";import{alwaysEnabledSlot as i}from"./helpers/always_enabled_slot";import{resolveFailureMessage as S}from"./use_smile_id_error_code_failure_message";import{useUseSmileIDLocalizations as b}from"../../../l10n/use_smile_id_localizations_provider";import{JobType as P,requiresDocument as c,requiresSelfie as h}from"../../../core/models/job_type";export function OrchestratedProcessingScreen({configuration:n}){return t(p,{content:({navigationManager:e,onNavigateNext:o})=>t(y,{processingConfig:n,navigationManager:e,onContinue:o})})}function y(n){const{navigationManager:e}=n;a(()=>{e.beginSubmissionIfNeeded()},[e]);const o=e.configuration.network?.config?.jobType??P.unknown,r=c(o)?e.captured.frontDocumentPath:void 0,s=e.documentFrameAspectRatio,u=b();return t(m,{state:x(e.jobSubmissionState,u),showFaceOval:h(o)||c(o),...e.selfieCaptureGeometry?{selfieCaptureGeometry:e.selfieCaptureGeometry}:{},showProgressPercentage:n.processingConfig.showProgressPercentage,showAttribution:f(e.configuration),...r!==void 0?{documentImageUri:r,documentBorderFraction:e.documentBorderFraction(d.Front)}:{},...r!==void 0&&s!==void 0?{documentAspectRatio:s}:{},...e.captured.selfiePath!==void 0?{capturedSelfiePath:e.captured.selfiePath}:{},...w(n.processingConfig),onContinue:n.onContinue,onRetry:()=>e.retrySubmission(),onExit:()=>e.exit({kind:"failed",error:C(e.jobSubmissionState)})})}function w(n){const e=i(n.continueButton),o=i(n.retryButton),r=i(n.exitButton);return{...e!==void 0?{continueButton:e}:{},...o!==void 0?{retryButton:o}:{},...r!==void 0?{exitButton:r}:{}}}function C(n){return n.kind==="failure"?n.error:new g}function x(n,e){switch(n.kind){case"notAttempted":case"loading":case"skipped":return{kind:"loading"};case"success":return{kind:"success",message:n.response.message};case"failure":return{kind:"failed",errorMessage:S(n.error instanceof l?n.error.errorCode:void 0,e)}}}
1
+ "use strict";import{jsx as i}from"react/jsx-runtime";import{useEffect as f}from"react";import{DocumentSide as m}from"@smileid/usesmileid_bridge";import{UseSmileIDProcessingScreen as p}from"../../screen/use_smile_id_processing_screen";import{flowShowAttribution as l}from"../config/attribution_resolver";import{UseSmileIDOrchestratedScreenHost as g}from"./use_smile_id_orchestrated_screen_host";import{ProcessingCancelledException as S,UseSmileIDException as h}from"../../../core/exception";import{alwaysEnabledSlot as s}from"./helpers/always_enabled_slot";import{resolveFailureMessage as P}from"./use_smile_id_error_code_failure_message";import{useUseSmileIDLocalizations as b}from"../../../l10n/use_smile_id_localizations_provider";import{JobType as c,requiresDocument as a,requiresSelfie as w}from"../../../core/models/job_type";export function OrchestratedProcessingScreen({configuration:n}){return i(g,{content:({navigationManager:e,onNavigateNext:o})=>i(y,{processingConfig:n,navigationManager:e,onContinue:o})})}function y(n){const{navigationManager:e}=n;f(()=>{e.beginSubmissionIfNeeded()},[e]);const o=e.configuration.network?.config?.jobType??c.unknown,t=o===c.unknownProduct,r=a(o)||t?e.captured.frontDocumentPath:void 0,u=e.documentFrameAspectRatio,d=b();return i(p,{state:x(e.jobSubmissionState,d),showFaceOval:w(o)||a(o)||t&&(e.captured.selfiePath!==void 0||e.captured.frontDocumentPath!==void 0),...e.selfieCaptureGeometry?{selfieCaptureGeometry:e.selfieCaptureGeometry}:{},showProgressPercentage:n.processingConfig.showProgressPercentage,showAttribution:l(e.configuration),...r!==void 0?{documentImageUri:r,documentBorderFraction:e.documentBorderFraction(m.Front)}:{},...r!==void 0&&u!==void 0?{documentAspectRatio:u}:{},...e.captured.selfiePath!==void 0?{capturedSelfiePath:e.captured.selfiePath}:{},...C(n.processingConfig),onContinue:n.onContinue,onRetry:()=>e.retrySubmission(),onExit:()=>e.exit({kind:"failed",error:k(e.jobSubmissionState)})})}function C(n){const e=s(n.continueButton),o=s(n.retryButton),t=s(n.exitButton);return{...e!==void 0?{continueButton:e}:{},...o!==void 0?{retryButton:o}:{},...t!==void 0?{exitButton:t}:{}}}function k(n){return n.kind==="failure"?n.error:new S}function x(n,e){switch(n.kind){case"notAttempted":case"loading":case"skipped":return{kind:"loading"};case"success":return{kind:"success",message:n.response.message};case"failure":return{kind:"failed",errorMessage:P(n.error instanceof h?n.error.errorCode:void 0,e)}}}
@@ -105,6 +105,19 @@ export declare class NonCaptureJobTypeValidator implements JobTypeValidator {
105
105
  constructor(jobType: JobType);
106
106
  validate(input: JobTypeValidatorInput, issues: ValidationIssue[]): void;
107
107
  }
108
+ /**
109
+ * Validates `JobType.unknownProduct` flows, which capture whatever their
110
+ * screens configure for the partner's backend to forward, so none of a
111
+ * product's rules apply. What holds is what every flow needs: the structural
112
+ * rules with each preview after its own capture, at least one capture and at
113
+ * most one of each type (the job hands back what it captured, one selfie and
114
+ * one document at most), a processing screen, a face analyzer for a selfie,
115
+ * and `skipApiSubmission`, since Smile ID has no endpoint to submit the job
116
+ * to.
117
+ */
118
+ export declare class UnknownProductJobTypeValidator implements JobTypeValidator {
119
+ validate(input: JobTypeValidatorInput, issues: ValidationIssue[]): void;
120
+ }
108
121
  /**
109
122
  * Validates a flow whose `JobType` doesn't resolve. It is always invalid,
110
123
  * and still gets the structural rules and the missing-block warnings, so a
@@ -1 +1 @@
1
- "use strict";import{RESIDENCY_ID_TYPE as y}from"../../../core/models/params";import{JobType as t}from"../../../core/models/job_type";import{InvalidJobTypeScreenConfigException as a,MissingJobTypeException as V,MissingMLConfigurationBlockException as E,MissingNetworkConfigurationBlockException as D}from"../../../core/exception/job_validation_exceptions";import{JOB_PARAMS_OWNERS as P,UnusedJobParamsException as v}from"../../../core/exception/unused_job_params_exception";import{DuplicateScreenTypeException as J,InvalidScreenOrderException as p,MissingCaptureForPreviewException as I}from"../../../core/exception/screen_config_validation_exceptions";import{IssueSeverity as u}from"../../../core/exception/issue_severity";import{isIdFieldBoundByToken as F,tokenConsentMissingSubfields as K}from"../../../data/model/token_payload";import{hasCaptureScreen as g,hasConsentScreen as R,hasDocumentCaptureScreen as A,hasProcessingScreen as w,resolveDocumentCaptures as B,resolveSdkScreens as j,resolveSelfieCaptures as M}from"../config/flow_configuration_screens";const N=new Map([[t.biometricKyc,"BiometricKyc"],[t.smartSelfieAuthentication,"SmartSelfieAuthentication"],[t.smartSelfieEnrollment,"SmartSelfieEnrollment"],[t.enhancedKyc,"EnhancedKyc"],[t.documentVerification,"DocumentVerification"],[t.bvn,"BVN"],[t.enhancedDocumentVerification,"EnhancedDocumentVerification"],[t.residencyDocumentVerification,"ResidencyDocumentVerification"],[t.unknown,"Unknown"]]);function S(o){return N.get(o)??"Unknown"}function h(o,e,n){const i=e.consentInformation!==void 0,r=e.tokenPayload?.consent;if(r!==void 0){const c=K(r);c.length>0&&n.push(a.forJob({jobType:o,reason:`the token's consent binding is incomplete \u2014 missing: ${c.join(", ")}`,suggestedFix:"Bind all four consent fields when minting the token at /v3/token, or bind none and collect consent in the app"}));return}e.skipApiSubmission!==!0&&!R(e.steps)&&!i&&n.push(a.forJob({jobType:o,reason:"must include either a Consent screen or a pre-supplied consentInformation",suggestedFix:"Add a consent { } screen to your flow, or supply consentInformation via the builder"}))}export const JOB_PARAMS_SUPPLIERS={enhancedKYCParams:o=>o.enhancedKYCParams,biometricKYCParams:o=>o.biometricKYCParams,documentVerificationParams:o=>o.documentVerificationParams,enhancedDocumentVerificationParams:o=>o.enhancedDocumentVerificationParams,residencyDocumentVerificationParams:o=>o.residencyDocumentVerificationParams};function b(o,e,n){for(const{fieldName:i,owner:r}of P)r!==o&&JOB_PARAMS_SUPPLIERS[i]?.(e)!==void 0&&n.push(new v({jobType:o,fieldName:i}))}function f(o,e){const n=new Map;let i=0;o.forEach((r,c)=>{if(r.kind==="capture"){i++;return}if(r.kind==="preview"||r.kind==="partner")return;const s=r.kind==="instructions"?`${r.kind}:${i}`:r.kind,d=n.get(s)??{kind:r.kind,indices:[]};d.indices.push(c),n.set(s,d)});for(const{kind:r,indices:c}of n.values())c.length>1&&e.push(new J({screenType:r,indices:c}))}function m(o,e){j(o).findIndex(c=>c.kind==="consent")>0&&e.push(new p({description:"Consent screen must be the first screen in the flow",severity:u.error}));const i=o.findIndex(c=>c.kind==="processing");i!==-1&&i!==o.length-1&&e.push(new p({description:"Processing screen must be the last screen in the flow",severity:u.error}));const r=g(o);o.forEach((c,s)=>{const d=o[s+1]?.kind;c.kind==="instructions"&&r&&d!=="capture"&&d!=="instructions"&&e.push(new p({description:`Instructions screen at index ${s} must be followed by a Capture screen`,severity:u.error}))})}function l(o,e,n){let i=!1,r=0;o.forEach((c,s)=>{c.kind==="capture"?i=!0:c.kind==="preview"&&(r+=1,i?r>e&&n.push(new p({description:`Preview screen at index ${s} exceeds the maximum of ${e} preview screen(s) allowed for this flow`,severity:u.error})):n.push(new I({previewIndex:s})))})}function T(o,e,n){w(e.steps)||n.push(a.forJob({jobType:o,reason:"must include a Processing screen",suggestedFix:"Add a processing { } screen as the last screen in the flow"}))}function k(o,e,n){const i=M(e.steps);i.length===0?n.push(a.forJob({jobType:o,reason:"must include exactly one Capture screen with captureType = SELFIE",suggestedFix:"Add a capture { captureType = CaptureType.SELFIE } screen to your flow"})):i.length>1&&n.push(a.forJob({jobType:o,reason:`must include exactly one Capture screen with captureType = SELFIE, but found ${i.length}`,suggestedFix:"Remove the extra selfie capture screens \u2014 only one is allowed"}))}function C(o,e,n,i){e.ml?e.ml.analyzers.selfie||i.push(a.forJob({jobType:o,reason:"ml { } block must register analyzers for CaptureType.SELFIE",suggestedFix:"Add forCaptureType(CaptureType.SELFIE) { } inside the ml { } block"})):i.push(a.forJob({jobType:o,reason:"ml { } block is required and must register analyzers for CaptureType.SELFIE",suggestedFix:n}))}export class SelfieJobTypeValidator{jobType;constructor(e){this.jobType=e}validate(e,n){f(e.steps,n),m(e.steps,n),l(e.steps,1,n),h(this.jobType,e,n),b(this.jobType,e,n),k(this.jobType,e,n),A(e.steps)&&n.push(a.forJob({jobType:this.jobType,reason:"must not include a Document capture screen",suggestedFix:`Remove the Document capture screen \u2014 ${S(this.jobType)} requires selfie capture only`})),T(this.jobType,e,n),C(this.jobType,e,"Add the ml { } block with forCaptureType(CaptureType.SELFIE) { } inside",n),e.ml?.analyzers.document&&n.push(a.forJob({jobType:this.jobType,reason:"ml { } block must not register analyzers for CaptureType.DOCUMENT",suggestedFix:`Remove forCaptureType(CaptureType.DOCUMENT) { } from the ml { } block \u2014 ${S(this.jobType)} does not use document capture`})),this.jobType===t.biometricKyc&&e.biometricKYCParams===void 0&&n.push(a.forJob({jobType:this.jobType,reason:"biometricKYCParams is required for BiometricKyc jobs",suggestedFix:"Set builder.biometricKYCParams with the identity fields before building"})),this.jobType===t.smartSelfieAuthentication&&(e.userId===void 0||e.userId.trim()==="")&&n.push(a.forJob({jobType:this.jobType,reason:"userId is required for SmartSelfieAuthentication jobs",suggestedFix:"Set builder.userId with the identifier returned by a prior Smart Selfie Enrollment before building"}))}}export class DocumentJobTypeValidator{jobType;constructor(e){this.jobType=e}validate(e,n){f(e.steps,n),m(e.steps,n),l(e.steps,2,n),h(this.jobType,e,n),b(this.jobType,e,n),k(this.jobType,e,n);const i=B(e.steps);if(i.length===0?n.push(a.forJob({jobType:this.jobType,reason:"must include exactly one Capture screen with captureType = DOCUMENT",suggestedFix:"Add a capture { captureType = CaptureType.DOCUMENT } screen to your flow"})):i.length>1&&n.push(a.forJob({jobType:this.jobType,reason:`must include exactly one Capture screen with captureType = DOCUMENT, but found ${i.length}`,suggestedFix:"Remove the extra document capture screens \u2014 only one is allowed"})),T(this.jobType,e,n),C(this.jobType,e,"Add the ml { } block with forCaptureType(CaptureType.SELFIE) { } inside \u2014 document capture uses NoopDocumentDetectorAnalyzer by default",n),this.appendParamsRule(e,n),this.jobType===t.enhancedDocumentVerification&&i.some(r=>r.documentConfig?.documentType?.kind==="southAfricaGreenBook")&&n.push(a.forJob({jobType:this.jobType,reason:"South Africa Green Book is not supported for Enhanced Document Verification",suggestedFix:"Use JobType.documentVerification for the Green Book, or choose a supported document type for Enhanced Document Verification"})),this.jobType===t.residencyDocumentVerification)for(const r of i){const c=r.documentConfig,s=c?.documentType;s?.kind!=="passport"&&n.push(a.forJob({jobType:this.jobType,reason:`documentType must be passport \u2014 ${s?.kind??"no document type"} is not a residency primary document`,suggestedFix:"Set documentType to the passport preset on the document capture screen"})),c&&c.allowSkipBack===!0&&n.push(a.forJob({jobType:this.jobType,reason:"allowSkipBack must be false \u2014 the visa capture is mandatory",suggestedFix:"Remove allowSkipBack from the document capture screen"}))}}appendParamsRule(e,n){this.jobType===t.documentVerification&&e.documentVerificationParams===void 0&&n.push(a.forJob({jobType:this.jobType,reason:"documentVerificationParams is required for DocumentVerification jobs",suggestedFix:"Set builder.documentVerificationParams with the country (and optional idType) before building"})),this.jobType===t.enhancedDocumentVerification&&e.enhancedDocumentVerificationParams===void 0&&n.push(a.forJob({jobType:this.jobType,reason:"enhancedDocumentVerificationParams is required for EnhancedDocumentVerification jobs",suggestedFix:"Set builder.enhancedDocumentVerificationParams with the country and idType before building"})),this.jobType===t.residencyDocumentVerification&&!F(e.tokenPayload,"idType")&&e.residencyDocumentVerificationParams!==void 0&&hasNonPassportIdType(e.residencyDocumentVerificationParams)&&n.push(residencyIdTypeIssue()),this.jobType===t.residencyDocumentVerification&&e.residencyDocumentVerificationParams===void 0&&n.push(a.forJob({jobType:this.jobType,reason:"residencyDocumentVerificationParams is required for ResidencyDocumentVerification jobs",suggestedFix:"Set builder.residencyDocumentVerificationParams with the country and idType before building"}))}}export class NonCaptureJobTypeValidator{jobType;constructor(e){this.jobType=e}validate(e,n){f(e.steps,n),m(e.steps,n),l(e.steps,0,n),h(this.jobType,e,n),b(this.jobType,e,n),T(this.jobType,e,n);const i=j(e.steps).filter(r=>r.kind!=="consent"&&r.kind!=="processing");if(i.length>0){const r=[...new Set(i.map(c=>c.kind))].join(", ");n.push(a.forJob({jobType:this.jobType,reason:`must only contain consent and processing screens, but found: ${r}`,suggestedFix:"Remove all screens except consent { } and processing { } from your flow"}))}this.jobType===t.enhancedKyc&&e.enhancedKYCParams===void 0&&n.push(a.forJob({jobType:this.jobType,reason:"enhancedKYCParams is required for EnhancedKyc jobs",suggestedFix:"Set builder.enhancedKYCParams with the identity fields before building"}))}}export class UnknownJobTypeValidator{validate(e,n){f(e.steps,n),m(e.steps,n),l(e.steps,2,n),g(e.steps)&&!e.ml&&n.push(new E),w(e.steps)&&!e.network&&n.push(new D),n.push(new V)}}export const jobTypeValidators=new Map([[t.biometricKyc,new SelfieJobTypeValidator(t.biometricKyc)],[t.smartSelfieAuthentication,new SelfieJobTypeValidator(t.smartSelfieAuthentication)],[t.smartSelfieEnrollment,new SelfieJobTypeValidator(t.smartSelfieEnrollment)],[t.documentVerification,new DocumentJobTypeValidator(t.documentVerification)],[t.enhancedDocumentVerification,new DocumentJobTypeValidator(t.enhancedDocumentVerification)],[t.residencyDocumentVerification,new DocumentJobTypeValidator(t.residencyDocumentVerification)],[t.enhancedKyc,new NonCaptureJobTypeValidator(t.enhancedKyc)],[t.bvn,new NonCaptureJobTypeValidator(t.bvn)]]);const x=new UnknownJobTypeValidator;export function resolveJobTypeValidator(o){return o===void 0?x:jobTypeValidators.get(o)??x}export function collectJobTypeIssues(o,e){const n=o.network?.config?.jobType;resolveJobTypeValidator(n).validate(o,e)}export function residencyIdTypeIssue(){return a.forJob({jobType:t.residencyDocumentVerification,reason:`idType must be "${y}" \u2014 the backend rejects any other value for this job type`,suggestedFix:`Set builder.residencyDocumentVerificationParams with idType: "${y}"`})}export function hasNonPassportIdType(o){return(o.idType?.trim()??"")!==""&&o.idType!==y}
1
+ "use strict";import{RESIDENCY_ID_TYPE as T}from"../../../core/models/params";import{JobType as a}from"../../../core/models/job_type";import{InvalidJobTypeScreenConfigException as s,MissingJobTypeException as V,MissingMLConfigurationBlockException as J,MissingNetworkConfigurationBlockException as F}from"../../../core/exception/job_validation_exceptions";import{jobTypeName as w}from"../../../core/exception/invalid_job_type_screen_config_exception";import{JOB_PARAMS_OWNERS as I,UnusedJobParamsException as A}from"../../../core/exception/unused_job_params_exception";import{DuplicateScreenTypeException as R,InvalidScreenOrderException as p,MissingCaptureForPreviewException as C}from"../../../core/exception/screen_config_validation_exceptions";import{IssueSeverity as u}from"../../../core/exception/issue_severity";import{isIdFieldBoundByToken as M,tokenConsentMissingSubfields as K}from"../../../data/model/token_payload";import{hasCaptureScreen as j,hasConsentScreen as B,hasDocumentCaptureScreen as $,hasProcessingScreen as k,resolveDocumentCaptures as S,resolveSdkScreens as x,resolveSelfieCaptures as P}from"../config/flow_configuration_screens";function m(n,e,o){const t=e.consentInformation!==void 0,r=e.tokenPayload?.consent;if(r!==void 0){const i=K(r);i.length>0&&o.push(s.forJob({jobType:n,reason:`the token's consent binding is incomplete \u2014 missing: ${i.join(", ")}`,suggestedFix:"Bind all four consent fields when minting the token at /v3/token, or bind none and collect consent in the app"}));return}e.skipApiSubmission!==!0&&!B(e.steps)&&!t&&o.push(s.forJob({jobType:n,reason:"must include either a Consent screen or a pre-supplied consentInformation",suggestedFix:"Add a consent { } screen to your flow, or supply consentInformation via the builder"}))}export const JOB_PARAMS_SUPPLIERS={enhancedKYCParams:n=>n.enhancedKYCParams,biometricKYCParams:n=>n.biometricKYCParams,documentVerificationParams:n=>n.documentVerificationParams,enhancedDocumentVerificationParams:n=>n.enhancedDocumentVerificationParams,residencyDocumentVerificationParams:n=>n.residencyDocumentVerificationParams};function h(n,e,o){for(const{fieldName:t,owner:r}of I)r!==n&&JOB_PARAMS_SUPPLIERS[t]?.(e)!==void 0&&o.push(new A({jobType:n,fieldName:t}))}function f(n,e){const o=new Map;let t=0;n.forEach((r,i)=>{if(r.kind==="capture"){t++;return}if(r.kind==="preview"||r.kind==="partner")return;const c=r.kind==="instructions"?`${r.kind}:${t}`:r.kind,d=o.get(c)??{kind:r.kind,indices:[]};d.indices.push(i),o.set(c,d)});for(const{kind:r,indices:i}of o.values())i.length>1&&e.push(new R({screenType:r,indices:i}))}function l(n,e){x(n).findIndex(i=>i.kind==="consent")>0&&e.push(new p({description:"Consent screen must be the first screen in the flow",severity:u.error}));const t=n.findIndex(i=>i.kind==="processing");t!==-1&&t!==n.length-1&&e.push(new p({description:"Processing screen must be the last screen in the flow",severity:u.error}));const r=j(n);n.forEach((i,c)=>{const d=n[c+1]?.kind;i.kind==="instructions"&&r&&d!=="capture"&&d!=="instructions"&&e.push(new p({description:`Instructions screen at index ${c} must be followed by a Capture screen`,severity:u.error}))})}function y(n,e,o){let t=!1,r=0;n.forEach((i,c)=>{i.kind==="capture"?t=!0:i.kind==="preview"&&(r+=1,t?r>e&&o.push(new p({description:`Preview screen at index ${c} exceeds the maximum of ${e} preview screen(s) allowed for this flow`,severity:u.error})):o.push(new C({previewIndex:c})))})}function b(n,e,o){k(e.steps)||o.push(s.forJob({jobType:n,reason:"must include a Processing screen",suggestedFix:"Add a processing { } screen as the last screen in the flow"}))}function E(n,e,o){const t=P(e.steps);t.length===0?o.push(s.forJob({jobType:n,reason:"must include exactly one Capture screen with captureType = SELFIE",suggestedFix:"Add a capture { captureType = CaptureType.SELFIE } screen to your flow"})):t.length>1&&o.push(s.forJob({jobType:n,reason:`must include exactly one Capture screen with captureType = SELFIE, but found ${t.length}`,suggestedFix:"Remove the extra selfie capture screens \u2014 only one is allowed"}))}function g(n,e,o,t){e.ml?e.ml.analyzers.selfie||t.push(s.forJob({jobType:n,reason:"ml { } block must register analyzers for CaptureType.SELFIE",suggestedFix:"Add forCaptureType(CaptureType.SELFIE) { } inside the ml { } block"})):t.push(s.forJob({jobType:n,reason:"ml { } block is required and must register analyzers for CaptureType.SELFIE",suggestedFix:o}))}export class SelfieJobTypeValidator{jobType;constructor(e){this.jobType=e}validate(e,o){f(e.steps,o),l(e.steps,o),y(e.steps,1,o),m(this.jobType,e,o),h(this.jobType,e,o),E(this.jobType,e,o),$(e.steps)&&o.push(s.forJob({jobType:this.jobType,reason:"must not include a Document capture screen",suggestedFix:`Remove the Document capture screen \u2014 ${w(this.jobType)} requires selfie capture only`})),b(this.jobType,e,o),g(this.jobType,e,"Add the ml { } block with forCaptureType(CaptureType.SELFIE) { } inside",o),e.ml?.analyzers.document&&o.push(s.forJob({jobType:this.jobType,reason:"ml { } block must not register analyzers for CaptureType.DOCUMENT",suggestedFix:`Remove forCaptureType(CaptureType.DOCUMENT) { } from the ml { } block \u2014 ${w(this.jobType)} does not use document capture`})),this.jobType===a.biometricKyc&&e.biometricKYCParams===void 0&&o.push(s.forJob({jobType:this.jobType,reason:"biometricKYCParams is required for BiometricKyc jobs",suggestedFix:"Set builder.biometricKYCParams with the identity fields before building"})),this.jobType===a.smartSelfieAuthentication&&(e.userId===void 0||e.userId.trim()==="")&&o.push(s.forJob({jobType:this.jobType,reason:"userId is required for SmartSelfieAuthentication jobs",suggestedFix:"Set builder.userId with the identifier returned by a prior Smart Selfie Enrollment before building"}))}}export class DocumentJobTypeValidator{jobType;constructor(e){this.jobType=e}validate(e,o){f(e.steps,o),l(e.steps,o),y(e.steps,2,o),m(this.jobType,e,o),h(this.jobType,e,o),E(this.jobType,e,o);const t=S(e.steps);if(t.length===0?o.push(s.forJob({jobType:this.jobType,reason:"must include exactly one Capture screen with captureType = DOCUMENT",suggestedFix:"Add a capture { captureType = CaptureType.DOCUMENT } screen to your flow"})):t.length>1&&o.push(s.forJob({jobType:this.jobType,reason:`must include exactly one Capture screen with captureType = DOCUMENT, but found ${t.length}`,suggestedFix:"Remove the extra document capture screens \u2014 only one is allowed"})),b(this.jobType,e,o),g(this.jobType,e,"Add the ml { } block with forCaptureType(CaptureType.SELFIE) { } inside \u2014 document capture uses NoopDocumentDetectorAnalyzer by default",o),this.appendParamsRule(e,o),this.jobType===a.enhancedDocumentVerification&&t.some(r=>r.documentConfig?.documentType?.kind==="southAfricaGreenBook")&&o.push(s.forJob({jobType:this.jobType,reason:"South Africa Green Book is not supported for Enhanced Document Verification",suggestedFix:"Use JobType.documentVerification for the Green Book, or choose a supported document type for Enhanced Document Verification"})),this.jobType===a.residencyDocumentVerification)for(const r of t){const i=r.documentConfig,c=i?.documentType;c?.kind!=="passport"&&o.push(s.forJob({jobType:this.jobType,reason:`documentType must be passport \u2014 ${c?.kind??"no document type"} is not a residency primary document`,suggestedFix:"Set documentType to the passport preset on the document capture screen"})),i&&i.allowSkipBack===!0&&o.push(s.forJob({jobType:this.jobType,reason:"allowSkipBack must be false \u2014 the visa capture is mandatory",suggestedFix:"Remove allowSkipBack from the document capture screen"}))}}appendParamsRule(e,o){this.jobType===a.documentVerification&&e.documentVerificationParams===void 0&&o.push(s.forJob({jobType:this.jobType,reason:"documentVerificationParams is required for DocumentVerification jobs",suggestedFix:"Set builder.documentVerificationParams with the country (and optional idType) before building"})),this.jobType===a.enhancedDocumentVerification&&e.enhancedDocumentVerificationParams===void 0&&o.push(s.forJob({jobType:this.jobType,reason:"enhancedDocumentVerificationParams is required for EnhancedDocumentVerification jobs",suggestedFix:"Set builder.enhancedDocumentVerificationParams with the country and idType before building"})),this.jobType===a.residencyDocumentVerification&&!M(e.tokenPayload,"idType")&&e.residencyDocumentVerificationParams!==void 0&&hasNonPassportIdType(e.residencyDocumentVerificationParams)&&o.push(residencyIdTypeIssue()),this.jobType===a.residencyDocumentVerification&&e.residencyDocumentVerificationParams===void 0&&o.push(s.forJob({jobType:this.jobType,reason:"residencyDocumentVerificationParams is required for ResidencyDocumentVerification jobs",suggestedFix:"Set builder.residencyDocumentVerificationParams with the country and idType before building"}))}}export class NonCaptureJobTypeValidator{jobType;constructor(e){this.jobType=e}validate(e,o){f(e.steps,o),l(e.steps,o),y(e.steps,0,o),m(this.jobType,e,o),h(this.jobType,e,o),b(this.jobType,e,o);const t=x(e.steps).filter(r=>r.kind!=="consent"&&r.kind!=="processing");if(t.length>0){const r=[...new Set(t.map(i=>i.kind))].join(", ");o.push(s.forJob({jobType:this.jobType,reason:`must only contain consent and processing screens, but found: ${r}`,suggestedFix:"Remove all screens except consent { } and processing { } from your flow"}))}this.jobType===a.enhancedKyc&&e.enhancedKYCParams===void 0&&o.push(s.forJob({jobType:this.jobType,reason:"enhancedKYCParams is required for EnhancedKyc jobs",suggestedFix:"Set builder.enhancedKYCParams with the identity fields before building"}))}}function N(n,e){let o=!1,t=!1;n.forEach((r,i)=>{r.kind==="capture"?(o=!0,t=!0):r.kind==="preview"&&(o?t||e.push(new p({description:`Preview screen at index ${i} must follow its own Capture screen`,severity:u.error})):e.push(new C({previewIndex:i})),t=!1)})}function D(n,e,o,t){o<=1||t.push(s.forJob({jobType:n,reason:`may include at most one Capture screen with captureType = ${e}, but found ${o}`,suggestedFix:`Remove the extra ${e.toLowerCase()} capture screens \u2014 only one is allowed`}))}export class UnknownProductJobTypeValidator{validate(e,o){const t=a.unknownProduct,r=P(e.steps),i=S(e.steps);f(e.steps,o),l(e.steps,o),N(e.steps,o),m(t,e,o),h(t,e,o),e.skipApiSubmission||o.push(s.forJob({jobType:t,reason:"requires skipApiSubmission = true \u2014 the job is handed back for your backend to forward, never submitted",suggestedFix:"Set config { skipApiSubmission = true }, or set the jobType of the product to submit"})),r.length===0&&i.length===0&&o.push(s.forJob({jobType:t,reason:"must include at least one Capture screen",suggestedFix:"Add a capture { captureType = CaptureType.SELFIE } or capture { captureType = CaptureType.DOCUMENT } screen to your flow"})),D(t,"SELFIE",r.length,o),D(t,"DOCUMENT",i.length,o),b(t,e,o),r.length>0&&g(t,e,"Add the ml { } block with forCaptureType(CaptureType.SELFIE) { } inside",o)}}export class UnknownJobTypeValidator{validate(e,o){f(e.steps,o),l(e.steps,o),y(e.steps,2,o),j(e.steps)&&!e.ml&&o.push(new J),k(e.steps)&&!e.network&&o.push(new F),o.push(new V)}}export const jobTypeValidators=new Map([[a.biometricKyc,new SelfieJobTypeValidator(a.biometricKyc)],[a.smartSelfieAuthentication,new SelfieJobTypeValidator(a.smartSelfieAuthentication)],[a.smartSelfieEnrollment,new SelfieJobTypeValidator(a.smartSelfieEnrollment)],[a.documentVerification,new DocumentJobTypeValidator(a.documentVerification)],[a.enhancedDocumentVerification,new DocumentJobTypeValidator(a.enhancedDocumentVerification)],[a.residencyDocumentVerification,new DocumentJobTypeValidator(a.residencyDocumentVerification)],[a.enhancedKyc,new NonCaptureJobTypeValidator(a.enhancedKyc)],[a.bvn,new NonCaptureJobTypeValidator(a.bvn)],[a.unknownProduct,new UnknownProductJobTypeValidator]]);const v=new UnknownJobTypeValidator;export function resolveJobTypeValidator(n){return n===void 0?v:jobTypeValidators.get(n)??v}export function collectJobTypeIssues(n,e){const o=n.network?.config?.jobType;resolveJobTypeValidator(o).validate(n,e)}export function residencyIdTypeIssue(){return s.forJob({jobType:a.residencyDocumentVerification,reason:`idType must be "${T}" \u2014 the backend rejects any other value for this job type`,suggestedFix:`Set builder.residencyDocumentVerificationParams with idType: "${T}"`})}export function hasNonPassportIdType(n){return(n.idType?.trim()??"")!==""&&n.idType!==T}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smileid/usesmileid",
3
- "version": "12.3.1-SNAPSHOT.71",
3
+ "version": "12.3.1-SNAPSHOT.73",
4
4
  "description": "Official Smile ID React Native (Expo) SDK for identity verification: selfie capture, liveness checks, and document verification powered by on-device ML.",
5
5
  "homepage": "https://usesmileid.com",
6
6
  "repository": {
@@ -48,11 +48,11 @@
48
48
  "CHANGELOG.md"
49
49
  ],
50
50
  "dependencies": {
51
- "@smileid/kamera": "1.2.1-SNAPSHOT.34",
51
+ "@smileid/kamera": "1.2.1-SNAPSHOT.35",
52
52
  "@smileid/njia": "0.0.1-SNAPSHOT.11",
53
53
  "zod": "^4.6.7",
54
- "@smileid/usesmileid_bridge": "12.3.1-SNAPSHOT.71",
55
- "@smileid/usesmileid_platform_interface": "12.3.1-SNAPSHOT.71"
54
+ "@smileid/usesmileid_bridge": "12.3.1-SNAPSHOT.73",
55
+ "@smileid/usesmileid_platform_interface": "12.3.1-SNAPSHOT.73"
56
56
  },
57
57
  "peerDependencies": {
58
58
  "@react-native-async-storage/async-storage": ">=1.21.0",