@authme/engine 2.1.1

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 (35) hide show
  1. package/CHANGELOG.md +332 -0
  2. package/README.md +7 -0
  3. package/assets/engine-worker.js +642 -0
  4. package/assets/ml_engine_web.js +21 -0
  5. package/assets/ml_engine_web.simd.js +21 -0
  6. package/assets/ml_engine_web.simd.wasm +0 -0
  7. package/assets/ml_engine_web.wasm +0 -0
  8. package/package.json +16 -0
  9. package/src/index.d.ts +3 -0
  10. package/src/index.js +7 -0
  11. package/src/index.js.map +1 -0
  12. package/src/lib/engine.d.ts +40 -0
  13. package/src/lib/engine.js +206 -0
  14. package/src/lib/engine.js.map +1 -0
  15. package/src/lib/enum/auth.enum.d.ts +3 -0
  16. package/src/lib/enum/auth.enum.js +8 -0
  17. package/src/lib/enum/auth.enum.js.map +1 -0
  18. package/src/lib/enum/index.d.ts +2 -0
  19. package/src/lib/enum/index.js +6 -0
  20. package/src/lib/enum/index.js.map +1 -0
  21. package/src/lib/enum/module.enum.d.ts +8 -0
  22. package/src/lib/enum/module.enum.js +13 -0
  23. package/src/lib/enum/module.enum.js.map +1 -0
  24. package/src/lib/interface/basic-type.interface.d.ts +12 -0
  25. package/src/lib/interface/basic-type.interface.js +3 -0
  26. package/src/lib/interface/basic-type.interface.js.map +1 -0
  27. package/src/lib/interface/config.interface.d.ts +7 -0
  28. package/src/lib/interface/config.interface.js +10 -0
  29. package/src/lib/interface/config.interface.js.map +1 -0
  30. package/src/lib/interface/index.d.ts +3 -0
  31. package/src/lib/interface/index.js +7 -0
  32. package/src/lib/interface/index.js.map +1 -0
  33. package/src/lib/interface/worker-command.interface.d.ts +7 -0
  34. package/src/lib/interface/worker-command.interface.js +3 -0
  35. package/src/lib/interface/worker-command.interface.js.map +1 -0
@@ -0,0 +1,642 @@
1
+ (function () {
2
+ // Common func
3
+ let wasm_loaded = false;
4
+ let wasm_loading = false;
5
+
6
+ let modelSession = {};
7
+
8
+ function isSimdSupported() {
9
+ try {
10
+ // Test for WebAssembly SIMD capability (for both browsers and Node.js)
11
+ // This typed array is a WebAssembly program containing SIMD instructions.
12
+ return WebAssembly.validate(
13
+ new Uint8Array([
14
+ 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 10, 9, 1,
15
+ 7, 0, 65, 0, 253, 15, 26, 11,
16
+ ])
17
+ );
18
+ } catch (e) {
19
+ return false;
20
+ }
21
+ }
22
+
23
+ function base64toBlob(data) {
24
+ const byteChars = self.atob(data);
25
+ const byteNumbers = new Array(byteChars.length);
26
+ for (let i = 0; i < byteChars.length; i++) {
27
+ byteNumbers[i] = byteChars.charCodeAt(i);
28
+ }
29
+ const byteArray = new Uint8Array(byteNumbers);
30
+ return new Blob([byteArray], { type: 'application/octet-stream' });
31
+ }
32
+
33
+ async function fetchModel(code) {
34
+ const method = self.config.dataTransferMethod || 'binary';
35
+
36
+ const resp = await fetch(
37
+ `${self.config.apiBaseUrl}/api/model-management/v1/model/${code}${
38
+ method === 'binary' ? '/file' : ''
39
+ }`,
40
+ {
41
+ headers: {
42
+ Authorization: 'Bearer ' + self.config.token,
43
+ },
44
+ }
45
+ );
46
+
47
+ if (method === 'binary') {
48
+ return resp.blob();
49
+ } else {
50
+ const data = await resp.json();
51
+ return base64toBlob(data.data);
52
+ }
53
+ }
54
+
55
+ async function loadWasm() {
56
+ return new Promise((res, rej) => {
57
+ // console.log('load wasm');
58
+ if (wasm_loaded || wasm_loading) {
59
+ res(true);
60
+ } else {
61
+ wasm_loading = true;
62
+ self['Module'] = {};
63
+ self['Module'] = {
64
+ locateFile: (path, scriptDirectory) => `${scriptDirectory}/${path}`,
65
+ print: (msg) => {
66
+ postMessage({
67
+ module: 'DEBUG',
68
+ command: 'DEBUG',
69
+ id: null,
70
+ value: msg,
71
+ });
72
+ },
73
+ };
74
+ self.importScripts(
75
+ isSimdSupported()
76
+ ? `${self.config.scriptPath}ml_engine_web.simd.js`
77
+ : `${self.config.scriptPath}ml_engine_web.js`
78
+ );
79
+ let tryInitEngineLib = async () => {
80
+ try {
81
+ const module = await AuthmeMLEngineLib({
82
+ print: (msg) => {
83
+ console.log(msg);
84
+ postMessage({
85
+ module: 'DEBUG',
86
+ command: 'DEBUG',
87
+ id: null,
88
+ value: msg,
89
+ });
90
+ },
91
+ });
92
+ self.EngineLib = module;
93
+ module.FS.mkdir('/model');
94
+ wasm_loaded = true;
95
+ wasm_loading = false;
96
+ // console.log('load wasm finished');
97
+ res(true);
98
+ } catch (error) {
99
+ console.warn(
100
+ 'init Authme EngineLib error:',
101
+ error,
102
+ ' Try after 1 second.'
103
+ );
104
+ await waitTime(500);
105
+ await tryInitEngineLib();
106
+ }
107
+ };
108
+ tryInitEngineLib();
109
+ }
110
+ });
111
+ }
112
+
113
+ // MRZ
114
+ self.MRZ = {
115
+ instance: null,
116
+ init: async function () {
117
+ return await self.Base.init(self.MRZ, 'MRZ');
118
+ },
119
+ start: function () {
120
+ return self.Base.start(self.MRZ);
121
+ },
122
+ stop: function () {
123
+ return self.Base.stop(self.MRZ);
124
+ },
125
+ getJsonReport: function () {
126
+ return self.Base.getJsonReport(self.MRZ);
127
+ },
128
+ setFrameSize: function (params) {
129
+ return self.Base.setFrameSize(self.MRZ, params);
130
+ },
131
+ recognition: function (params) {
132
+ const result = self.Base.recognition(self.MRZ, params);
133
+ if (result) {
134
+ result.eStatus = result.eStatus.constructor.name;
135
+ result.tField = Object.entries(result.tField)
136
+ .map(([k, v]) => [
137
+ k,
138
+ v
139
+ .map((x) => String.fromCharCode(x))
140
+ .filter((x) => x !== '\x00')
141
+ .join(''),
142
+ ])
143
+ .reduce((prev, cur) => {
144
+ prev[cur[0]] = cur[1];
145
+ return prev;
146
+ }, {});
147
+ }
148
+ return result;
149
+ },
150
+ getParams: function () {
151
+ return self.Base.getParams(self.MRZ);
152
+ },
153
+ setParams: function (params) {
154
+ return self.Base.setParams(self.MRZ, params);
155
+ },
156
+ getDebugImage: function (params) {
157
+ return self.Base.getDebugImage(self.MRZ, params);
158
+ },
159
+ destroy: function () {
160
+ return self.Base.destroy(self.MRZ);
161
+ },
162
+ };
163
+
164
+ // Card OCR
165
+ self.CardOCR = {
166
+ instance: null,
167
+ init: async function () {
168
+ let result = await self.Base.init(self.CardOCR, 'CardOCR');
169
+ return result;
170
+ },
171
+ start: function () {
172
+ return self.Base.start(self.CardOCR);
173
+ },
174
+ stop: function () {
175
+ return self.Base.stop(self.CardOCR);
176
+ },
177
+ getJsonReport: function () {
178
+ return self.Base.getJsonReport(self.CardOCR);
179
+ },
180
+ setFrameSize: function (params) {
181
+ return self.Base.setFrameSize(self.CardOCR, params);
182
+ },
183
+ recognition: function (params) {
184
+ const result = self.Base.recognition(self.CardOCR, params);
185
+ if (result) {
186
+ if (result.pointer > 0) {
187
+ result.imageData = self.EngineLib.HEAPU8.slice(
188
+ result.pointer,
189
+ result.pointer + result.iHeight * result.iWidth * 4
190
+ );
191
+ self.EngineLib._free(result.pointer);
192
+ }
193
+ result.eStatus = result.eStatus.constructor.name;
194
+ result.info.cardClass.eClass =
195
+ result.info.cardClass.eClass.constructor.name;
196
+ }
197
+ return result;
198
+ },
199
+ getDebugImage: function (params) {
200
+ return self.Base.getDebugImage(self.CardOCR, params);
201
+ },
202
+ setType: function (params) {
203
+ const engine = self.CardOCR.instance;
204
+ if (engine) {
205
+ const engineParams = engine.getParams();
206
+ engineParams.eTargetCardType =
207
+ self.EngineLib.EAuthMeCardClass.values[params.type];
208
+ engineParams.fImageBlurTh = 750;
209
+ engine.setParams(engineParams);
210
+ return true;
211
+ }
212
+ return false;
213
+ },
214
+ setMaskPosition: function (params) {
215
+ const positions = params.positions;
216
+ return self.CardOCR.instance?.setCardMatchROI(
217
+ positions[0][0],
218
+ positions[0][1],
219
+ positions[1][0],
220
+ positions[1][1],
221
+ positions[2][0],
222
+ positions[2][1],
223
+ positions[3][0],
224
+ positions[3][1]
225
+ );
226
+ },
227
+ getParams: function () {
228
+ return self.Base.getParams(self.CardOCR);
229
+ },
230
+ setParams: function (params) {
231
+ return self.Base.setParams(self.CardOCR, params);
232
+ },
233
+ destroy: function () {
234
+ return self.Base.destroy(self.CardOCR);
235
+ },
236
+ };
237
+
238
+ // Id Card Anti Fraud
239
+ self.IdCardAntiFraud = {
240
+ instance: null,
241
+ init: async function () {
242
+ await self.Base.init(self.IdCardAntiFraud, 'IdCardAntiFraudService');
243
+ if (self.IdCardAntiFraud.instance) {
244
+ const engine = self.IdCardAntiFraud.instance;
245
+ const engineParams = engine.getParams();
246
+ engineParams.timeoutSec = 52;
247
+ engine.setParams(engineParams);
248
+ return true;
249
+ }
250
+ },
251
+ start: function () {
252
+ return self.Base.start(self.IdCardAntiFraud);
253
+ },
254
+ stop: function () {
255
+ return self.Base.stop(self.IdCardAntiFraud);
256
+ },
257
+ getJsonReport: function () {
258
+ return self.Base.getJsonReport(self.IdCardAntiFraud);
259
+ },
260
+ setFrameSize: function (params) {
261
+ return self.Base.setFrameSize(self.IdCardAntiFraud, params);
262
+ },
263
+ recognition: function (params) {
264
+ const result = self.Base.recognition(self.IdCardAntiFraud, params);
265
+ if (result) {
266
+ result.eStatus = result.eStatus.constructor.name;
267
+ result.eStage = result.eStage.constructor.name;
268
+ result.info.eCardMatchStatus =
269
+ result.info.eCardMatchStatus.constructor.name;
270
+ result.info.cardClass.eClass =
271
+ result.info.cardClass.eClass.constructor.name;
272
+ result.info.laserTag.eStatus =
273
+ result.info.laserTag.eStatus.constructor.name;
274
+ result.info.metalTag.aeStatus = result.info.metalTag.aeStatus.map(
275
+ (x) => x.constructor.name
276
+ );
277
+ result.info.taiwanHole.eStatus =
278
+ result.info.taiwanHole.eStatus.constructor.name;
279
+ }
280
+ return result;
281
+ },
282
+ setMaskPosition: function (params) {
283
+ const positions = params.positions;
284
+ return self.IdCardAntiFraud.instance?.setFrontalCardVertices(
285
+ positions[0][0],
286
+ positions[0][1],
287
+ positions[1][0],
288
+ positions[1][1],
289
+ positions[2][0],
290
+ positions[2][1],
291
+ positions[3][0],
292
+ positions[3][1]
293
+ );
294
+ },
295
+ setStage: function (params) {
296
+ if (self.IdCardAntiFraud.instance) {
297
+ const stageList = new self.EngineLib.FraudStageList();
298
+ params.forEach((x) => {
299
+ stageList.push_back(self.EngineLib.EAuthMeIDCardAntiFraudStage[x]);
300
+ });
301
+ self.IdCardAntiFraud.instance.setStage(stageList);
302
+ }
303
+ },
304
+ getParams: function () {
305
+ return self.Base.getParams(self.IdCardAntiFraud);
306
+ },
307
+ setParams: function (params) {
308
+ return self.Base.setParams(self.IdCardAntiFraud, params);
309
+ },
310
+ getDebugImage: function (params) {
311
+ return self.Base.getDebugImage(self.IdCardAntiFraud, params);
312
+ },
313
+ destroy: function () {
314
+ return self.Base.destroy(self.IdCardAntiFraud);
315
+ },
316
+ };
317
+
318
+ self.Fas = {
319
+ instance: null,
320
+ init: async function () {
321
+ await self.Base.init(self.Fas, 'CFASService');
322
+ },
323
+ start: function () {
324
+ return self.Base.start(self.Fas);
325
+ },
326
+ stop: function () {
327
+ return self.Base.stop(self.Fas);
328
+ },
329
+ getJsonReport: function () {
330
+ return self.Base.getJsonReport(self.Fas);
331
+ },
332
+ setFrameSize: function (params) {
333
+ self.Base.setFrameSize(self.Fas, params);
334
+ if (config.frame.width / config.frame.height >= 1) {
335
+ const params = self.Fas.instance.getParams();
336
+ params.fFaceRoiPreviewRatioW = 0.3;
337
+ self.Fas.instance.setParams(params);
338
+ }
339
+ },
340
+ setStage: function (params) {
341
+ if (self.Fas.instance) {
342
+ const stageList = new self.EngineLib.FASStageList();
343
+ params.stageList.forEach((x) => {
344
+ stageList.push_back(self.EngineLib.EAuthMeFASServiceStage[x]);
345
+ });
346
+ self.Fas.instance.setStage(stageList);
347
+ }
348
+ },
349
+ recognition: function (params) {
350
+ const result = self.Base.recognition(self.Fas, params);
351
+ if (result) {
352
+ result.eStatus = result.eStatus.constructor.name;
353
+ result.eStage = result.eStage.constructor.name;
354
+ result.info.eye.eStatus = result.info.eye.eStatus.constructor.name;
355
+ result.info.fas.eStatus = result.info.fas.eStatus.constructor.name;
356
+ result.info.mouth.eStatus = result.info.mouth.eStatus.constructor.name;
357
+ result.info.pose.ePose = result.info.pose.ePose.constructor.name;
358
+ result.info.miniFAS = result.info.miniFAS.constructor.name;
359
+ }
360
+ return result;
361
+ },
362
+ getParams: function () {
363
+ return self.Base.getParams(self.Fas);
364
+ },
365
+ setParams: function (params) {
366
+ return self.Base.setParams(self.Fas, params);
367
+ },
368
+ getDebugImage: function (params) {
369
+ return self.Base.getDebugImage(self.Fas, params);
370
+ },
371
+ destroy: function () {
372
+ return self.Base.destroy(self.Fas);
373
+ },
374
+ };
375
+
376
+ // Base
377
+ self.Base = {
378
+ init: async function (target, constructorName) {
379
+ return new Promise((res, rej) => {
380
+ try {
381
+ setTimeout(async () => {
382
+ const models = [];
383
+ const versionVector =
384
+ self.EngineLib[constructorName]['getModelVersion']();
385
+ target.sessionUsed = [];
386
+ for (let i = 0; i < versionVector.size(); i++) {
387
+ let item = versionVector.get(i);
388
+ target.sessionUsed.push(item.szName);
389
+ models.push({
390
+ name: item.szName,
391
+ version: item.szVersion,
392
+ });
393
+ }
394
+
395
+ let queryModelString = models
396
+ .map((x) => 'models=' + x.name + '[' + x.version + ']')
397
+ .join('&');
398
+
399
+ let modelPath = await loadModels(queryModelString);
400
+ let modelPointer = models.map(({ name }, index) => {
401
+ if (modelSession[name]) {
402
+ return modelSession[name];
403
+ } else {
404
+ modelSession[name] = self.EngineLib.createInferenceSession(
405
+ name,
406
+ modelPath[index]
407
+ );
408
+ return modelSession[name];
409
+ }
410
+ });
411
+ const instance = new self.EngineLib[constructorName]();
412
+ instance.initial(...modelPointer);
413
+ const engine = instance;
414
+ const uiParams = engine.getUIParams();
415
+ uiParams.previewPosition.fLeft = 0;
416
+ uiParams.previewPosition.fTop = 0;
417
+ uiParams.previewPosition.fRight = 1;
418
+ uiParams.previewPosition.fBottom = 1;
419
+ engine.setUIParams(uiParams);
420
+ target.instance = instance;
421
+ res(true);
422
+ }, 10);
423
+ } catch (error) {
424
+ rej(error.message);
425
+ }
426
+ });
427
+ },
428
+ start: function (target) {
429
+ return target?.instance?.start();
430
+ },
431
+ stop: function (target) {
432
+ return target?.instance?.stop();
433
+ },
434
+ setFrameSize: function (target, params) {
435
+ config.frame.width = Math.floor(params.width);
436
+ config.frame.height = Math.floor(params.height);
437
+ if (target.instance) {
438
+ const engine = target.instance;
439
+ const uiParams = engine.getUIParams();
440
+ uiParams.analyzeSize.iHeight = config.frame.height;
441
+ uiParams.analyzeSize.iWidth = config.frame.width;
442
+ engine.setUIParams(uiParams);
443
+ return true;
444
+ }
445
+ },
446
+ recognition: function (target, params) {
447
+ const engine = target.instance;
448
+ if (engine) {
449
+ try {
450
+ const data = params.data;
451
+ const heapInfo = putOnHeap(data);
452
+ const result = engine.run(
453
+ heapInfo.byteOffset,
454
+ heapInfo.length,
455
+ config.frame.width,
456
+ config.frame.height
457
+ );
458
+ self.EngineLib._free(heapInfo.dataPtr);
459
+ return result;
460
+ } catch (error) {
461
+ // console.warn(error);
462
+ // console.warn('[Recognition Error]: ' + error?.message);
463
+ return null;
464
+ }
465
+ }
466
+ console.warn('engine not initialized');
467
+ },
468
+ getParams: function (target) {
469
+ return target.instance.getParams();
470
+ },
471
+ setParams: function (target, params) {
472
+ return target.instance.setParams(params.params);
473
+ },
474
+ getDebugImage: function (target, params) {
475
+ const data = params.data;
476
+ const heapInfo = putOnHeap(data);
477
+ let imageData;
478
+ const pointer = target.instance.getDebugImage(
479
+ heapInfo.byteOffset,
480
+ heapInfo.length,
481
+ config.frame.width,
482
+ config.frame.height
483
+ );
484
+ self.EngineLib._free(heapInfo.dataPtr);
485
+ if (pointer) {
486
+ imageData = self.EngineLib.HEAPU8.slice(
487
+ pointer,
488
+ pointer + config.frame.width * config.frame.height * 4
489
+ );
490
+ self.EngineLib._free(pointer);
491
+ }
492
+ return imageData;
493
+ },
494
+ destroy: function (target) {
495
+ if (target.instance) {
496
+ target.instance.delete();
497
+ target.instance = null;
498
+ }
499
+ if (target.sessionUsed) {
500
+ target.sessionUsed.forEach((name) => {
501
+ if (modelSession[name]) {
502
+ self.EngineLib.deleteSession(modelSession[name]);
503
+ modelSession[name] = null;
504
+ }
505
+ });
506
+ target.sessionUsed = [];
507
+ }
508
+ },
509
+ getJsonReport: function (target) {
510
+ return target?.instance?.getJsonReport();
511
+ },
512
+ };
513
+
514
+ self.Core = {
515
+ setConfig: async function (config) {
516
+ self.config = {
517
+ ...self.config,
518
+ ...config,
519
+ };
520
+ return true;
521
+ },
522
+ loadEngine: async function () {
523
+ return await loadWasm();
524
+ },
525
+ verify: async function (params) {
526
+ for (let index = 0; index < 20; index++) {
527
+ if (self.EngineLib) {
528
+ let result = self.EngineLib.verifySDK(params.cert, params.authToken);
529
+ return result.constructor.name;
530
+ }
531
+ await waitTime(500);
532
+ }
533
+ return false;
534
+ },
535
+ };
536
+
537
+ addEventListener(
538
+ 'message',
539
+ async function ({ data }) {
540
+ const { module, command, id, value } = data;
541
+ const fn = self[module][command];
542
+ if (fn) {
543
+ // console.log(`call ${module}.${command} :`, value);
544
+ const result = await fn(value);
545
+ // console.log(`worker return value for ${command}:`, result);
546
+ postMessage({
547
+ module,
548
+ command,
549
+ id,
550
+ value: result,
551
+ });
552
+ }
553
+ }.bind(self)
554
+ );
555
+
556
+ let config = {
557
+ scriptPath: 'assets',
558
+ apiBaseUrl: '/',
559
+ frame: {
560
+ width: 0,
561
+ height: 0,
562
+ },
563
+ };
564
+
565
+ async function loadModel(modelInfo) {
566
+ const { name, code } = modelInfo;
567
+ const modelData = await fetchModel(code);
568
+ console.log(modelData);
569
+ try {
570
+ const FS = self.EngineLib.FS;
571
+ FS.mkdir(name);
572
+ FS.mount(
573
+ FS.filesystems.WORKERFS,
574
+ {
575
+ blobs: [
576
+ {
577
+ name,
578
+ data: modelData,
579
+ },
580
+ ],
581
+ },
582
+ '/' + name
583
+ );
584
+ } catch (error) {
585
+ if (error?.errno === 20) {
586
+ // File Exist
587
+ return `/${name}/${name}`;
588
+ } else {
589
+ throw error;
590
+ }
591
+ }
592
+
593
+ return `/${name}/${name}`;
594
+ }
595
+
596
+ async function loadModels(modelString) {
597
+ const start = performance.now();
598
+ const resp = await fetch(
599
+ self.config.apiBaseUrl + '/api/model-management/v1/model?' + modelString,
600
+ {
601
+ headers: {
602
+ Authorization: 'Bearer ' + self.config.token,
603
+ },
604
+ }
605
+ );
606
+ if (!resp.ok) {
607
+ throw new Error('[HTTP Error] Status: ' + resp.status);
608
+ }
609
+ const result = await resp.json();
610
+ const modelPath = [];
611
+ for (let i = 0; i < result.models.length; i++) {
612
+ modelPath.push(await loadModel(result.models[i]));
613
+ }
614
+ const end = performance.now();
615
+ // console.log('Load Model Time: ', +end - start + ' ms');
616
+ return modelPath;
617
+ }
618
+
619
+ function putOnHeap(data) {
620
+ const Module = self.EngineLib;
621
+ const uint8ArrData = new Uint8Array(data);
622
+ const numBytes = uint8ArrData.length * uint8ArrData.BYTES_PER_ELEMENT;
623
+ const dataPtr = Module._malloc(numBytes);
624
+ const dataOnHeap = new Uint8Array(Module.HEAPU8.buffer, dataPtr, numBytes);
625
+ dataOnHeap.set(uint8ArrData);
626
+ return {
627
+ byteOffset: dataOnHeap.byteOffset,
628
+ length: uint8ArrData.length,
629
+ dataPtr: dataPtr,
630
+ dataOnHeap: dataOnHeap,
631
+ Module: Module,
632
+ };
633
+ }
634
+
635
+ async function waitTime(ms) {
636
+ return new Promise((res) => {
637
+ setTimeout(() => {
638
+ res(true);
639
+ }, ms);
640
+ });
641
+ }
642
+ })();