@myazahq/kyc-sdk-react-native 2.0.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 (87) hide show
  1. package/KycSdkReactNative.podspec +32 -0
  2. package/LICENSE +21 -0
  3. package/README.md +164 -0
  4. package/android/CMakeLists.txt +29 -0
  5. package/android/build.gradle +110 -0
  6. package/android/src/main/AndroidManifest.xml +12 -0
  7. package/android/src/main/cpp/cpp-adapter.cpp +12 -0
  8. package/android/src/main/java/co/myazahq/kyc/rn/MyazaFaceDetectorPackage.kt +36 -0
  9. package/android/src/main/java/co/myazahq/kyc/rn/MyazaStatusBarModule.kt +64 -0
  10. package/android/src/main/java/com/margelo/nitro/myazakyc/HybridMyazaFaceDetector.kt +134 -0
  11. package/app.plugin.js +55 -0
  12. package/expo-module.config.json +6 -0
  13. package/ios/HybridMyazaFaceDetector.swift +233 -0
  14. package/package.json +84 -0
  15. package/react-native.config.js +23 -0
  16. package/src/MyazaKYC.tsx +235 -0
  17. package/src/__tests__/cardCrop.test.ts +39 -0
  18. package/src/__tests__/deviceMetadata.test.ts +34 -0
  19. package/src/__tests__/errors.test.ts +34 -0
  20. package/src/__tests__/flow.test.ts +61 -0
  21. package/src/__tests__/gestureDetector.test.ts +37 -0
  22. package/src/__tests__/liveness.test.ts +112 -0
  23. package/src/__tests__/resolveUrl.test.ts +64 -0
  24. package/src/__tests__/validators.test.ts +38 -0
  25. package/src/assets/liveness/Blink.gif +0 -0
  26. package/src/assets/liveness/Nod.gif +0 -0
  27. package/src/assets/liveness/Smile.gif +0 -0
  28. package/src/assets/liveness/Turn.gif +0 -0
  29. package/src/components/CameraPermissionView.tsx +116 -0
  30. package/src/components/CameraViewfinder.tsx +156 -0
  31. package/src/components/CountryFlag.tsx +52 -0
  32. package/src/components/DocumentCropper.tsx +325 -0
  33. package/src/components/GlassIconButton.tsx +92 -0
  34. package/src/components/Icon.tsx +125 -0
  35. package/src/components/KycFlow.tsx +205 -0
  36. package/src/components/KycSheet.tsx +224 -0
  37. package/src/components/MyazaAlert.tsx +57 -0
  38. package/src/components/MyazaButton.tsx +101 -0
  39. package/src/components/MyazaCard.tsx +48 -0
  40. package/src/components/MyazaInput.tsx +112 -0
  41. package/src/components/MyazaPulseLoader.tsx +71 -0
  42. package/src/components/StatusBarController.tsx +42 -0
  43. package/src/components/StepHeader.tsx +56 -0
  44. package/src/components/StepIndicator.tsx +74 -0
  45. package/src/components/Typography.tsx +69 -0
  46. package/src/components/fonts.ts +49 -0
  47. package/src/components/glass/GlassGroup.tsx +34 -0
  48. package/src/components/glass/GlassSurface.tsx +64 -0
  49. package/src/components/runtime.tsx +93 -0
  50. package/src/components/toast.tsx +154 -0
  51. package/src/components/useBranding.ts +27 -0
  52. package/src/components/useVideoRecorder.ts +122 -0
  53. package/src/config/captureSettings.ts +67 -0
  54. package/src/config/idTypes.ts +79 -0
  55. package/src/config/theme.ts +186 -0
  56. package/src/index.ts +54 -0
  57. package/src/liveness/challengeManager.ts +130 -0
  58. package/src/liveness/faceDetector.ts +79 -0
  59. package/src/liveness/gestureDetector.ts +80 -0
  60. package/src/liveness/speech.ts +66 -0
  61. package/src/liveness/types.ts +99 -0
  62. package/src/liveness/useLiveness.ts +484 -0
  63. package/src/liveness/visionCameraFaceDetector.ts +118 -0
  64. package/src/screens/ConsentStep.tsx +164 -0
  65. package/src/screens/DocumentCaptureStep.tsx +500 -0
  66. package/src/screens/IdInputStep.tsx +79 -0
  67. package/src/screens/IdTypeStep.tsx +142 -0
  68. package/src/screens/LivenessAvatar.tsx +69 -0
  69. package/src/screens/LivenessStep.tsx +615 -0
  70. package/src/screens/SubmittedStep.tsx +177 -0
  71. package/src/services/api.ts +291 -0
  72. package/src/services/cardCrop.ts +52 -0
  73. package/src/services/deviceMetadata.ts +185 -0
  74. package/src/services/errors.ts +92 -0
  75. package/src/services/mediaCompress.ts +129 -0
  76. package/src/services/resolveUrl.ts +98 -0
  77. package/src/services/retry.ts +70 -0
  78. package/src/services/validators.ts +103 -0
  79. package/src/specs/MyazaFaceDetector.nitro.ts +44 -0
  80. package/src/store/kycStore.ts +288 -0
  81. package/src/store/serverConfig.ts +78 -0
  82. package/src/types/config.ts +239 -0
  83. package/src/types/country-flag-icons.d.ts +6 -0
  84. package/src/types/verification.ts +79 -0
  85. package/src/utils/platform.ts +23 -0
  86. package/src/utils/tokens.ts +10 -0
  87. package/src/utils/uuid.ts +31 -0
@@ -0,0 +1,79 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Submission callback payload (returned to onSubmit)
3
+ // ---------------------------------------------------------------------------
4
+
5
+ export interface KYCSubmission {
6
+ verificationId: string;
7
+ status: 'pending';
8
+ metadata: Record<string, string>;
9
+ submittedAt: string;
10
+ }
11
+
12
+ // ---------------------------------------------------------------------------
13
+ // Technical error types (onError callback)
14
+ // ---------------------------------------------------------------------------
15
+
16
+ /**
17
+ * Typed, documented technical-error categories surfaced through `onError`.
18
+ * These are IDENTICAL to the web + Flutter SDKs' codes so integrators get one
19
+ * consistent contract across all three platforms.
20
+ *
21
+ * - `network_error` — connection failure / timeout (after retries)
22
+ * - `invalid_api_key` — server returned 401
23
+ * - `insufficient_credits` — server returned 402 (see `details`)
24
+ * - `upload_failed` — `POST /api/kyc/upload` failed (after retries)
25
+ * - `camera_permission_denied` — the user denied (or the OS blocks) camera
26
+ * access; capture cannot proceed
27
+ * - `feature_disabled` — server returned 403 (ID type or a verification
28
+ * feature is not enabled for the org)
29
+ * - `unknown` — anything else
30
+ *
31
+ * > Voice guidance is text-to-speech *output* — it never records audio, so
32
+ * > there is no microphone-permission error code.
33
+ */
34
+ export type KYCErrorCode =
35
+ | 'network_error'
36
+ | 'invalid_api_key'
37
+ | 'insufficient_credits'
38
+ | 'upload_failed'
39
+ | 'camera_permission_denied'
40
+ | 'feature_disabled'
41
+ | 'unknown';
42
+
43
+ export interface KYCErrorDetails {
44
+ required?: number;
45
+ balance?: number;
46
+ currency?: string;
47
+ }
48
+
49
+ /**
50
+ * The error instance passed to `onError`. It is a real `Error` (so existing
51
+ * `onError: (error: Error) => void` handlers keep working) that additionally
52
+ * carries a typed `code` and optional `details`. Narrow with `instanceof
53
+ * KYCError` (or read `error.code`) to branch on the category.
54
+ */
55
+ export class KYCError extends Error {
56
+ readonly code: KYCErrorCode;
57
+ readonly details?: KYCErrorDetails;
58
+
59
+ constructor(code: KYCErrorCode, message: string, details?: KYCErrorDetails) {
60
+ super(message);
61
+ this.name = 'KYCError';
62
+ this.code = code;
63
+ this.details = details;
64
+ // Restore the prototype chain for `instanceof` after transpilation.
65
+ Object.setPrototypeOf(this, KYCError.prototype);
66
+ }
67
+ }
68
+
69
+ // ---------------------------------------------------------------------------
70
+ // API call status (used by stores)
71
+ // ---------------------------------------------------------------------------
72
+
73
+ export type ApiStatus = 'idle' | 'loading' | 'success' | 'error';
74
+
75
+ export interface ApiError {
76
+ message: string;
77
+ code?: string;
78
+ statusCode?: number;
79
+ }
@@ -0,0 +1,23 @@
1
+ // Thin wrapper around React Native's `Platform` so the SDK's pure-logic modules
2
+ // (resolveUrl, deviceMetadata) stay testable under a plain Node test runner —
3
+ // where the `react-native` module isn't resolvable. Under Metro/RN this reads
4
+ // the real `Platform.OS`; under Node it falls back to `'ios'`.
5
+ //
6
+ // This is the ONLY place the SDK reaches for `Platform` outside of React
7
+ // components, so the platform concern is isolated to a single file.
8
+
9
+ export type PlatformOS = 'ios' | 'android' | 'windows' | 'macos' | 'web';
10
+
11
+ function readOS(): PlatformOS {
12
+ try {
13
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
14
+ const rn = require('react-native') as { Platform?: { OS?: PlatformOS } };
15
+ return rn?.Platform?.OS ?? 'ios';
16
+ } catch {
17
+ return 'ios';
18
+ }
19
+ }
20
+
21
+ export const OS: PlatformOS = readOS();
22
+ export const isAndroid = OS === 'android';
23
+ export const isIOS = OS === 'ios';
@@ -0,0 +1,10 @@
1
+ import type { MyazaKYCConfig } from '../types/config';
2
+
3
+ // Replaces {firstName} / {lastName} tokens with values from userData (or ''),
4
+ // mirroring the Flutter SDK's `_fillTokens` and the web SDK's token handling.
5
+ export function fillTokens(template: string, userData: MyazaKYCConfig['userData']): string {
6
+ return template
7
+ .replace(/\{firstName\}/g, userData?.firstName ?? '')
8
+ .replace(/\{lastName\}/g, userData?.lastName ?? '')
9
+ .trim();
10
+ }
@@ -0,0 +1,31 @@
1
+ // Best-effort UUID/request-id generator. Prefers `expo-crypto`'s native
2
+ // randomUUID when available, falling back to a Math.random()-based v4 (good
3
+ // enough for a request correlation id — not used for anything security-sensitive).
4
+
5
+ interface ExpoCryptoModule {
6
+ randomUUID?: () => string;
7
+ }
8
+
9
+ function fallbackUuid(): string {
10
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
11
+ const r = (Math.random() * 16) | 0;
12
+ const v = c === 'x' ? r : (r & 0x3) | 0x8;
13
+ return v.toString(16);
14
+ });
15
+ }
16
+
17
+ export function uuid(): string {
18
+ try {
19
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
20
+ const crypto = require('expo-crypto') as ExpoCryptoModule;
21
+ if (crypto?.randomUUID) return crypto.randomUUID();
22
+ } catch {
23
+ /* expo-crypto not installed — fall through */
24
+ }
25
+ return fallbackUuid();
26
+ }
27
+
28
+ /** Prefixed request id sent as `metadata.requestId` on every verify. */
29
+ export function generateRequestId(): string {
30
+ return `kyc_${uuid()}`;
31
+ }