alphavalid-sdk 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +133 -0
- package/bin/alphavalid.js +92 -0
- package/dist/__vite-browser-external-C7ivxuo1.mjs +18 -0
- package/dist/alphavalid.es.d.ts +126 -0
- package/dist/alphavalid.es.js +20092 -0
- package/dist/alphavalid.umd.d.ts +126 -0
- package/dist/alphavalid.umd.js +3852 -0
- package/dist/core/camera.d.ts +8 -0
- package/dist/core/camera.d.ts.map +1 -0
- package/dist/core/feedback.d.ts +112 -0
- package/dist/core/feedback.d.ts.map +1 -0
- package/dist/index.d.ts +126 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/setupModels-RA6BN3uf.mjs +19 -0
- package/dist/setupModels.d.ts +2 -0
- package/dist/setupModels.d.ts.map +1 -0
- package/dist/types/sdk.d.ts +451 -0
- package/dist/types/sdk.d.ts.map +1 -0
- package/dist/ui/baseStyles.d.ts +2 -0
- package/dist/ui/baseStyles.d.ts.map +1 -0
- package/dist/ui/captureButtonCoxinha.d.ts +13 -0
- package/dist/ui/captureButtonCoxinha.d.ts.map +1 -0
- package/dist/ui/containerStyles.d.ts +1 -0
- package/dist/ui/containerStyles.d.ts.map +1 -0
- package/dist/ui/loader.d.ts +15 -0
- package/dist/ui/loader.d.ts.map +1 -0
- package/dist/ui/overlay.d.ts +221 -0
- package/dist/ui/overlay.d.ts.map +1 -0
- package/dist/ui/overlayCoxinhaMobile.d.ts +10 -0
- package/dist/ui/overlayCoxinhaMobile.d.ts.map +1 -0
- package/dist/ui/userPreviewCoxinha.d.ts +20 -0
- package/dist/ui/userPreviewCoxinha.d.ts.map +1 -0
- package/dist/utils/canvas.d.ts +27 -0
- package/dist/utils/canvas.d.ts.map +1 -0
- package/dist/utils/dom.d.ts +3 -0
- package/dist/utils/dom.d.ts.map +1 -0
- package/dist/vision/faceDetector.d.ts +11 -0
- package/dist/vision/faceDetector.d.ts.map +1 -0
- package/models/README.md +8 -0
- package/models/face_landmark_68_tiny_model-shard1.bin +0 -0
- package/models/face_landmark_68_tiny_model-weights_manifest.json +1 -0
- package/models/tiny_face_detector_model-shard1.bin +0 -0
- package/models/tiny_face_detector_model-weights_manifest.json +1 -0
- package/package.json +31 -7
- package/public/images/alphaloader.gif +0 -0
- package/scripts/copy-models.cjs +31 -0
- package/tsconfig.json +21 -0
- package/vite.config.ts +19 -0
- package/.gitattributes +0 -2
package/README.md
CHANGED
|
@@ -1,2 +1,135 @@
|
|
|
1
1
|
# alphavalid-sdk
|
|
2
2
|
|
|
3
|
+
SDK frontend (framework-agnostic) para validação facial e liveness com captura de selfie em JPEG.
|
|
4
|
+
|
|
5
|
+
Principais recursos:
|
|
6
|
+
- câmera frontal com teardown correto
|
|
7
|
+
- overlay visual com guias e hints
|
|
8
|
+
- desafios de liveness configuráveis
|
|
9
|
+
- captura manual e auto-capture com gate de estabilidade
|
|
10
|
+
- preview com botões OK/Recapturar (SDK ou customizado)
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Instalação
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm i alphavalid-sdk
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Modelos (obrigatório)
|
|
23
|
+
|
|
24
|
+
O `face-api.js` carrega pesos via HTTP. Copie os models do pacote para a pasta pública do seu app.
|
|
25
|
+
|
|
26
|
+
### CLI (recomendado)
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npx alphavalid-sdk setup
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Ele detecta o tipo de projeto e copia:
|
|
33
|
+
- Angular: `src/assets/alphavalid-models` (runtime: `/assets/alphavalid-models`)
|
|
34
|
+
- Vite: `public/alphavalid-models` (runtime: `/alphavalid-models`)
|
|
35
|
+
|
|
36
|
+
### Manual
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
node ./node_modules/alphavalid-sdk/scripts/copy-models.cjs ./public/alphavalid-models
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Uso minimo
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import { AlphaValid } from 'alphavalid-sdk';
|
|
48
|
+
|
|
49
|
+
const sdk = new AlphaValid();
|
|
50
|
+
|
|
51
|
+
await sdk.start({
|
|
52
|
+
// se estiver no Angular/Ionic, use /assets/alphavalid-models
|
|
53
|
+
modelsPath: '/alphavalid-models',
|
|
54
|
+
onUserPreviewConfirm: (blob) => {
|
|
55
|
+
// enviar blob
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Para finalizar:
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
await sdk.stop();
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Preview (OK/Recapturar)
|
|
69
|
+
|
|
70
|
+
O preview gerenciado pelo SDK funciona em `uiMode: 'Mobile'` e `userPreview: true`.
|
|
71
|
+
Por padrao o preview ja vem ligado.
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
await sdk.start({
|
|
75
|
+
uiMode: 'Mobile',
|
|
76
|
+
userPreview: true,
|
|
77
|
+
previewOkText: 'OK',
|
|
78
|
+
previewRetakeText: 'Tirar outra',
|
|
79
|
+
onUserPreviewConfirm: (blob) => {
|
|
80
|
+
// enviar blob
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Se voce quiser renderizar um preview customizado:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
await sdk.start({
|
|
89
|
+
onPreview: (blob, actions) => {
|
|
90
|
+
// abra seu modal, use actions.retake() e actions.confirm()
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Personalizacao de botoes
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
await sdk.start({
|
|
101
|
+
captureButton: {
|
|
102
|
+
enabled: true,
|
|
103
|
+
text: 'Capturar foto',
|
|
104
|
+
color: '#ff6b35'
|
|
105
|
+
},
|
|
106
|
+
previewOkText: 'Usar foto',
|
|
107
|
+
previewRetakeText: 'Tirar outra'
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## API publica
|
|
114
|
+
|
|
115
|
+
- `new AlphaValid()`
|
|
116
|
+
- `start(options: AlphaValidStartOptions): Promise<void>`
|
|
117
|
+
- `stop(): Promise<void>`
|
|
118
|
+
- `capture(): Promise<Blob>`
|
|
119
|
+
- `getState(): AlphaValidState | null`
|
|
120
|
+
- `resetChallenges(): void`
|
|
121
|
+
- `setupModels(): Promise<string>` (importando `setupModels` do pacote)
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Documentacao completa
|
|
126
|
+
|
|
127
|
+
Veja [alphavalid-sdk-docs.md](alphavalid-sdk-docs.md) para:
|
|
128
|
+
- todas as opcoes do SDK
|
|
129
|
+
- defaults oficiais
|
|
130
|
+
- exemplos completos
|
|
131
|
+
- ajustes de liveness e debug
|
|
132
|
+
- detalhes do estado e callbacks
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
### `stop(): Promise<void>`
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
function detectProjectType() {
|
|
7
|
+
if (fs.existsSync('angular.json')) return 'angular';
|
|
8
|
+
if (fs.existsSync('vite.config.js') || fs.existsSync('vite.config.ts') || fs.existsSync('index.html') || fs.existsSync('public')) return 'vite';
|
|
9
|
+
return 'unknown';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function getTargetDir() {
|
|
13
|
+
const type = detectProjectType();
|
|
14
|
+
if (type === 'angular') return path.join('src', 'assets', 'alphavalid-models');
|
|
15
|
+
if (type === 'vite') return path.join('public', 'alphavalid-models');
|
|
16
|
+
return path.join('alphavalid-models');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function copyModels() {
|
|
20
|
+
const src = path.join(__dirname, '..', 'models');
|
|
21
|
+
const dest = path.resolve(process.cwd(), getTargetDir());
|
|
22
|
+
if (!fs.existsSync(src)) {
|
|
23
|
+
console.error('[AlphaValid] Pasta de models não encontrada:', src);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
27
|
+
for (const file of fs.readdirSync(src)) {
|
|
28
|
+
fs.copyFileSync(path.join(src, file), path.join(dest, file));
|
|
29
|
+
}
|
|
30
|
+
console.log(`[AlphaValid] Models copiados para ${dest}`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function copyLoaderGif() {
|
|
34
|
+
const projectRoot = process.cwd();
|
|
35
|
+
const sdkRoot = path.join(__dirname, '..');
|
|
36
|
+
|
|
37
|
+
// Prefer the packaged location (guaranteed by package.json "files")
|
|
38
|
+
let loaderSrc = path.join(sdkRoot, 'public', 'images', 'alphaloader.gif');
|
|
39
|
+
|
|
40
|
+
// Fallback for local development (repo) only
|
|
41
|
+
if (!fs.existsSync(loaderSrc)) {
|
|
42
|
+
const demoLoader = path.join(sdkRoot, 'demo', 'public', 'images', 'alphaloader.gif');
|
|
43
|
+
if (fs.existsSync(demoLoader)) loaderSrc = demoLoader;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!fs.existsSync(loaderSrc)) return;
|
|
47
|
+
|
|
48
|
+
// Angular/Ionic Angular
|
|
49
|
+
if (fs.existsSync(path.join(projectRoot, 'angular.json'))) {
|
|
50
|
+
// Canonical destination used by the SDK: src/assets/images (plural)
|
|
51
|
+
const angularImages = path.join(projectRoot, 'src', 'assets', 'images');
|
|
52
|
+
fs.mkdirSync(angularImages, { recursive: true });
|
|
53
|
+
fs.copyFileSync(loaderSrc, path.join(angularImages, 'alphaloader.gif'));
|
|
54
|
+
console.log('[AlphaValid] Loader GIF copiado para', angularImages);
|
|
55
|
+
|
|
56
|
+
// Compatibility: if the project already uses src/assets/image (singular), also copy there
|
|
57
|
+
const angularImageSingular = path.join(projectRoot, 'src', 'assets', 'image');
|
|
58
|
+
if (fs.existsSync(angularImageSingular)) {
|
|
59
|
+
fs.mkdirSync(angularImageSingular, { recursive: true });
|
|
60
|
+
fs.copyFileSync(loaderSrc, path.join(angularImageSingular, 'alphaloader.gif'));
|
|
61
|
+
console.log('[AlphaValid] Loader GIF (compat) copiado para', angularImageSingular);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Vite / SPA genérica: public/images
|
|
68
|
+
if (
|
|
69
|
+
fs.existsSync(path.join(projectRoot, 'vite.config.js')) ||
|
|
70
|
+
fs.existsSync(path.join(projectRoot, 'vite.config.ts')) ||
|
|
71
|
+
fs.existsSync(path.join(projectRoot, 'index.html'))
|
|
72
|
+
) {
|
|
73
|
+
const viteImages = path.join(projectRoot, 'public', 'images');
|
|
74
|
+
fs.mkdirSync(viteImages, { recursive: true });
|
|
75
|
+
fs.copyFileSync(loaderSrc, path.join(viteImages, 'alphaloader.gif'));
|
|
76
|
+
console.log('[AlphaValid] Loader GIF copiado para', viteImages);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
copyLoaderGif();
|
|
82
|
+
} catch {
|
|
83
|
+
// silencioso: se falhar, o SDK tem fallback interno
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
copyModels();
|
|
88
|
+
} catch (e) {
|
|
89
|
+
console.error('[AlphaValid] Não foi possível copiar automaticamente os models.');
|
|
90
|
+
console.error('Execute: npx alphavalid-sdk setup');
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var e = Object.create, t = Object.defineProperty, n = Object.getOwnPropertyDescriptor, r = Object.getOwnPropertyNames, i = Object.getPrototypeOf, a = Object.prototype.hasOwnProperty, o = (e, t) => () => (t || e((t = { exports: {} }).exports, t), t.exports), s = (e, i, o, s) => {
|
|
3
|
+
if (i && typeof i == "object" || typeof i == "function") for (var c = r(i), l = 0, u = c.length, d; l < u; l++) d = c[l], !a.call(e, d) && d !== o && t(e, d, {
|
|
4
|
+
get: ((e) => i[e]).bind(null, d),
|
|
5
|
+
enumerable: !(s = n(i, d)) || s.enumerable
|
|
6
|
+
});
|
|
7
|
+
return e;
|
|
8
|
+
}, c = (n, r, a) => (a = n == null ? {} : e(i(n)), s(r || !n || !n.__esModule ? t(a, "default", {
|
|
9
|
+
value: n,
|
|
10
|
+
enumerable: !0
|
|
11
|
+
}) : a, n)), l = /* @__PURE__ */ ((e) => typeof require < "u" ? require : typeof Proxy < "u" ? new Proxy(e, { get: (e, t) => (typeof require < "u" ? require : e)[t] }) : e)(function(e) {
|
|
12
|
+
if (typeof require < "u") return require.apply(this, arguments);
|
|
13
|
+
throw Error("Calling `require` for \"" + e + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
|
|
14
|
+
}), u = /* @__PURE__ */ o(((e, t) => {
|
|
15
|
+
t.exports = {};
|
|
16
|
+
}));
|
|
17
|
+
//#endregion
|
|
18
|
+
export { l as n, c as r, u as t };
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
interface Window {
|
|
3
|
+
mouthWidthRatioDebug?: number;
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
import type { AlphaValidStartOptions, AlphaValidState } from './types/sdk';
|
|
7
|
+
export declare function setupModels(): Promise<string>;
|
|
8
|
+
export declare class AlphaValid {
|
|
9
|
+
private _camera;
|
|
10
|
+
private _overlay;
|
|
11
|
+
private _container;
|
|
12
|
+
private _faceDetector;
|
|
13
|
+
private _loopTimer;
|
|
14
|
+
private _lastStatusValid;
|
|
15
|
+
private _options;
|
|
16
|
+
private _status;
|
|
17
|
+
private _challengeIndex;
|
|
18
|
+
private _challengeStartedAt;
|
|
19
|
+
private _challengeEnterAt;
|
|
20
|
+
private _challengeCompletedAt;
|
|
21
|
+
private _challengeBaselineSeen;
|
|
22
|
+
private _blinkArmed;
|
|
23
|
+
private _state;
|
|
24
|
+
private _stableSince;
|
|
25
|
+
private _lastStableCx;
|
|
26
|
+
private _lastStableCy;
|
|
27
|
+
private _lastStableArea;
|
|
28
|
+
private _autoCaptureFired;
|
|
29
|
+
private _lastGoodStatus;
|
|
30
|
+
private _lastGoodAt;
|
|
31
|
+
/**
|
|
32
|
+
* Last detected frame status (most recent tick) used specifically for real-time
|
|
33
|
+
* capture button gating (look-forward).
|
|
34
|
+
*/
|
|
35
|
+
private _lastStatusForCaptureGate;
|
|
36
|
+
private _lastLookForwardGateOk;
|
|
37
|
+
private _poseLatch;
|
|
38
|
+
private _lastPoseChallenge;
|
|
39
|
+
private _mouthJawBaseline;
|
|
40
|
+
private _faceLostAt;
|
|
41
|
+
private _lookForwardOkSince;
|
|
42
|
+
private _blinkCount;
|
|
43
|
+
private _blinkPrevClosed;
|
|
44
|
+
private _cheeseBaseline;
|
|
45
|
+
private _cheeseBaselineSamples;
|
|
46
|
+
private _cheeseBaselineSum;
|
|
47
|
+
private _cheeseBaselineStartedAt;
|
|
48
|
+
private _challengeHoldSince;
|
|
49
|
+
private _challengeLastStepOk;
|
|
50
|
+
private _challengeHoldProgress;
|
|
51
|
+
private _challengeUiProgress;
|
|
52
|
+
/** Keep the last start options so the loop/catch/finally always has access (avoids scope issues). */
|
|
53
|
+
private _startOptions;
|
|
54
|
+
/** Estado de preview: blob da última captura, se em preview. */
|
|
55
|
+
private _previewBlob;
|
|
56
|
+
/** Guardar actions do preview para retake/confirm. */
|
|
57
|
+
private _previewActions;
|
|
58
|
+
private _cheeseWindow;
|
|
59
|
+
private _cheeseWindowStart;
|
|
60
|
+
private _openMouthWindow;
|
|
61
|
+
private _openMouthWindowStart;
|
|
62
|
+
/** Internal SDK lifecycle state machine. */
|
|
63
|
+
private _lifecycle;
|
|
64
|
+
/** Prevent starting multiple detection loops concurrently. */
|
|
65
|
+
private _loopActive;
|
|
66
|
+
/** Internal flag for debug logs (derived from start options). */
|
|
67
|
+
private _debug;
|
|
68
|
+
/** Prevent concurrent capture() executions. */
|
|
69
|
+
private _isCapturing;
|
|
70
|
+
/** userPreview UI (Coxinha mode only). */
|
|
71
|
+
private _userPreviewUi;
|
|
72
|
+
private _userPreviewUrl;
|
|
73
|
+
/** Built-in camera/models loader overlay. */
|
|
74
|
+
private _loader;
|
|
75
|
+
private _captureBtn;
|
|
76
|
+
private _disposeCaptureButton;
|
|
77
|
+
private _syncCaptureButton;
|
|
78
|
+
private _setLifecycle;
|
|
79
|
+
/**
|
|
80
|
+
* Pauses the detection loop without stopping the camera stream or clearing options.
|
|
81
|
+
* Safe to call multiple times.
|
|
82
|
+
*/
|
|
83
|
+
private _pause;
|
|
84
|
+
/**
|
|
85
|
+
* Resume the detection loop after a preview retake without tearing down/restoring options multiple times.
|
|
86
|
+
* Camera & overlay are recreated by calling start() with the original options.
|
|
87
|
+
*/
|
|
88
|
+
private _retakeFromPreview;
|
|
89
|
+
/**
|
|
90
|
+
* Confirms the preview and finalizes the flow.
|
|
91
|
+
*/
|
|
92
|
+
private _confirmFromPreview;
|
|
93
|
+
private _hideUserPreviewUi;
|
|
94
|
+
private _disposeUserPreviewUi;
|
|
95
|
+
/**
|
|
96
|
+
* Chama o preview após captura, pausa detecção e exibe opções de retake/confirm.
|
|
97
|
+
*/
|
|
98
|
+
private _showPreview;
|
|
99
|
+
private _usesCustomPreview;
|
|
100
|
+
private _usesSdkManagedPreview;
|
|
101
|
+
/** Hide camera until everything is ready (prevents showing video before models/overlay are loaded). */
|
|
102
|
+
private _setVideoVisibility;
|
|
103
|
+
/** Esconde vídeo + overlay enquanto o host exibe preview customizado. */
|
|
104
|
+
private _setCaptureSurfaceVisibility;
|
|
105
|
+
start(options: AlphaValidStartOptions): Promise<void>;
|
|
106
|
+
stop(): Promise<void>;
|
|
107
|
+
/** Indica se está em preview (bloqueia detecção/captura). */
|
|
108
|
+
private get _isInPreview();
|
|
109
|
+
capture(): Promise<Blob>;
|
|
110
|
+
getState(): AlphaValidState | null;
|
|
111
|
+
/** Reset the challenge progression back to step 0 (does not restart camera/detector). */
|
|
112
|
+
resetChallenges(): void;
|
|
113
|
+
private getCurrentChallenge;
|
|
114
|
+
private markStepCompletedIfNeeded;
|
|
115
|
+
private mapChallengeToHint;
|
|
116
|
+
private isStableFrame;
|
|
117
|
+
/**
|
|
118
|
+
* Simple, independent lookForward gate for capture.
|
|
119
|
+
* Intentionally does NOT reuse computeFeedback/lookForward challenge state.
|
|
120
|
+
* Returns true when user is roughly facing the camera.
|
|
121
|
+
*/
|
|
122
|
+
private _isLookForwardForCapture;
|
|
123
|
+
private startDetectionLoop;
|
|
124
|
+
}
|
|
125
|
+
export type { AlphaValidHint, AlphaValidStartOptions, AlphaValidState } from './types/sdk';
|
|
126
|
+
//# sourceMappingURL=index.d.ts.map
|