petrus-react-native 0.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 (163) hide show
  1. package/PetrusReactNative.podspec +20 -0
  2. package/android/build.gradle +64 -0
  3. package/android/src/main/AndroidManifest.xml +4 -0
  4. package/android/src/main/java/com/petrusreactnative/PDF417ScanSession.kt +86 -0
  5. package/android/src/main/java/com/petrusreactnative/PassportScanSession.kt +137 -0
  6. package/android/src/main/java/com/petrusreactnative/PetrusCameraView.kt +146 -0
  7. package/android/src/main/java/com/petrusreactnative/PetrusCameraViewManager.kt +93 -0
  8. package/android/src/main/java/com/petrusreactnative/PetrusOverlayView.kt +87 -0
  9. package/android/src/main/java/com/petrusreactnative/PetrusReactNativeModule.kt +253 -0
  10. package/android/src/main/java/com/petrusreactnative/PetrusReactNativePackage.kt +38 -0
  11. package/android/src/main/java/com/petrusreactnative/VehicleRegistrationScanSession.kt +119 -0
  12. package/android/src/main/java/com/petrusreactnative/events/CapturedEvent.kt +30 -0
  13. package/android/src/main/java/com/petrusreactnative/events/DocumentDetectedEvent.kt +49 -0
  14. package/android/src/main/java/com/petrusreactnative/events/FrameMetadataEvent.kt +24 -0
  15. package/android/src/main/java/com/petrusreactnative/mrz/PassportResultMapping.kt +54 -0
  16. package/android/src/main/java/com/petrusreactnative/ocr/OCRResultMapping.kt +52 -0
  17. package/android/src/main/java/com/petrusreactnative/pdf417/SouthAfricanDriversLicenseResultMapping.kt +80 -0
  18. package/android/src/main/java/com/petrusreactnative/sa/SouthAfricanIDResultMapping.kt +50 -0
  19. package/android/src/main/java/com/petrusreactnative/vehicle/VehicleRegistrationResultMapping.kt +72 -0
  20. package/ios/PetrusReactNative.h +5 -0
  21. package/ios/PetrusReactNative.mm +21 -0
  22. package/lib/module/NativePetrusReactNative.js +5 -0
  23. package/lib/module/NativePetrusReactNative.js.map +1 -0
  24. package/lib/module/PetrusCameraView.js +6 -0
  25. package/lib/module/PetrusCameraView.js.map +1 -0
  26. package/lib/module/PetrusCameraView.native.js +24 -0
  27. package/lib/module/PetrusCameraView.native.js.map +1 -0
  28. package/lib/module/PetrusCameraViewNativeComponent.ts +47 -0
  29. package/lib/module/cameraPermissions.js +9 -0
  30. package/lib/module/cameraPermissions.js.map +1 -0
  31. package/lib/module/cameraPermissions.native.js +10 -0
  32. package/lib/module/cameraPermissions.native.js.map +1 -0
  33. package/lib/module/getPipelineVersion.js +6 -0
  34. package/lib/module/getPipelineVersion.js.map +1 -0
  35. package/lib/module/getPipelineVersion.native.js +7 -0
  36. package/lib/module/getPipelineVersion.native.js.map +1 -0
  37. package/lib/module/index.js +45 -0
  38. package/lib/module/index.js.map +1 -0
  39. package/lib/module/package.json +1 -0
  40. package/lib/module/parseMRZ.js +6 -0
  41. package/lib/module/parseMRZ.js.map +1 -0
  42. package/lib/module/parseMRZ.native.js +12 -0
  43. package/lib/module/parseMRZ.native.js.map +1 -0
  44. package/lib/module/parseSouthAfricanDriversLicense.js +6 -0
  45. package/lib/module/parseSouthAfricanDriversLicense.js.map +1 -0
  46. package/lib/module/parseSouthAfricanDriversLicense.native.js +12 -0
  47. package/lib/module/parseSouthAfricanDriversLicense.native.js.map +1 -0
  48. package/lib/module/parseSouthAfricanID.js +6 -0
  49. package/lib/module/parseSouthAfricanID.js.map +1 -0
  50. package/lib/module/parseSouthAfricanID.native.js +8 -0
  51. package/lib/module/parseSouthAfricanID.native.js.map +1 -0
  52. package/lib/module/parseVehicleRegistration.js +6 -0
  53. package/lib/module/parseVehicleRegistration.js.map +1 -0
  54. package/lib/module/parseVehicleRegistration.native.js +8 -0
  55. package/lib/module/parseVehicleRegistration.native.js.map +1 -0
  56. package/lib/module/recognizeText.js +6 -0
  57. package/lib/module/recognizeText.js.map +1 -0
  58. package/lib/module/recognizeText.native.js +8 -0
  59. package/lib/module/recognizeText.native.js.map +1 -0
  60. package/lib/module/scanPDF417.js +6 -0
  61. package/lib/module/scanPDF417.js.map +1 -0
  62. package/lib/module/scanPDF417.native.js +8 -0
  63. package/lib/module/scanPDF417.native.js.map +1 -0
  64. package/lib/module/scanPassport.js +6 -0
  65. package/lib/module/scanPassport.js.map +1 -0
  66. package/lib/module/scanPassport.native.js +13 -0
  67. package/lib/module/scanPassport.native.js.map +1 -0
  68. package/lib/module/scanSouthAfricanDriversLicense.js +6 -0
  69. package/lib/module/scanSouthAfricanDriversLicense.js.map +1 -0
  70. package/lib/module/scanSouthAfricanDriversLicense.native.js +12 -0
  71. package/lib/module/scanSouthAfricanDriversLicense.native.js.map +1 -0
  72. package/lib/module/scanVehicleRegistration.js +6 -0
  73. package/lib/module/scanVehicleRegistration.js.map +1 -0
  74. package/lib/module/scanVehicleRegistration.native.js +13 -0
  75. package/lib/module/scanVehicleRegistration.native.js.map +1 -0
  76. package/lib/module/types.js +2 -0
  77. package/lib/module/types.js.map +1 -0
  78. package/lib/typescript/package.json +1 -0
  79. package/lib/typescript/src/NativePetrusReactNative.d.ts +271 -0
  80. package/lib/typescript/src/NativePetrusReactNative.d.ts.map +1 -0
  81. package/lib/typescript/src/PetrusCameraView.d.ts +10 -0
  82. package/lib/typescript/src/PetrusCameraView.d.ts.map +1 -0
  83. package/lib/typescript/src/PetrusCameraView.native.d.ts +4 -0
  84. package/lib/typescript/src/PetrusCameraView.native.d.ts.map +1 -0
  85. package/lib/typescript/src/PetrusCameraViewNativeComponent.d.ts +38 -0
  86. package/lib/typescript/src/PetrusCameraViewNativeComponent.d.ts.map +1 -0
  87. package/lib/typescript/src/cameraPermissions.d.ts +4 -0
  88. package/lib/typescript/src/cameraPermissions.d.ts.map +1 -0
  89. package/lib/typescript/src/cameraPermissions.native.d.ts +4 -0
  90. package/lib/typescript/src/cameraPermissions.native.d.ts.map +1 -0
  91. package/lib/typescript/src/getPipelineVersion.d.ts +2 -0
  92. package/lib/typescript/src/getPipelineVersion.d.ts.map +1 -0
  93. package/lib/typescript/src/getPipelineVersion.native.d.ts +2 -0
  94. package/lib/typescript/src/getPipelineVersion.native.d.ts.map +1 -0
  95. package/lib/typescript/src/index.d.ts +45 -0
  96. package/lib/typescript/src/index.d.ts.map +1 -0
  97. package/lib/typescript/src/parseMRZ.d.ts +3 -0
  98. package/lib/typescript/src/parseMRZ.d.ts.map +1 -0
  99. package/lib/typescript/src/parseMRZ.native.d.ts +8 -0
  100. package/lib/typescript/src/parseMRZ.native.d.ts.map +1 -0
  101. package/lib/typescript/src/parseSouthAfricanDriversLicense.d.ts +3 -0
  102. package/lib/typescript/src/parseSouthAfricanDriversLicense.d.ts.map +1 -0
  103. package/lib/typescript/src/parseSouthAfricanDriversLicense.native.d.ts +8 -0
  104. package/lib/typescript/src/parseSouthAfricanDriversLicense.native.d.ts.map +1 -0
  105. package/lib/typescript/src/parseSouthAfricanID.d.ts +3 -0
  106. package/lib/typescript/src/parseSouthAfricanID.d.ts.map +1 -0
  107. package/lib/typescript/src/parseSouthAfricanID.native.d.ts +4 -0
  108. package/lib/typescript/src/parseSouthAfricanID.native.d.ts.map +1 -0
  109. package/lib/typescript/src/parseVehicleRegistration.d.ts +3 -0
  110. package/lib/typescript/src/parseVehicleRegistration.d.ts.map +1 -0
  111. package/lib/typescript/src/parseVehicleRegistration.native.d.ts +4 -0
  112. package/lib/typescript/src/parseVehicleRegistration.native.d.ts.map +1 -0
  113. package/lib/typescript/src/recognizeText.d.ts +3 -0
  114. package/lib/typescript/src/recognizeText.d.ts.map +1 -0
  115. package/lib/typescript/src/recognizeText.native.d.ts +4 -0
  116. package/lib/typescript/src/recognizeText.native.d.ts.map +1 -0
  117. package/lib/typescript/src/scanPDF417.d.ts +3 -0
  118. package/lib/typescript/src/scanPDF417.d.ts.map +1 -0
  119. package/lib/typescript/src/scanPDF417.native.d.ts +4 -0
  120. package/lib/typescript/src/scanPDF417.native.d.ts.map +1 -0
  121. package/lib/typescript/src/scanPassport.d.ts +3 -0
  122. package/lib/typescript/src/scanPassport.d.ts.map +1 -0
  123. package/lib/typescript/src/scanPassport.native.d.ts +9 -0
  124. package/lib/typescript/src/scanPassport.native.d.ts.map +1 -0
  125. package/lib/typescript/src/scanSouthAfricanDriversLicense.d.ts +3 -0
  126. package/lib/typescript/src/scanSouthAfricanDriversLicense.d.ts.map +1 -0
  127. package/lib/typescript/src/scanSouthAfricanDriversLicense.native.d.ts +8 -0
  128. package/lib/typescript/src/scanSouthAfricanDriversLicense.native.d.ts.map +1 -0
  129. package/lib/typescript/src/scanVehicleRegistration.d.ts +3 -0
  130. package/lib/typescript/src/scanVehicleRegistration.d.ts.map +1 -0
  131. package/lib/typescript/src/scanVehicleRegistration.native.d.ts +9 -0
  132. package/lib/typescript/src/scanVehicleRegistration.native.d.ts.map +1 -0
  133. package/lib/typescript/src/types.d.ts +237 -0
  134. package/lib/typescript/src/types.d.ts.map +1 -0
  135. package/package.json +124 -0
  136. package/src/NativePetrusReactNative.ts +303 -0
  137. package/src/PetrusCameraView.native.tsx +44 -0
  138. package/src/PetrusCameraView.tsx +19 -0
  139. package/src/PetrusCameraViewNativeComponent.ts +47 -0
  140. package/src/cameraPermissions.native.tsx +10 -0
  141. package/src/cameraPermissions.tsx +13 -0
  142. package/src/getPipelineVersion.native.tsx +5 -0
  143. package/src/getPipelineVersion.tsx +5 -0
  144. package/src/index.tsx +83 -0
  145. package/src/parseMRZ.native.tsx +11 -0
  146. package/src/parseMRZ.tsx +7 -0
  147. package/src/parseSouthAfricanDriversLicense.native.tsx +13 -0
  148. package/src/parseSouthAfricanDriversLicense.tsx +9 -0
  149. package/src/parseSouthAfricanID.native.tsx +7 -0
  150. package/src/parseSouthAfricanID.tsx +7 -0
  151. package/src/parseVehicleRegistration.native.tsx +9 -0
  152. package/src/parseVehicleRegistration.tsx +9 -0
  153. package/src/recognizeText.native.tsx +7 -0
  154. package/src/recognizeText.tsx +7 -0
  155. package/src/scanPDF417.native.tsx +7 -0
  156. package/src/scanPDF417.tsx +7 -0
  157. package/src/scanPassport.native.tsx +12 -0
  158. package/src/scanPassport.tsx +7 -0
  159. package/src/scanSouthAfricanDriversLicense.native.tsx +11 -0
  160. package/src/scanSouthAfricanDriversLicense.tsx +7 -0
  161. package/src/scanVehicleRegistration.native.tsx +12 -0
  162. package/src/scanVehicleRegistration.tsx +7 -0
  163. package/src/types.ts +272 -0
@@ -0,0 +1,303 @@
1
+ import { TurboModuleRegistry, type TurboModule } from 'react-native';
2
+
3
+ export interface Spec extends TurboModule {
4
+ // Phase 0 placeholder: proves the JS <-> native TurboModule <-> petrus-core
5
+ // wiring works end to end. Replaced by the real capture/detect/OCR/parse API
6
+ // surface in later phases.
7
+ getPipelineVersion(): string;
8
+
9
+ // Phase 1: camera runtime permission (Android only -- see PetrusReactNativeModule.kt).
10
+ checkPermission(): Promise<'granted' | 'denied' | 'blocked'>;
11
+ requestPermission(): Promise<'granted' | 'denied' | 'blocked'>;
12
+
13
+ // Phase 3: ML Kit-based OCR (Android only). Raw text/boxes/confidence -- no
14
+ // document-specific field parsing. `imagePath` may be a bare filesystem path or a
15
+ // URI (file://, content://, ...).
16
+ recognizeText(imagePath: string): Promise<{
17
+ fullText: string;
18
+ confidence: number;
19
+ blocks: Array<{
20
+ text: string;
21
+ boundingBox: {
22
+ left: number;
23
+ top: number;
24
+ right: number;
25
+ bottom: number;
26
+ };
27
+ lines: Array<{
28
+ text: string;
29
+ confidence: number;
30
+ boundingBox: {
31
+ left: number;
32
+ top: number;
33
+ right: number;
34
+ bottom: number;
35
+ };
36
+ words: Array<{
37
+ text: string;
38
+ confidence: number;
39
+ boundingBox: {
40
+ left: number;
41
+ top: number;
42
+ right: number;
43
+ bottom: number;
44
+ };
45
+ }>;
46
+ }>;
47
+ }>;
48
+ }>;
49
+
50
+ // Phase 4: SA ID parsing (Android only). Pure CPU work (regex + arithmetic on a
51
+ // short string) -- synchronous, no Promise needed, same as getPipelineVersion.
52
+ // `text` is expected to be OCR output (e.g. recognizeText's `fullText`), not tied
53
+ // to any specific OCR engine.
54
+ parseSouthAfricanID(text: string): {
55
+ idNumber: string | null;
56
+ isValid: boolean;
57
+ dateOfBirth: {
58
+ year: number;
59
+ month: number;
60
+ day: number;
61
+ } | null;
62
+ gender: 'male' | 'female' | null;
63
+ citizenship: 'citizen' | 'permanent_resident' | 'refugee' | 'unknown' | null;
64
+ validation: {
65
+ isValid: boolean;
66
+ hasValidChecksum: boolean;
67
+ hasValidDateOfBirth: boolean;
68
+ hasValidCitizenshipDigit: boolean;
69
+ } | null;
70
+ };
71
+
72
+ // Phase 5: PDF417 barcode scanning + SA driver's licence parsing (Android only).
73
+ // See the README's confidence note on the reverse-engineered barcode format
74
+ // before relying on the decoded *licence fields* in production -- the barcode
75
+ // detection/decoding itself (ZXing) has no such caveat.
76
+
77
+ // Decodes a PDF417 barcode from a still image. `imagePath` may be a bare
78
+ // filesystem path or a URI. Rejects (does not resolve null) if no barcode is
79
+ // found in the image -- there's no meaningful "empty" PDF417 scan result.
80
+ scanPDF417(imagePath: string): Promise<{
81
+ /** Base64-encoded raw decoded barcode bytes (binary for SA licence barcodes). */
82
+ rawDataBase64: string;
83
+ /** Best-effort ISO-8859-1 text view of the same bytes; rarely meaningful for encrypted payloads. */
84
+ rawText: string;
85
+ }>;
86
+
87
+ // Parses already-scanned raw barcode bytes (e.g. scanPDF417's rawDataBase64) into
88
+ // SA driver's licence fields. Synchronous -- pure CPU work (RSA modPow over a few
89
+ // hundred bytes + nibble parsing), no I/O. Throws if rawDataBase64 doesn't decode
90
+ // to a recognized SA driver's licence barcode format -- unlike parseSouthAfricanID,
91
+ // there's no meaningful partial/not-found result to return here since this is
92
+ // expected to be called on data that already came from a barcode scan.
93
+ parseSouthAfricanDriversLicense(rawDataBase64: string): {
94
+ version: 'v1' | 'v2';
95
+ surname: string;
96
+ initials: string;
97
+ idNumber: string | null;
98
+ idNumberValidation: {
99
+ isValid: boolean;
100
+ hasValidChecksum: boolean;
101
+ hasValidDateOfBirth: boolean;
102
+ hasValidCitizenshipDigit: boolean;
103
+ } | null;
104
+ licenseNumber: string;
105
+ vehicleCodes: string[];
106
+ vehicleRestrictions: string[];
107
+ prdpCode: string | null;
108
+ idCountryOfIssue: string;
109
+ licenseCountryOfIssue: string;
110
+ gender: 'male' | 'female' | null;
111
+ dateOfBirth: { year: number; month: number; day: number } | null;
112
+ licenseIssueNumber: number | null;
113
+ licenseValidFrom: { year: number; month: number; day: number } | null;
114
+ licenseValidTo: { year: number; month: number; day: number } | null;
115
+ prdpExpiry: { year: number; month: number; day: number } | null;
116
+ driverRestrictionCodes: number[];
117
+ parseWarnings: string[];
118
+ };
119
+
120
+ // Convenience: opens a headless (no preview UI) camera session, scans for a
121
+ // PDF417 barcode, and parses it as an SA driver's licence in one call -- i.e.
122
+ // scanPDF417 + parseSouthAfricanDriversLicense composed natively. Rejects on
123
+ // timeout (~20s) or if no Activity is available, rather than resolving null.
124
+ scanSouthAfricanDriversLicense(): Promise<{
125
+ version: 'v1' | 'v2';
126
+ surname: string;
127
+ initials: string;
128
+ idNumber: string | null;
129
+ idNumberValidation: {
130
+ isValid: boolean;
131
+ hasValidChecksum: boolean;
132
+ hasValidDateOfBirth: boolean;
133
+ hasValidCitizenshipDigit: boolean;
134
+ } | null;
135
+ licenseNumber: string;
136
+ vehicleCodes: string[];
137
+ vehicleRestrictions: string[];
138
+ prdpCode: string | null;
139
+ idCountryOfIssue: string;
140
+ licenseCountryOfIssue: string;
141
+ gender: 'male' | 'female' | null;
142
+ dateOfBirth: { year: number; month: number; day: number } | null;
143
+ licenseIssueNumber: number | null;
144
+ licenseValidFrom: { year: number; month: number; day: number } | null;
145
+ licenseValidTo: { year: number; month: number; day: number } | null;
146
+ prdpExpiry: { year: number; month: number; day: number } | null;
147
+ driverRestrictionCodes: number[];
148
+ parseWarnings: string[];
149
+ }>;
150
+
151
+ // Phase 6: SA vehicle registration document parsing (Android only). Label
152
+ // wording is based on general knowledge of NATIS/eNaTIS documents, not verified
153
+ // against a physical sample -- see the README's confidence note before relying
154
+ // on extracted fields in production. Government API integration, face matching,
155
+ // driver's licence, and passport parsing are explicitly out of scope here.
156
+
157
+ // Parses OCR text (e.g. recognizeText's `fullText`) into vehicle registration
158
+ // fields. Synchronous -- pure CPU work (regex-based field extraction), same
159
+ // reasoning as parseSouthAfricanID. Never throws for unrecognized/partial text --
160
+ // returns as much as could be extracted, with `documentType: 'unknown'` and/or
161
+ // `parseWarnings` entries flagging what looked off.
162
+ parseVehicleRegistration(text: string): {
163
+ documentType:
164
+ | 'registration_certificate'
165
+ | 'license_disc'
166
+ | 'notification_of_change'
167
+ | 'roadworthy_certificate'
168
+ | 'unknown';
169
+ registrationNumber: string | null;
170
+ vin: string | null;
171
+ vinValidation: {
172
+ hasValidLength: boolean;
173
+ hasValidCharacterSet: boolean;
174
+ isStructurallyValid: boolean;
175
+ northAmericanCheckDigitValid: boolean | null;
176
+ } | null;
177
+ engineNumber: string | null;
178
+ make: string | null;
179
+ model: string | null;
180
+ yearModel: number | null;
181
+ ownerName: string | null;
182
+ ownerIdNumber: string | null;
183
+ ownerIdValidation: {
184
+ isValid: boolean;
185
+ hasValidChecksum: boolean;
186
+ hasValidDateOfBirth: boolean;
187
+ hasValidCitizenshipDigit: boolean;
188
+ } | null;
189
+ validation: {
190
+ isValid: boolean;
191
+ hasStructurallyValidVin: boolean;
192
+ hasPlausibleRegistrationNumber: boolean;
193
+ hasPlausibleYearModel: boolean;
194
+ };
195
+ parseWarnings: string[];
196
+ };
197
+
198
+ // Convenience: opens a headless (no preview UI) camera session, runs OCR on
199
+ // frames, and parses each result as a vehicle registration document in one call
200
+ // -- stops once a frame yields a registration number or VIN, or the scan window
201
+ // (~20s) elapses. Rejects on timeout or if no Activity is available, rather than
202
+ // resolving null (same convention as scanSouthAfricanDriversLicense).
203
+ scanVehicleRegistration(): Promise<{
204
+ documentType:
205
+ | 'registration_certificate'
206
+ | 'license_disc'
207
+ | 'notification_of_change'
208
+ | 'roadworthy_certificate'
209
+ | 'unknown';
210
+ registrationNumber: string | null;
211
+ vin: string | null;
212
+ vinValidation: {
213
+ hasValidLength: boolean;
214
+ hasValidCharacterSet: boolean;
215
+ isStructurallyValid: boolean;
216
+ northAmericanCheckDigitValid: boolean | null;
217
+ } | null;
218
+ engineNumber: string | null;
219
+ make: string | null;
220
+ model: string | null;
221
+ yearModel: number | null;
222
+ ownerName: string | null;
223
+ ownerIdNumber: string | null;
224
+ ownerIdValidation: {
225
+ isValid: boolean;
226
+ hasValidChecksum: boolean;
227
+ hasValidDateOfBirth: boolean;
228
+ hasValidCitizenshipDigit: boolean;
229
+ } | null;
230
+ validation: {
231
+ isValid: boolean;
232
+ hasStructurallyValidVin: boolean;
233
+ hasPlausibleRegistrationNumber: boolean;
234
+ hasPlausibleYearModel: boolean;
235
+ };
236
+ parseWarnings: string[];
237
+ }>;
238
+
239
+ // Phase 7: ICAO 9303 TD3 (passport) MRZ parsing (Android only). Everything
240
+ // runs on-device -- ML Kit text recognition is on-device, and MRZChecksum/
241
+ // MRZParser/PassportParser are pure Kotlin with no network calls. NFC chip
242
+ // reading, face matching, visa parsing (TD1/TD2), driver's licence, and
243
+ // vehicle documents are explicitly out of scope for this phase.
244
+
245
+ // Parses MRZ text (e.g. recognizeText's `fullText`, already cropped to the MRZ
246
+ // region, or pasted raw) into passport fields. Synchronous -- pure CPU work
247
+ // (regex + checksum arithmetic over two 44-character lines), same reasoning as
248
+ // parseSouthAfricanID/parseVehicleRegistration. Never throws/rejects -- when no
249
+ // MRZ-shaped line pair can be located in the text at all, every string field
250
+ // comes back empty and `parseWarnings` explains why, same "always return a
251
+ // result object" convention as parseSouthAfricanID's null idNumber.
252
+ parseMRZ(text: string): {
253
+ documentCode: string;
254
+ issuingCountry: string;
255
+ surname: string;
256
+ givenNames: string;
257
+ passportNumber: string;
258
+ nationality: string;
259
+ dateOfBirth: { year: number; month: number; day: number; twoDigitYear: number } | null;
260
+ sex: 'male' | 'female' | 'unspecified';
261
+ dateOfExpiry: { year: number; month: number; day: number; twoDigitYear: number } | null;
262
+ personalNumber: string | null;
263
+ validation: {
264
+ isValid: boolean;
265
+ passportNumberCheckValid: boolean;
266
+ dateOfBirthCheckValid: boolean;
267
+ expiryDateCheckValid: boolean;
268
+ personalNumberCheckValid: boolean;
269
+ compositeCheckValid: boolean;
270
+ };
271
+ parseWarnings: string[];
272
+ };
273
+
274
+ // Convenience: opens a headless (no preview UI) camera session; per frame,
275
+ // detects the document boundary, crops just the MRZ band (ICAO 9303's
276
+ // Effective Reading Zone geometry), runs OCR on *only that crop*, and parses
277
+ // it -- stops once a frame yields a non-empty passport number, or the scan
278
+ // window (~20s) elapses. Rejects on timeout or if no Activity is available
279
+ // (same convention as scanSouthAfricanDriversLicense/scanVehicleRegistration).
280
+ scanPassport(): Promise<{
281
+ documentCode: string;
282
+ issuingCountry: string;
283
+ surname: string;
284
+ givenNames: string;
285
+ passportNumber: string;
286
+ nationality: string;
287
+ dateOfBirth: { year: number; month: number; day: number; twoDigitYear: number } | null;
288
+ sex: 'male' | 'female' | 'unspecified';
289
+ dateOfExpiry: { year: number; month: number; day: number; twoDigitYear: number } | null;
290
+ personalNumber: string | null;
291
+ validation: {
292
+ isValid: boolean;
293
+ passportNumberCheckValid: boolean;
294
+ dateOfBirthCheckValid: boolean;
295
+ expiryDateCheckValid: boolean;
296
+ personalNumberCheckValid: boolean;
297
+ compositeCheckValid: boolean;
298
+ };
299
+ parseWarnings: string[];
300
+ }>;
301
+ }
302
+
303
+ export default TurboModuleRegistry.getEnforcing<Spec>('PetrusReactNative');
@@ -0,0 +1,44 @@
1
+ import type { NativeSyntheticEvent } from 'react-native';
2
+ import NativePetrusCameraView from './PetrusCameraViewNativeComponent';
3
+ import type {
4
+ PetrusFrameMetadata,
5
+ PetrusDocumentDetectedEvent,
6
+ PetrusCapturedEvent,
7
+ } from './types';
8
+ import type { PetrusCameraViewProps } from './PetrusCameraView';
9
+
10
+ export type { PetrusCameraViewProps } from './PetrusCameraView';
11
+
12
+ export function PetrusCameraView({
13
+ onFrameMetadata,
14
+ onDocumentDetected,
15
+ onCaptured,
16
+ ...rest
17
+ }: PetrusCameraViewProps) {
18
+ return (
19
+ <NativePetrusCameraView
20
+ {...rest}
21
+ onFrameMetadata={
22
+ onFrameMetadata == null
23
+ ? undefined
24
+ : (event: NativeSyntheticEvent<PetrusFrameMetadata>) => {
25
+ onFrameMetadata(event.nativeEvent);
26
+ }
27
+ }
28
+ onDocumentDetected={
29
+ onDocumentDetected == null
30
+ ? undefined
31
+ : (event: NativeSyntheticEvent<PetrusDocumentDetectedEvent>) => {
32
+ onDocumentDetected(event.nativeEvent);
33
+ }
34
+ }
35
+ onCaptured={
36
+ onCaptured == null
37
+ ? undefined
38
+ : (event: NativeSyntheticEvent<PetrusCapturedEvent>) => {
39
+ onCaptured(event.nativeEvent);
40
+ }
41
+ }
42
+ />
43
+ );
44
+ }
@@ -0,0 +1,19 @@
1
+ import type { ViewProps } from 'react-native';
2
+ import type {
3
+ PetrusFrameMetadata,
4
+ PetrusDocumentDetectedEvent,
5
+ PetrusCapturedEvent,
6
+ } from './types';
7
+
8
+ export interface PetrusCameraViewProps extends ViewProps {
9
+ isActive?: boolean;
10
+ onFrameMetadata?: (metadata: PetrusFrameMetadata) => void;
11
+ onDocumentDetected?: (event: PetrusDocumentDetectedEvent) => void;
12
+ onCaptured?: (event: PetrusCapturedEvent) => void;
13
+ }
14
+
15
+ export function PetrusCameraView(_props: PetrusCameraViewProps): never {
16
+ throw new Error(
17
+ "'petrus-react-native's PetrusCameraView is only supported on native platforms."
18
+ );
19
+ }
@@ -0,0 +1,47 @@
1
+ import { codegenNativeComponent, type ViewProps, type CodegenTypes } from 'react-native';
2
+
3
+ type NativePoint2D = Readonly<{
4
+ x: CodegenTypes.Double;
5
+ y: CodegenTypes.Double;
6
+ }>;
7
+
8
+ // Always sent as a well-formed object (zeroed when nothing's detected), never
9
+ // null/omitted -- avoids relying on nullable/optional object support in the event
10
+ // codegen path. `detected`/callers should treat these as meaningless when unset.
11
+ type NativeDocumentCorners = Readonly<{
12
+ topLeft: NativePoint2D;
13
+ topRight: NativePoint2D;
14
+ bottomRight: NativePoint2D;
15
+ bottomLeft: NativePoint2D;
16
+ frameWidth: CodegenTypes.Int32;
17
+ frameHeight: CodegenTypes.Int32;
18
+ rotationDegrees: CodegenTypes.Int32;
19
+ }>;
20
+
21
+ export interface NativeProps extends ViewProps {
22
+ isActive?: CodegenTypes.WithDefault<boolean, false>;
23
+
24
+ onFrameMetadata?: CodegenTypes.DirectEventHandler<{
25
+ width: CodegenTypes.Int32;
26
+ height: CodegenTypes.Int32;
27
+ rotation: CodegenTypes.Int32;
28
+ // Epoch milliseconds -- exceeds Int32 range, so this must be Double.
29
+ timestamp: CodegenTypes.Double;
30
+ }>;
31
+
32
+ onDocumentDetected?: CodegenTypes.DirectEventHandler<{
33
+ detected: boolean;
34
+ isStable: boolean;
35
+ stableDurationMs: CodegenTypes.Double;
36
+ confidence: CodegenTypes.Double;
37
+ corners: NativeDocumentCorners;
38
+ }>;
39
+
40
+ onCaptured?: CodegenTypes.DirectEventHandler<{
41
+ corners: NativeDocumentCorners;
42
+ confidence: CodegenTypes.Double;
43
+ timestamp: CodegenTypes.Double;
44
+ }>;
45
+ }
46
+
47
+ export default codegenNativeComponent<NativeProps>('PetrusCameraView');
@@ -0,0 +1,10 @@
1
+ import PetrusReactNative from './NativePetrusReactNative';
2
+ import type { PetrusCameraPermissionStatus } from './types';
3
+
4
+ export function checkPermission(): Promise<PetrusCameraPermissionStatus> {
5
+ return PetrusReactNative.checkPermission();
6
+ }
7
+
8
+ export function requestPermission(): Promise<PetrusCameraPermissionStatus> {
9
+ return PetrusReactNative.requestPermission();
10
+ }
@@ -0,0 +1,13 @@
1
+ import type { PetrusCameraPermissionStatus } from './types';
2
+
3
+ export function checkPermission(): Promise<PetrusCameraPermissionStatus> {
4
+ return Promise.reject(
5
+ new Error("'petrus-react-native' is only supported on native platforms.")
6
+ );
7
+ }
8
+
9
+ export function requestPermission(): Promise<PetrusCameraPermissionStatus> {
10
+ return Promise.reject(
11
+ new Error("'petrus-react-native' is only supported on native platforms.")
12
+ );
13
+ }
@@ -0,0 +1,5 @@
1
+ import PetrusReactNative from './NativePetrusReactNative';
2
+
3
+ export function getPipelineVersion(): string {
4
+ return PetrusReactNative.getPipelineVersion();
5
+ }
@@ -0,0 +1,5 @@
1
+ export function getPipelineVersion(): string {
2
+ throw new Error(
3
+ "'petrus-react-native' is only supported on native platforms."
4
+ );
5
+ }
package/src/index.tsx ADDED
@@ -0,0 +1,83 @@
1
+ import { getPipelineVersion } from './getPipelineVersion';
2
+ import { checkPermission, requestPermission } from './cameraPermissions';
3
+ import { recognizeText } from './recognizeText';
4
+ import { parseSouthAfricanID } from './parseSouthAfricanID';
5
+ import { scanPDF417 } from './scanPDF417';
6
+ import { parseSouthAfricanDriversLicense } from './parseSouthAfricanDriversLicense';
7
+ import { scanSouthAfricanDriversLicense } from './scanSouthAfricanDriversLicense';
8
+ import { parseVehicleRegistration } from './parseVehicleRegistration';
9
+ import { scanVehicleRegistration } from './scanVehicleRegistration';
10
+ import { parseMRZ } from './parseMRZ';
11
+ import { scanPassport } from './scanPassport';
12
+
13
+ export { getPipelineVersion } from './getPipelineVersion';
14
+
15
+ export { PetrusCameraView } from './PetrusCameraView';
16
+ export type { PetrusCameraViewProps } from './PetrusCameraView';
17
+
18
+ export { checkPermission, requestPermission } from './cameraPermissions';
19
+
20
+ export { recognizeText } from './recognizeText';
21
+
22
+ export { parseSouthAfricanID } from './parseSouthAfricanID';
23
+
24
+ export { scanPDF417 } from './scanPDF417';
25
+ export { parseSouthAfricanDriversLicense } from './parseSouthAfricanDriversLicense';
26
+ export { scanSouthAfricanDriversLicense } from './scanSouthAfricanDriversLicense';
27
+
28
+ export { parseVehicleRegistration } from './parseVehicleRegistration';
29
+ export { scanVehicleRegistration } from './scanVehicleRegistration';
30
+
31
+ export { parseMRZ } from './parseMRZ';
32
+ export { scanPassport } from './scanPassport';
33
+
34
+ export type {
35
+ PetrusCameraPermissionStatus,
36
+ PetrusFrameMetadata,
37
+ PetrusPoint2D,
38
+ PetrusDocumentCorners,
39
+ PetrusDocumentDetectedEvent,
40
+ PetrusCapturedEvent,
41
+ OCRBoundingBox,
42
+ OCRWord,
43
+ OCRLine,
44
+ OCRBlock,
45
+ OCRResult,
46
+ SouthAfricanGender,
47
+ SouthAfricanCitizenship,
48
+ SouthAfricanDateOfBirth,
49
+ SouthAfricanIDValidation,
50
+ SouthAfricanIDResult,
51
+ PDF417ScanResult,
52
+ SouthAfricanDriversLicenseVersion,
53
+ CalendarDate,
54
+ SouthAfricanDriversLicenseResult,
55
+ VehicleDocumentType,
56
+ VINValidation,
57
+ VehicleRegistrationValidation,
58
+ VehicleRegistrationResult,
59
+ MRZSex,
60
+ MRZDate,
61
+ MRZValidation,
62
+ PassportResult,
63
+ } from './types';
64
+
65
+ /**
66
+ * Namespaced convenience alias over the same functions above (e.g.
67
+ * `Petrus.parseSouthAfricanID(text)`), for callers who prefer a single import over
68
+ * multiple named ones. Both forms call the same underlying implementation.
69
+ */
70
+ export const Petrus = {
71
+ getPipelineVersion,
72
+ checkPermission,
73
+ requestPermission,
74
+ recognizeText,
75
+ parseSouthAfricanID,
76
+ scanPDF417,
77
+ parseSouthAfricanDriversLicense,
78
+ scanSouthAfricanDriversLicense,
79
+ parseVehicleRegistration,
80
+ scanVehicleRegistration,
81
+ parseMRZ,
82
+ scanPassport,
83
+ };
@@ -0,0 +1,11 @@
1
+ import PetrusReactNative from './NativePetrusReactNative';
2
+ import type { PassportResult } from './types';
3
+
4
+ /**
5
+ * `text` is expected to be MRZ OCR output (e.g. recognizeText's `fullText`,
6
+ * already cropped to the MRZ region, or pasted raw two-line MRZ text). Never
7
+ * throws -- see PassportResult's doc comment for the "no MRZ found" shape.
8
+ */
9
+ export function parseMRZ(text: string): PassportResult {
10
+ return PetrusReactNative.parseMRZ(text);
11
+ }
@@ -0,0 +1,7 @@
1
+ import type { PassportResult } from './types';
2
+
3
+ export function parseMRZ(_text: string): PassportResult {
4
+ throw new Error(
5
+ "'petrus-react-native' is only supported on native platforms."
6
+ );
7
+ }
@@ -0,0 +1,13 @@
1
+ import PetrusReactNative from './NativePetrusReactNative';
2
+ import type { SouthAfricanDriversLicenseResult } from './types';
3
+
4
+ /**
5
+ * `rawDataBase64` is expected to be already-scanned raw barcode bytes (e.g.
6
+ * scanPDF417's `rawDataBase64`). Throws if it doesn't decode to a recognized SA
7
+ * driver's licence barcode format.
8
+ */
9
+ export function parseSouthAfricanDriversLicense(
10
+ rawDataBase64: string
11
+ ): SouthAfricanDriversLicenseResult {
12
+ return PetrusReactNative.parseSouthAfricanDriversLicense(rawDataBase64);
13
+ }
@@ -0,0 +1,9 @@
1
+ import type { SouthAfricanDriversLicenseResult } from './types';
2
+
3
+ export function parseSouthAfricanDriversLicense(
4
+ _rawDataBase64: string
5
+ ): SouthAfricanDriversLicenseResult {
6
+ throw new Error(
7
+ "'petrus-react-native' is only supported on native platforms."
8
+ );
9
+ }
@@ -0,0 +1,7 @@
1
+ import PetrusReactNative from './NativePetrusReactNative';
2
+ import type { SouthAfricanIDResult } from './types';
3
+
4
+ /** `text` is expected to be OCR output (e.g. recognizeText's `fullText`). */
5
+ export function parseSouthAfricanID(text: string): SouthAfricanIDResult {
6
+ return PetrusReactNative.parseSouthAfricanID(text);
7
+ }
@@ -0,0 +1,7 @@
1
+ import type { SouthAfricanIDResult } from './types';
2
+
3
+ export function parseSouthAfricanID(_text: string): SouthAfricanIDResult {
4
+ throw new Error(
5
+ "'petrus-react-native' is only supported on native platforms."
6
+ );
7
+ }
@@ -0,0 +1,9 @@
1
+ import PetrusReactNative from './NativePetrusReactNative';
2
+ import type { VehicleRegistrationResult } from './types';
3
+
4
+ /** `text` is expected to be OCR output (e.g. recognizeText's `fullText`). */
5
+ export function parseVehicleRegistration(
6
+ text: string
7
+ ): VehicleRegistrationResult {
8
+ return PetrusReactNative.parseVehicleRegistration(text);
9
+ }
@@ -0,0 +1,9 @@
1
+ import type { VehicleRegistrationResult } from './types';
2
+
3
+ export function parseVehicleRegistration(
4
+ _text: string
5
+ ): VehicleRegistrationResult {
6
+ throw new Error(
7
+ "'petrus-react-native' is only supported on native platforms."
8
+ );
9
+ }
@@ -0,0 +1,7 @@
1
+ import PetrusReactNative from './NativePetrusReactNative';
2
+ import type { OCRResult } from './types';
3
+
4
+ /** `imagePath` may be a bare filesystem path or a URI (file://, content://, ...). */
5
+ export function recognizeText(imagePath: string): Promise<OCRResult> {
6
+ return PetrusReactNative.recognizeText(imagePath);
7
+ }
@@ -0,0 +1,7 @@
1
+ import type { OCRResult } from './types';
2
+
3
+ export function recognizeText(_imagePath: string): Promise<OCRResult> {
4
+ return Promise.reject(
5
+ new Error("'petrus-react-native' is only supported on native platforms.")
6
+ );
7
+ }
@@ -0,0 +1,7 @@
1
+ import PetrusReactNative from './NativePetrusReactNative';
2
+ import type { PDF417ScanResult } from './types';
3
+
4
+ /** `imagePath` may be a bare filesystem path or a URI (file://, content://, ...). */
5
+ export function scanPDF417(imagePath: string): Promise<PDF417ScanResult> {
6
+ return PetrusReactNative.scanPDF417(imagePath);
7
+ }
@@ -0,0 +1,7 @@
1
+ import type { PDF417ScanResult } from './types';
2
+
3
+ export function scanPDF417(_imagePath: string): Promise<PDF417ScanResult> {
4
+ return Promise.reject(
5
+ new Error("'petrus-react-native' is only supported on native platforms.")
6
+ );
7
+ }
@@ -0,0 +1,12 @@
1
+ import PetrusReactNative from './NativePetrusReactNative';
2
+ import type { PassportResult } from './types';
3
+
4
+ /**
5
+ * Opens a headless (no preview UI) camera session; per frame, detects the
6
+ * document boundary, crops just the MRZ band, runs OCR on only that crop, and
7
+ * parses it -- stops once a frame yields a non-empty passport number. Rejects
8
+ * on timeout (~20s) or if no Activity is available.
9
+ */
10
+ export function scanPassport(): Promise<PassportResult> {
11
+ return PetrusReactNative.scanPassport();
12
+ }