santoid-sdk 8.0.0 → 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CHANGELOG.md +17 -3
  2. package/README.md +123 -244
  3. package/api/ApiLivenessSessionService.d.ts +14 -0
  4. package/api/ApiLivenessSessionService.js +4 -0
  5. package/browser/index.js +1 -1
  6. package/browser/liveness-capture.js +2 -0
  7. package/browser/liveness-capture.js.LICENSE.txt +350 -0
  8. package/client/age/index.d.ts +18 -0
  9. package/client/age/index.js +40 -0
  10. package/client/index.d.ts +4 -2
  11. package/client/index.js +4 -2
  12. package/client/liveness/index.d.ts +2 -2
  13. package/client/liveness/index.js +3 -3
  14. package/client/liveness/methods/livenessSession/Service.d.ts +7 -2
  15. package/client/liveness/methods/livenessSession/Service.js +14 -6
  16. package/client/liveness/methods/livenessSession/index.d.ts +13 -9
  17. package/client/liveness/methods/livenessSession/index.js +12 -9
  18. package/client/liveness/methods/livenessSession/isLivenessApproved.d.ts +6 -0
  19. package/client/liveness/methods/livenessSession/isLivenessApproved.js +13 -0
  20. package/client/liveness/methods/uploadIdentificationDocument/Service.d.ts +8 -29
  21. package/client/liveness/methods/uploadIdentificationDocument/Service.js +25 -66
  22. package/client/liveness/methods/uploadIdentificationDocument/index.d.ts +4 -18
  23. package/client/liveness/methods/uploadIdentificationDocument/index.js +4 -8
  24. package/client/liveness-capture/index.d.ts +35 -0
  25. package/client/liveness-capture/index.js +2 -0
  26. package/client/liveness-capture/index.js.LICENSE.txt +350 -0
  27. package/client/liveness-capture/types.d.ts +2 -0
  28. package/client/liveness-capture/types.js +2 -0
  29. package/package.json +14 -6
  30. package/server/index.d.ts +0 -2
  31. package/server/index.js +0 -2
  32. package/server/liveness/index.d.ts +1 -2
  33. package/server/liveness/index.js +1 -3
  34. package/server/liveness/methods/uploadIdentificationDocument/Service.d.ts +3 -3
  35. package/server/liveness/methods/uploadIdentificationDocument/Service.js +2 -2
  36. package/server/liveness/methods/uploadIdentificationDocument/index.d.ts +7 -21
  37. package/server/liveness/methods/uploadIdentificationDocument/index.js +4 -10
  38. package/tsconfig.json +3 -0
  39. package/tsconfig.prod.json +3 -0
  40. package/utils/constants.d.ts +1 -2
  41. package/utils/constants.js +4 -3
  42. package/utils/error.d.ts +6 -5
  43. package/utils/error.js +7 -6
  44. package/utils/types.d.ts +0 -39
  45. package/webpack.config.cjs +45 -2
  46. package/client/liveness/methods/livenessDetection/Service.d.ts +0 -28
  47. package/client/liveness/methods/livenessDetection/Service.js +0 -138
  48. package/client/liveness/methods/livenessDetection/index.d.ts +0 -23
  49. package/client/liveness/methods/livenessDetection/index.js +0 -58
  50. package/server/liveness/methods/livenessDetection/Service.d.ts +0 -6
  51. package/server/liveness/methods/livenessDetection/Service.js +0 -20
  52. package/server/liveness/methods/livenessDetection/index.d.ts +0 -13
  53. package/server/liveness/methods/livenessDetection/index.js +0 -50
  54. package/utils/websocket.d.ts +0 -18
  55. package/utils/websocket.js +0 -62
@@ -1,25 +1,22 @@
1
1
  import { ApiTypificationService, type ITypificationResult } from '../../../../api/ApiTypificationService';
2
2
  import { ApiFaceMatchService, type IFaceMatchResult } from '../../../../api/ApiFaceMatchService';
3
- import { type ILivenessResults, type IBaseSDKOptions, type TCallbackFunction, type ISDKOptions } from '../../../../utils/types';
3
+ import { type IBaseSDKOptions, type TCallbackFunction } from '../../../../utils/types';
4
4
  import { SDKError } from '../../../../utils/error';
5
- import { type livenessDetection } from '../livenessDetection';
6
- export declare class UploadIdentificationDocumentService<TFrameType, TMediaType> {
7
- options: IServiceOptions<TFrameType, TMediaType>;
8
- internalOptions: IInternalServiceOptions<TFrameType, TMediaType>;
5
+ export declare class UploadIdentificationDocumentService<TFrameType> {
6
+ options: IServiceOptions<TFrameType>;
9
7
  typificationService: ApiTypificationService<TFrameType>;
10
8
  faceMatchService: ApiFaceMatchService<TFrameType>;
11
9
  results: IUploadIdentificationDocumentResults<TFrameType>;
12
- constructor(options: IServiceOptions<TFrameType, TMediaType>, internalOptions: IInternalServiceOptions<TFrameType, TMediaType>);
10
+ constructor(options: IServiceOptions<TFrameType>);
13
11
  getResults(): IUploadIdentificationDocumentResults<TFrameType>;
14
12
  updateResults(updatedResults: Partial<IUploadIdentificationDocumentResults<TFrameType>>): Promise<void>;
15
13
  updateUploadedDocument(file: TFrameType): void;
16
14
  waitForResults(requestId: string): Promise<ITypificationResult>;
17
15
  waitForResultsFaceMatch(requestId: string): Promise<IFaceMatchResult>;
18
16
  startDocumentUpload(file: TFrameType): Promise<void>;
19
- startLivenessDetection(startLivenessDetectionOptions?: ICustomLivenessOptions<TFrameType, TMediaType>): TLivenessDetectionReturn<TMediaType> | undefined;
20
17
  startFaceMatch(firstImage: TFrameType, secondImage: TFrameType): Promise<void>;
21
- tryStartFaceMatch(): Promise<void>;
22
- startAll(file: TFrameType, startLivenessDetectionOptions?: ICustomLivenessOptions<TFrameType, TMediaType>): void;
18
+ startFaceComparison(selfie: TFrameType): Promise<void>;
19
+ startAll(file: TFrameType, selfie?: TFrameType): Promise<void>;
23
20
  }
24
21
  type TResultStatuses = 'success' | 'error' | null;
25
22
  export interface IUploadIdentificationDocumentResults<TFrameType> {
@@ -30,12 +27,6 @@ export interface IUploadIdentificationDocumentResults<TFrameType> {
30
27
  loading: boolean;
31
28
  error: SDKError | null;
32
29
  };
33
- liveness: {
34
- status: TResultStatuses;
35
- results: ILivenessResults<TFrameType | null | undefined> | null;
36
- loading: boolean;
37
- error: SDKError | null;
38
- };
39
30
  faceMatch: {
40
31
  status: TResultStatuses;
41
32
  results: IFaceMatchResult | null;
@@ -43,28 +34,16 @@ export interface IUploadIdentificationDocumentResults<TFrameType> {
43
34
  error: SDKError | null;
44
35
  };
45
36
  }
46
- type ICustomLivenessOptions<TFrameType, TMediaType> = Omit<ISDKOptions<TFrameType, TMediaType>, 'track' | 'token'> & {
47
- track?: string;
48
- token?: string;
49
- };
50
- export interface IServiceOptions<TFrameType, TMediaType> extends IBaseSDKOptions {
51
- livenessDetectionOptions?: ICustomLivenessOptions<TFrameType, TMediaType>;
37
+ export interface IServiceOptions<TFrameType> extends IBaseSDKOptions {
52
38
  onUpdate?: (results?: IUploadIdentificationDocumentResults<TFrameType>) => void | Promise<void>;
53
- onSuccess?: <TFrameType, ResultsType = ILivenessResults<TFrameType>>(results?: ResultsType) => void | Promise<void>;
39
+ onSuccess?: <TFrameType, ResultsType = IUploadIdentificationDocumentResults<TFrameType>>(results?: ResultsType) => void | Promise<void>;
54
40
  onError?: (error?: SDKError) => void | Promise<void>;
55
41
  onEnd?: TCallbackFunction;
56
42
  onValidationRequested?: (requestInformation: IRequestInformation) => void | Promise<void>;
57
43
  onClearInterval?: (interval: ReturnType<typeof setInterval>) => void | Promise<void>;
58
44
  }
59
- type TLivenessDetectionReturn<TMediaType> = Omit<ReturnType<typeof livenessDetection>, 'getVideoStream'> & {
60
- getVideoStream?: () => TMediaType;
61
- };
62
- type TLivenessDetectionFn<TFrameType, TMediaType> = (options: ISDKOptions<TFrameType, TMediaType>) => TLivenessDetectionReturn<TMediaType>;
63
45
  interface IRequestInformation {
64
46
  track: string;
65
47
  requestId: string;
66
48
  }
67
- export interface IInternalServiceOptions<TFrameType, TMediaType> {
68
- livenessDetection: TLivenessDetectionFn<TFrameType, TMediaType>;
69
- }
70
49
  export {};
@@ -7,15 +7,13 @@ const error_1 = require("../../../../utils/error");
7
7
  const uuid_1 = require("uuid");
8
8
  const index_1 = require("../../utils/index");
9
9
  class UploadIdentificationDocumentService {
10
- constructor(options, internalOptions) {
10
+ constructor(options) {
11
11
  this.results = {
12
12
  uploadedDocument: null,
13
13
  typification: { status: null, results: null, loading: false, error: null },
14
- liveness: { status: null, results: null, loading: false, error: null },
15
14
  faceMatch: { status: null, results: null, loading: false, error: null },
16
15
  };
17
16
  this.options = options;
18
- this.internalOptions = internalOptions;
19
17
  this.typificationService = new ApiTypificationService_1.ApiTypificationService(options, { FormDataClass: FormData, tryDecodeJwt: index_1.tryDecodeJwt });
20
18
  this.faceMatchService = new ApiFaceMatchService_1.ApiFaceMatchService(options, { FormDataClass: FormData, tryDecodeJwt: index_1.tryDecodeJwt });
21
19
  }
@@ -24,14 +22,15 @@ class UploadIdentificationDocumentService {
24
22
  }
25
23
  async updateResults(updatedResults) {
26
24
  var _a, _b, _c, _d, _e, _f;
27
- this.results = Object.assign(Object.assign({}, this.results), updatedResults);
28
- await ((_b = (_a = this.options).onUpdate) === null || _b === void 0 ? void 0 : _b.call(_a, this.results));
29
- // Prevent Face Match loop
30
- if (!updatedResults.faceMatch) {
31
- this.tryStartFaceMatch();
32
- }
33
- if (Object.entries(this.results).every(([key, value]) => key === 'uploadedDocument' || !!value.results)) {
34
- await ((_d = (_c = this.options).onSuccess) === null || _d === void 0 ? void 0 : _d.call(_c, this.results));
25
+ const results = Object.assign(Object.assign({}, this.results), updatedResults);
26
+ this.results = results;
27
+ await ((_b = (_a = this.options).onUpdate) === null || _b === void 0 ? void 0 : _b.call(_a, results));
28
+ // Decide sobre o estado desta atualizacao, nao o de this.results depois do
29
+ // await: com upload e face match em paralelo, as duas atualizacoes finais
30
+ // leriam o mesmo estado e o onSuccess sairia duas vezes.
31
+ const { typification, faceMatch } = results;
32
+ if (typification.results && !typification.loading && !faceMatch.loading) {
33
+ await ((_d = (_c = this.options).onSuccess) === null || _d === void 0 ? void 0 : _d.call(_c, results));
35
34
  await ((_f = (_e = this.options).onEnd) === null || _f === void 0 ? void 0 : _f.call(_e));
36
35
  }
37
36
  }
@@ -121,47 +120,6 @@ class UploadIdentificationDocumentService {
121
120
  this.updateResults({ typification: { status: 'error', results: null, loading: false, error: adaptedError } });
122
121
  }
123
122
  }
124
- startLivenessDetection(startLivenessDetectionOptions) {
125
- var _a, _b;
126
- const adaptedLivenessDetection = Object.assign(Object.assign({}, this.options.livenessDetectionOptions), startLivenessDetectionOptions);
127
- this.updateResults({ liveness: { results: null, status: null, loading: true, error: null } });
128
- try {
129
- return this.internalOptions.livenessDetection(Object.assign(Object.assign({ domain: this.options.domain, customId: this.options.customId, customWebSocketUrl: this.options.customWebSocketUrl, token: this.options.token, track: this.options.track }, adaptedLivenessDetection), { onSuccess: async (livenessResults) => {
130
- var _a;
131
- await ((_a = adaptedLivenessDetection === null || adaptedLivenessDetection === void 0 ? void 0 : adaptedLivenessDetection.onSuccess) === null || _a === void 0 ? void 0 : _a.call(adaptedLivenessDetection, livenessResults));
132
- this.updateResults({
133
- liveness: {
134
- status: 'success',
135
- results: (livenessResults),
136
- loading: false,
137
- error: null,
138
- },
139
- });
140
- }, onError: async (livenessErrorDetails) => {
141
- var _a, _b, _c;
142
- await ((_a = adaptedLivenessDetection === null || adaptedLivenessDetection === void 0 ? void 0 : adaptedLivenessDetection.onError) === null || _a === void 0 ? void 0 : _a.call(adaptedLivenessDetection, livenessErrorDetails));
143
- await ((_c = (_b = this.options).onError) === null || _c === void 0 ? void 0 : _c.call(_b, livenessErrorDetails));
144
- this.updateResults({
145
- liveness: {
146
- status: 'error',
147
- results: null,
148
- loading: (livenessErrorDetails === null || livenessErrorDetails === void 0 ? void 0 : livenessErrorDetails.code) === 'wrong-position',
149
- error: livenessErrorDetails !== null && livenessErrorDetails !== void 0 ? livenessErrorDetails : null,
150
- },
151
- });
152
- } }));
153
- }
154
- catch (err) {
155
- const adaptedError = new error_1.SDKError({
156
- message: 'Error during liveness detection',
157
- code: error_1.EUploadIdentificationDocumentErrorCodes.LIVENESS_DETECTION_ERROR,
158
- fatal: false,
159
- details: err,
160
- });
161
- (_b = (_a = this.options).onError) === null || _b === void 0 ? void 0 : _b.call(_a, adaptedError);
162
- this.updateResults({ liveness: { status: 'error', results: null, loading: false, error: adaptedError } });
163
- }
164
- }
165
123
  async startFaceMatch(firstImage, secondImage) {
166
124
  var _a, _b;
167
125
  try {
@@ -181,26 +139,27 @@ class UploadIdentificationDocumentService {
181
139
  this.updateResults({ faceMatch: { results: null, status: 'error', loading: false, error: adaptedError } });
182
140
  }
183
141
  }
184
- async tryStartFaceMatch() {
185
- var _a, _b, _c;
186
- if (this.results.uploadedDocument &&
187
- ((_a = this.results.liveness.results) === null || _a === void 0 ? void 0 : _a.successFrames.front) &&
188
- !this.results.faceMatch.loading &&
189
- !this.results.liveness.loading &&
190
- !this.results.typification.loading) {
191
- await this.startFaceMatch(this.results.uploadedDocument, this.results.liveness.results.successFrames.front);
192
- }
193
- else {
194
- await ((_c = (_b = this.options).onError) === null || _c === void 0 ? void 0 : _c.call(_b, new error_1.SDKError({
142
+ // A selfie vem de quem chama - por exemplo, a foto de referencia da prova de
143
+ // vida (livenessSession). O documento e' o enviado em startDocumentUpload.
144
+ async startFaceComparison(selfie) {
145
+ var _a, _b;
146
+ if (!this.results.uploadedDocument || !selfie) {
147
+ await ((_b = (_a = this.options).onError) === null || _b === void 0 ? void 0 : _b.call(_a, new error_1.SDKError({
195
148
  message: 'Unavailable faces',
196
149
  code: error_1.EUploadIdentificationDocumentErrorCodes.FACE_MATCH_UNAVAILABLE_FACES_ERROR,
197
150
  fatal: false,
198
151
  })));
152
+ return;
199
153
  }
154
+ await this.startFaceMatch(this.results.uploadedDocument, selfie);
200
155
  }
201
- startAll(file, startLivenessDetectionOptions) {
202
- this.startDocumentUpload(file);
203
- this.startLivenessDetection(startLivenessDetectionOptions);
156
+ // Em paralelo: o onSuccess so dispara quando nada mais esta carregando, entao
157
+ // em sequencia ele sairia uma vez sem o face match e outra com ele.
158
+ async startAll(file, selfie) {
159
+ await Promise.all([
160
+ this.startDocumentUpload(file),
161
+ selfie ? this.startFaceComparison(selfie) : undefined,
162
+ ]);
204
163
  }
205
164
  }
206
165
  exports.UploadIdentificationDocumentService = UploadIdentificationDocumentService;
@@ -1,22 +1,8 @@
1
1
  import { type IServiceOptions } from './Service';
2
- import { type TFrameType, type TMediaType } from '../livenessDetection';
3
- export declare function uploadIdentificationDocument(options: IServiceOptions<TFrameType, TMediaType>): {
2
+ export type TFrameType = File | Blob;
3
+ export declare function uploadIdentificationDocument(options: IServiceOptions<TFrameType>): {
4
4
  startDocumentUpload: (file: TFrameType) => Promise<void>;
5
- startLivenessDetection: (startLivenessDetectionOptions?: (Omit<import("../../../../utils/types").ISDKOptions<TFrameType, TMediaType>, "token" | "track"> & {
6
- track?: string | undefined;
7
- token?: string | undefined;
8
- }) | undefined) => (Omit<{
9
- getVideoStream: () => TMediaType;
10
- stopLivenessDetection: () => Promise<void>;
11
- resumeGettingFrames: () => void;
12
- pauseGettingFrames: () => void;
13
- }, "getVideoStream"> & {
14
- getVideoStream?: (() => TMediaType) | undefined;
15
- }) | undefined;
16
- startFaceComparison: () => Promise<void>;
17
- startAll: (file: TFrameType, startLivenessDetectionOptions?: (Omit<import("../../../../utils/types").ISDKOptions<TFrameType, TMediaType>, "token" | "track"> & {
18
- track?: string | undefined;
19
- token?: string | undefined;
20
- }) | undefined) => void;
5
+ startFaceComparison: (selfie: TFrameType) => Promise<void>;
6
+ startAll: (file: TFrameType, selfie?: TFrameType | undefined) => Promise<void>;
21
7
  getResults: () => import("./Service").IUploadIdentificationDocumentResults<TFrameType>;
22
8
  };
@@ -2,21 +2,17 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.uploadIdentificationDocument = void 0;
4
4
  const Service_1 = require("./Service");
5
- const livenessDetection_1 = require("../livenessDetection");
6
5
  function uploadIdentificationDocument(options) {
7
- const uploadIdentificationDocumentService = new Service_1.UploadIdentificationDocumentService(options, { livenessDetection: livenessDetection_1.livenessDetection });
6
+ const uploadIdentificationDocumentService = new Service_1.UploadIdentificationDocumentService(options);
8
7
  return {
9
8
  startDocumentUpload: async (...rest) => {
10
9
  await uploadIdentificationDocumentService.startDocumentUpload(...rest);
11
10
  },
12
- startLivenessDetection: (...rest) => {
13
- return uploadIdentificationDocumentService.startLivenessDetection(...rest);
14
- },
15
11
  startFaceComparison: async (...rest) => {
16
- await uploadIdentificationDocumentService.tryStartFaceMatch(...rest);
12
+ await uploadIdentificationDocumentService.startFaceComparison(...rest);
17
13
  },
18
- startAll: (...rest) => {
19
- uploadIdentificationDocumentService.startAll(...rest);
14
+ startAll: async (...rest) => {
15
+ await uploadIdentificationDocumentService.startAll(...rest);
20
16
  },
21
17
  getResults: (...rest) => {
22
18
  return uploadIdentificationDocumentService.getResults(...rest);
@@ -0,0 +1,35 @@
1
+ import { type TLivenessCaptureColorMode, type TLivenessCaptureLanguage } from './types';
2
+ import { type TLivenessSessionOptions } from '../liveness/methods/livenessSession';
3
+ import { isLivenessApproved } from '../liveness/methods/livenessSession/isLivenessApproved';
4
+ import { type ILivenessSessionResult } from '../../api/ApiLivenessSessionService';
5
+ import { SDKError } from '../../utils/error';
6
+ export { isLivenessApproved };
7
+ export type { TLivenessCaptureColorMode, TLivenessCaptureLanguage };
8
+ export interface ILivenessCaptureResult extends ILivenessSessionResult {
9
+ approved: boolean;
10
+ threshold: number;
11
+ }
12
+ export type TMountLivenessOptions = Omit<TLivenessSessionOptions, 'onResults' | 'onError'> & {
13
+ language?: TLivenessCaptureLanguage;
14
+ colorMode?: TLivenessCaptureColorMode;
15
+ /** Confianca minima para `approved`. Padrao: 80. */
16
+ threshold?: number;
17
+ /** A captura terminou e o resultado esta sendo consultado. */
18
+ onCaptureComplete?: () => void | Promise<void>;
19
+ onResult?: (result: ILivenessCaptureResult) => void | Promise<void>;
20
+ onError?: (error: SDKError) => void | Promise<void>;
21
+ onCancel?: () => void | Promise<void>;
22
+ };
23
+ /**
24
+ * Monta a captura da prova de vida dentro de `element`.
25
+ *
26
+ * Cria a sessao, abre a camera, busca o resultado e entrega em `onResult`
27
+ * com `approved` ja calculado. Funciona em qualquer pagina - com ou sem
28
+ * framework -, porque a captura roda isolada dentro do elemento.
29
+ *
30
+ * O elemento precisa de altura: a captura ocupa o espaco que ele oferece.
31
+ */
32
+ export declare function mountLiveness(element: HTMLElement, options: TMountLivenessOptions): {
33
+ getSessionId: () => string | null;
34
+ unmount: () => void;
35
+ };