@pagopa/io-react-native-iso18013 0.3.0 → 0.5.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 (110) hide show
  1. package/README.md +10 -5
  2. package/android/build.gradle +7 -1
  3. package/android/src/main/java/com/ioreactnativeiso18013/IoReactNativeCborModule.kt +69 -134
  4. package/android/src/main/java/com/ioreactnativeiso18013/IoReactNativeIso18013Module.kt +254 -183
  5. package/android/src/test/java/com/ioreactnativeiso18013/Base64UtilsTest.kt +66 -0
  6. package/android/src/test/java/com/ioreactnativeiso18013/IoReactNativeIso18013Test.kt +508 -0
  7. package/ios/Base64Utils.swift +10 -3
  8. package/ios/IoReactNativeCbor.mm +21 -21
  9. package/ios/IoReactNativeCbor.swift +116 -138
  10. package/ios/IoReactNativeIso18013.mm +10 -10
  11. package/ios/IoReactNativeIso18013.swift +172 -193
  12. package/lib/module/cbor/cbor/README.md +39 -59
  13. package/lib/module/cbor/cbor/decoder.js +13 -23
  14. package/lib/module/cbor/cbor/decoder.js.map +1 -1
  15. package/lib/module/cbor/cbor/error.js +15 -0
  16. package/lib/module/cbor/cbor/error.js.map +1 -0
  17. package/lib/module/cbor/cbor/index.js +1 -0
  18. package/lib/module/cbor/cbor/index.js.map +1 -1
  19. package/lib/module/cbor/cose/README.md +39 -9
  20. package/lib/module/cbor/cose/error.js +17 -0
  21. package/lib/module/cbor/cose/error.js.map +1 -0
  22. package/lib/module/cbor/cose/index.js +1 -0
  23. package/lib/module/cbor/cose/index.js.map +1 -1
  24. package/lib/module/cbor/cose/sign.js +4 -3
  25. package/lib/module/cbor/cose/sign.js.map +1 -1
  26. package/lib/module/iso18013/index.js +0 -1
  27. package/lib/module/iso18013/index.js.map +1 -1
  28. package/lib/module/iso18013/iso18013-5/README.md +120 -44
  29. package/lib/module/iso18013/iso18013-5/error.js +25 -0
  30. package/lib/module/iso18013/iso18013-5/error.js.map +1 -0
  31. package/lib/module/iso18013/iso18013-5/index.js +3 -2
  32. package/lib/module/iso18013/iso18013-5/index.js.map +1 -1
  33. package/lib/module/iso18013/iso18013-5/proximity.js +20 -15
  34. package/lib/module/iso18013/iso18013-5/proximity.js.map +1 -1
  35. package/lib/module/iso18013/iso18013-5/{schema.js → request.js} +1 -37
  36. package/lib/module/iso18013/iso18013-5/request.js.map +1 -0
  37. package/lib/module/iso18013/iso18013-7/README.md +66 -41
  38. package/lib/module/iso18013/iso18013-7/error.js +15 -0
  39. package/lib/module/iso18013/iso18013-7/error.js.map +1 -0
  40. package/lib/module/iso18013/iso18013-7/index.js +1 -0
  41. package/lib/module/iso18013/iso18013-7/index.js.map +1 -1
  42. package/lib/module/iso18013/iso18013-7/remote.js +11 -24
  43. package/lib/module/iso18013/iso18013-7/remote.js.map +1 -1
  44. package/lib/module/schema.js +46 -0
  45. package/lib/module/schema.js.map +1 -0
  46. package/lib/typescript/src/cbor/cbor/decoder.d.ts +12 -22
  47. package/lib/typescript/src/cbor/cbor/decoder.d.ts.map +1 -1
  48. package/lib/typescript/src/cbor/cbor/error.d.ts +68 -0
  49. package/lib/typescript/src/cbor/cbor/error.d.ts.map +1 -0
  50. package/lib/typescript/src/cbor/cbor/index.d.ts +1 -1
  51. package/lib/typescript/src/cbor/cbor/index.d.ts.map +1 -1
  52. package/lib/typescript/src/cbor/cose/error.d.ts +68 -0
  53. package/lib/typescript/src/cbor/cose/error.d.ts.map +1 -0
  54. package/lib/typescript/src/cbor/cose/index.d.ts +1 -1
  55. package/lib/typescript/src/cbor/cose/index.d.ts.map +1 -1
  56. package/lib/typescript/src/cbor/cose/sign.d.ts +4 -3
  57. package/lib/typescript/src/cbor/cose/sign.d.ts.map +1 -1
  58. package/lib/typescript/src/iso18013/index.d.ts +0 -1
  59. package/lib/typescript/src/iso18013/index.d.ts.map +1 -1
  60. package/lib/typescript/src/iso18013/iso18013-5/error.d.ts +73 -0
  61. package/lib/typescript/src/iso18013/iso18013-5/error.d.ts.map +1 -0
  62. package/lib/typescript/src/iso18013/iso18013-5/index.d.ts +4 -3
  63. package/lib/typescript/src/iso18013/iso18013-5/index.d.ts.map +1 -1
  64. package/lib/typescript/src/iso18013/iso18013-5/proximity.d.ts +21 -14
  65. package/lib/typescript/src/iso18013/iso18013-5/proximity.d.ts.map +1 -1
  66. package/lib/typescript/src/iso18013/iso18013-5/{schema.d.ts → request.d.ts} +1 -39
  67. package/lib/typescript/src/iso18013/iso18013-5/request.d.ts.map +1 -0
  68. package/lib/typescript/src/iso18013/iso18013-7/error.d.ts +68 -0
  69. package/lib/typescript/src/iso18013/iso18013-7/error.d.ts.map +1 -0
  70. package/lib/typescript/src/iso18013/iso18013-7/index.d.ts +3 -2
  71. package/lib/typescript/src/iso18013/iso18013-7/index.d.ts.map +1 -1
  72. package/lib/typescript/src/iso18013/iso18013-7/remote.d.ts +11 -25
  73. package/lib/typescript/src/iso18013/iso18013-7/remote.d.ts.map +1 -1
  74. package/lib/typescript/src/iso18013/types.d.ts +25 -0
  75. package/lib/typescript/src/iso18013/types.d.ts.map +1 -1
  76. package/lib/typescript/src/schema.d.ts +76 -0
  77. package/lib/typescript/src/schema.d.ts.map +1 -0
  78. package/package.json +1 -1
  79. package/src/cbor/cbor/README.md +39 -59
  80. package/src/cbor/cbor/decoder.ts +13 -23
  81. package/src/cbor/cbor/error.ts +23 -0
  82. package/src/cbor/cbor/index.ts +5 -1
  83. package/src/cbor/cose/README.md +39 -9
  84. package/src/cbor/cose/error.ts +23 -0
  85. package/src/cbor/cose/index.ts +5 -1
  86. package/src/cbor/cose/sign.ts +5 -4
  87. package/src/iso18013/index.ts +0 -7
  88. package/src/iso18013/iso18013-5/README.md +120 -44
  89. package/src/iso18013/iso18013-5/error.ts +35 -0
  90. package/src/iso18013/iso18013-5/index.ts +9 -8
  91. package/src/iso18013/iso18013-5/proximity.ts +21 -17
  92. package/src/iso18013/iso18013-5/{schema.ts → request.ts} +0 -42
  93. package/src/iso18013/iso18013-7/README.md +66 -41
  94. package/src/iso18013/iso18013-7/error.ts +21 -0
  95. package/src/iso18013/iso18013-7/index.ts +6 -5
  96. package/src/iso18013/iso18013-7/remote.ts +12 -34
  97. package/src/iso18013/types.ts +24 -0
  98. package/src/schema.ts +55 -0
  99. package/lib/module/cbor/cbor/failure.js +0 -2
  100. package/lib/module/cbor/cbor/failure.js.map +0 -1
  101. package/lib/module/cbor/cose/failure.js +0 -2
  102. package/lib/module/cbor/cose/failure.js.map +0 -1
  103. package/lib/module/iso18013/iso18013-5/schema.js.map +0 -1
  104. package/lib/typescript/src/cbor/cbor/failure.d.ts +0 -15
  105. package/lib/typescript/src/cbor/cbor/failure.d.ts.map +0 -1
  106. package/lib/typescript/src/cbor/cose/failure.d.ts +0 -15
  107. package/lib/typescript/src/cbor/cose/failure.d.ts.map +0 -1
  108. package/lib/typescript/src/iso18013/iso18013-5/schema.d.ts.map +0 -1
  109. package/src/cbor/cbor/failure.ts +0 -18
  110. package/src/cbor/cose/failure.ts +0 -20
@@ -1,95 +1,75 @@
1
- ## CBOR
1
+ # CBOR
2
2
 
3
3
  This module provides methods to decode CBOR data into readable objects.
4
4
 
5
5
  ```typescript
6
- import { CBOR } from '@pagopa/io-react-native-cbor';
6
+ import { CBOR } from '@pagopa/io-react-native-iso18013';
7
7
  ```
8
8
 
9
- ### Methods
9
+ ## Methods
10
10
 
11
11
  #### `decode`
12
12
 
13
- This method allows to decode CBOR data into readable JSON objects.
14
- Returns a `Promise` which resolves to a JSON object, or rejects with an instance of `CborFailure` in case of failure.
13
+ Decodes CBOR data into readable JSON objects.
15
14
 
16
15
  **Note**: this method does not decode nested CBOR objects and therefore complex objects needs additional manual decoding
17
16
 
18
17
  ```typescript
19
- try {
20
- const decoded = await CBOR.decode('...');
21
- } catch (e) {
22
- const { message, userInfo } = e as CborFailure;
23
- }
18
+ const decoded = await CBOR.decode('...');
24
19
  ```
25
20
 
26
21
  #### `decodeDocuments`
27
22
 
28
- This metod allows the decoding of CBOR data which contains MDOC objects.
29
- Returns a promise wich resolves to a [Documents](#documents) object, or rejects with an instance of `CborFailure` in case of failure.
23
+ Decodes CBOR data containing MDOC objects.
30
24
 
31
25
  ```typescript
32
- try {
33
- const decoded = await CBOR.decodeDocuments('...');
34
- } catch (e) {
35
- const { message, userInfo } = e as CborFailure;
36
- }
26
+ const decoded = await CBOR.decodeDocuments('...');
37
27
  ```
38
28
 
39
- ### Types
29
+ #### `decodeIssuerSigned`
40
30
 
41
- #### `Documents`
31
+ Decodes CBOR data containing an Issuer Signed object.
42
32
 
43
33
  ```typescript
44
- type Documents = {
45
- status?: number;
46
- version?: string;
47
- documents?: Array<MDOC>;
48
- };
34
+ const decoded = await CBOR.decodeIssuerSigned('...');
49
35
  ```
50
36
 
51
- #### `MDOC`
37
+ ## Errors
52
38
 
53
- ```typescript
54
- type MDOC = {
55
- docType?: DocumentType;
56
- issuerSigned?: IssuerSigned;
57
- };
58
- ```
39
+ This table contains the list of error codes that can be thrown by the `CBOR` module which are mapped via the `ModuleErrorCodes` type:
40
+ | Type | Platform | Description |
41
+ | -------------------------- | ----------- | ------------------------------------------------------------ |
42
+ | DECODE_ERROR | Android/iOS | An error occurred while decoding the CBOR |
43
+ | DECODE_DOCUMENTS_ERROR | Android/iOS | An error occurred while decoding a CBOR mDOC |
44
+ | DECODE_ISSUER_SIGNED_ERROR | Android/iOS | An error occurred while decoding a CBOR Issuer Signed object |
59
45
 
60
- #### `IssuerSigned`
46
+ An error can be parsed using the `ModuleErrorSchema` with type `ModuleErrorCodes` exposed by the `ISO18013_5` module. The error can be parsed as follows:
61
47
 
62
48
  ```typescript
63
- type IssuerSigned = {
64
- nameSpaces?: Record<string, Array<DocumentValue>>;
65
- issuerAuth?: string;
66
- };
49
+ import { CBOR } from '@pagopa/io-react-native-iso18013';
50
+ try {
51
+ await CBOR.func();
52
+ } catch (error) {
53
+ const parsedError = CBOR.ModuleErrorSchema.parse(error); // Or ModuleErrorSchema.safeParse(error) for safe parsing
54
+ console.log(JSON.stringify(parsedError, null, 2));
55
+ }
67
56
  ```
68
57
 
69
- #### `DocumentValue`
58
+ The parsed object will contain properties from both iOS and Android platforms:
70
59
 
71
60
  ```typescript
72
- type DocumentValue = {
73
- digestID?: number;
74
- random?: string;
75
- elementIdentifier?: string;
76
- elementValue?: string;
61
+ {
62
+ code: string; // Defined in ModuleErrorCodes
63
+ message: string;
64
+ name: string;
65
+ userInfo?: Record<string, any> | null;
66
+ nativeStackAndroid?: Array<{
67
+ lineNumber: number;
68
+ file: string;
69
+ methodName: string;
70
+ class: string;
71
+ }>;
72
+ domain?: string;
73
+ nativeStackIOS?: Array<string>;
77
74
  };
78
75
  ```
79
-
80
- #### `DocumentType`
81
-
82
- ```typescript
83
- enum DocumentTypeEnum {
84
- MDL = 'org.iso.18013.5.1.mDL',
85
- EU_PID = 'eu.europa.ec.eudi.pid.1',
86
- }
87
- ```
88
-
89
- ### Error Codes
90
-
91
- | Type | Platform | Description |
92
- | ----------------- | ----------- | --------------------------------------------- |
93
- | INVALID_ENCODING | Android/iOS | Provided payload has incorrect encoding |
94
- | UNABLE_TO_DECODE | Android/iOS | The data does not contain a valid CBOR object |
95
- | UNKNOWN_EXCEPTION | Android/iOS | Unexpected failure |
@@ -8,15 +8,11 @@ import {
8
8
  import { coerceToJSON } from './schema.utils';
9
9
 
10
10
  /**
11
- * Decode base64 encoded CBOR data to JSON object.
11
+ * Decode base64 or base64url encoded CBOR data to JSON object.
12
+ * This method does not handle nested CBOR data, which will need additional parsing.
12
13
  *
13
- * If it is not possibile to decode the provided data, the promise will be rejected with
14
- * an instance of {@link CborFailure}.
15
- *
16
- * **NOTE**: this method does not handle nested CBOR data, which will need additional
17
- * parsing.
18
- *
19
- * @param data - The base64 or base64url encoded CBOR data
14
+ * @param data - The base64 or base64url encoded CBOR string
15
+ * @throws {ModuleError} in case of failure which can be parsed with {@link ModuleErrorSchema}
20
16
  * @returns The decoded data as JSON object
21
17
  */
22
18
  export const decode = async (data: string): Promise<any> => {
@@ -25,12 +21,9 @@ export const decode = async (data: string): Promise<any> => {
25
21
  };
26
22
 
27
23
  /**
28
- * Decode base64 or base64url encoded CBOR data to mDOC object
29
- *
30
- * If it is not possibile to decode the provided data, the promise will be rejected with
31
- * an instance of {@link CborFailure}.
32
- *
33
- * @param data - The base64 encoded MDOC data
24
+ * Decode base64 or base64url encoded mDOC-CBOR data to a JSON object
25
+ * @param data - The base64 or base64url encoded mDOC-CBOR string
26
+ * @throws {ModuleError} in case of failure which can be parsed with {@link ModuleErrorSchema}
34
27
  * @returns The decoded data as mDOC object
35
28
  */
36
29
  export const decodeDocuments = async (data: string): Promise<Documents> => {
@@ -39,18 +32,15 @@ export const decodeDocuments = async (data: string): Promise<Documents> => {
39
32
  };
40
33
 
41
34
  /**
42
- * Extract and decode the {@link IssuerSigned} with the {@link IssuerAuth} decoded from base64 encoded CBOR
43
- *
44
- * If it is not possibile to decode the provided data, the promise will be rejected with
45
- * an instance of {@link CborFailure}.
46
- *
47
- * @param issuerSigned - The base64 or base64url encoded MDOC data
48
- * @returns The decoded {@link IssuerSigned} contained in the mDOC object
35
+ * Decode base64 or base64url encoded issuerSigned attribute part of an mDOC-CBOR.
36
+ * @param data - The base64 or base64url encoded mDOC-CBOR containing the issuerSigned
37
+ * @throws {ModuleError} in case of failure which can be parsed with {@link ModuleErrorSchema}
38
+ * @returns The decoded {@link IssuerSigned}
49
39
  */
50
40
  export const decodeIssuerSigned = async (
51
- issuerSigned: string
41
+ data: string
52
42
  ): Promise<IssuerSigned> => {
53
43
  const decodedIssuerSignedString =
54
- await IoReactNativeCbor.decodeIssuerSigned(issuerSigned);
44
+ await IoReactNativeCbor.decodeIssuerSigned(data);
55
45
  return await IssuerSignedFromString.parseAsync(decodedIssuerSignedString);
56
46
  };
@@ -0,0 +1,23 @@
1
+ import z from 'zod';
2
+ import { GenericModuleErrorSchema } from '../../schema';
3
+
4
+ /**
5
+ * Error codes which the CBOR module uses to reject a promise.
6
+ */
7
+ const ModuleErrorCodesSchema = z.enum([
8
+ 'DECODE_ERROR',
9
+ 'DECODE_DOCUMENTS_ERROR',
10
+ 'DECODE_ISSUER_SIGNED_ERROR',
11
+ 'EUNSPECIFIED', // Android only default when no other error is specified
12
+ ]);
13
+
14
+ export type ModuleErrorCodes = z.infer<typeof ModuleErrorCodesSchema>;
15
+
16
+ /**
17
+ * Schema which can be used to parse a rejected promise error by the CBOR module.
18
+ */
19
+ export const ModuleErrorSchema = GenericModuleErrorSchema(
20
+ ModuleErrorCodesSchema
21
+ );
22
+
23
+ export type ModuleError = z.infer<typeof ModuleErrorSchema>;
@@ -6,4 +6,8 @@ export {
6
6
  IssuerSigned,
7
7
  MDOC,
8
8
  } from './schema';
9
- export { type CborFailure, type CborFailureCodes } from './failure';
9
+ export {
10
+ type ModuleError,
11
+ type ModuleErrorCodes,
12
+ ModuleErrorSchema,
13
+ } from './error';
@@ -3,7 +3,7 @@
3
3
  This module provides methods to sign and verify data with COSE.
4
4
 
5
5
  ```typescript
6
- import { COSE } from '@pagopa/io-react-native-cbor';
6
+ import { COSE } from '@pagopa/io-react-native-iso18013';
7
7
  ```
8
8
 
9
9
  ### Methods
@@ -42,12 +42,42 @@ try {
42
42
  }
43
43
  ```
44
44
 
45
- ### Error Codes
45
+ ### Error
46
46
 
47
- | Type | Platform | Description |
48
- | -------------------- | ----------- | -------------------------------------------------- |
49
- | PUBLIC_KEY_NOT_FOUND | Android/iOS | The public key is missing for the specified keyTag |
50
- | INVALID_ENCODING | Android/iOS | Provided payload has incorrect encoding |
51
- | UNABLE_TO_SIGN | Android/iOS | It was not possible to sign the given string |
52
- | THREADING_ERROR | iOS | Unexpected failure |
53
- | UNKNOWN_EXCEPTION | Android/iOS | Unexpected failure |
47
+ This table contains the list of error codes that can be thrown by the `COSE` module which are mapped via the `ModuleErrorCodes` type:
48
+ | Type | Platform | Description |
49
+ | -------------------------- | ----------- | ------------------------------------------------------------ |
50
+ | SIGN_ERROR | Android/iOS | An error occurred while signing the data |
51
+ | VERIFY_ERROR | Android/iOS | An error occurred while verifying the signature |
52
+ | THREADING_ERROR | iOS | An error occurred while performing the sign operation in background |
53
+
54
+ An error can be parsed using the `ModuleErrorSchema` with type `ModuleErrorCodes` exposed by the `COSE` module. The error can be parsed as follows:
55
+
56
+ ```typescript
57
+ import { COSE } from '@pagopa/io-react-native-iso18013';
58
+ try {
59
+ await COSE.func();
60
+ } catch (error) {
61
+ const parsedError = COSE.ModuleErrorSchema.parse(error); // Or ModuleErrorSchema.safeParse(error) for safe parsing
62
+ console.log(JSON.stringify(parsedError, null, 2));
63
+ }
64
+ ```
65
+
66
+ The parsed object will contain properties from both iOS and Android platforms:
67
+
68
+ ```typescript
69
+ {
70
+ code: string; // Defined in ModuleErrorCodes
71
+ message: string;
72
+ name: string;
73
+ userInfo?: Record<string, any> | null;
74
+ nativeStackAndroid?: Array<{
75
+ lineNumber: number;
76
+ file: string;
77
+ methodName: string;
78
+ class: string;
79
+ }>;
80
+ domain?: string;
81
+ nativeStackIOS?: Array<string>;
82
+ };
83
+ ```
@@ -0,0 +1,23 @@
1
+ import z from 'zod';
2
+ import { GenericModuleErrorSchema } from '../../schema';
3
+
4
+ /**
5
+ * Error codes which the COSE module uses to reject a promise.
6
+ */
7
+ const ModuleErrorCodesSchema = z.enum([
8
+ 'SIGN_ERROR',
9
+ 'VERIFY_ERROR',
10
+ 'THREADING_ERROR', // iOS only
11
+ 'EUNSPECIFIED', // Android only default when no other error is specified
12
+ ]);
13
+
14
+ export type ModuleErrorCodes = z.infer<typeof ModuleErrorCodesSchema>;
15
+
16
+ /**
17
+ * Schema which can be used to parse a rejected promise error by the COSE module.
18
+ */
19
+ export const ModuleErrorSchema = GenericModuleErrorSchema(
20
+ ModuleErrorCodesSchema
21
+ );
22
+
23
+ export type ModuleError = z.infer<typeof ModuleErrorSchema>;
@@ -1,2 +1,6 @@
1
1
  export { sign, verify } from './sign';
2
- export { type CoseFailure, type CoseFailureCodes } from './failure';
2
+ export {
3
+ type ModuleErrorCodes,
4
+ type ModuleError,
5
+ ModuleErrorSchema,
6
+ } from './error';
@@ -4,19 +4,20 @@ import { IoReactNativeCbor } from '..';
4
4
  /**
5
5
  * Sign base64 encoded data with COSE and return the COSE-Sign1 object in base64 encoding
6
6
  *
7
- * @param payload - The base64 or base64url encoded payload to sign
7
+ * @param data - The base64 or base64url encoded payload to sign
8
8
  * @param keyTag - The alias of the key to use for signing.
9
- * @throws {CoseFailure} If the key does not exist
9
+ * @throws {ModuleError} in case of failure which can be parsed with {@link ModuleErrorSchema}
10
10
  * @returns The COSE-Sign1 object in base64 encoding
11
11
  */
12
- export const sign = async (payload: string, keyTag: string): Promise<string> =>
13
- await IoReactNativeCbor.sign(payload, keyTag);
12
+ export const sign = async (data: string, keyTag: string): Promise<string> =>
13
+ await IoReactNativeCbor.sign(data, keyTag);
14
14
 
15
15
  /**
16
16
  * Verifies a COSE-Sign1 object with the provided public key
17
17
  *
18
18
  * @param data - The COSE-Sign1 object in base64 or base64url encoding
19
19
  * @param publicKey - The public key in JWK format
20
+ * @throws {ModuleError} in case of failure which can be parsed with {@link ModuleErrorSchema}
20
21
  * @returns true if the signature is valid, false otherwise
21
22
  */
22
23
  export const verify = async (
@@ -1,11 +1,4 @@
1
1
  import { NativeModules, Platform } from 'react-native';
2
- export {
3
- type AcceptedFields,
4
- type EventError,
5
- type VerifierRequest,
6
- parseEventError,
7
- parseVerifierRequest,
8
- } from './iso18013-5/schema';
9
2
 
10
3
  const LINKING_ERROR =
11
4
  `The package '@pagopa/io-react-native-iso18013' (IoReactNativeIso18013) doesn't seem to be linked. Make sure: \n\n` +
@@ -1,13 +1,15 @@
1
1
  # ISO18013-5
2
2
 
3
- This library provides a React Native module based on [iso18013-android](https://github.com/pagopa/iso18013-android) and [iso18013-ios](https://github.com/pagopa/iso18013-ios) which allows mDL proximity presentation according to the
4
- ISO 18013-5 standard and remote presentation according to the ISO 18013-7 standard.
3
+ This library provides a React Native module based on [iso18013-android](https://github.com/pagopa/iso18013-android) and [iso18013-ios](https://github.com/pagopa/iso18013-ios) which allows mDL proximity presentation according to the ISO 18013-5 standard.
5
4
 
6
5
  ## Installation
7
6
 
8
- ## Usage
7
+ ```
8
+ yarn add @pagopa/io-react-native-iso18013
9
+ cd ios && bundle exec pod install && cd ..
10
+ ```
9
11
 
10
- ### `events`
12
+ ## Events
11
13
 
12
14
  This library emits the following events:
13
15
  | Event | Payload | Description |
@@ -15,17 +17,39 @@ This library emits the following events:
15
17
  | onDeviceConnecting (iOS only) | `undefined` | Event dispatched when the verifier app is connecting |
16
18
  | onDeviceConnected | `undefined` | Event dispatched when the verifier app is connected. |
17
19
  | onDocumentRequestReceived | `{ data: string } \| undefined` | Event dispatched when the consumer app receives a new request, contained in the data payload. It can be parsed via the `parseVerifierRequest` provided [here](src/schema.ts). |
18
- | onDeviceDisconnected | `undefined` | Event dispatched when the verifier app disconnects. |
20
+ | onDeviceDisconnected | `undefined` | Event dispatched when the verifier app disconnects by sending the END (0x02) flag. |
19
21
  | onError | `{ error: string } \| undefined` | Event dispatched when an error occurs which is contained in the error payload. It can be parsed via the `parseError` provided [here](src/schema.ts). |
20
22
 
21
- Listeners can be added using the `addListener` method and removed using the `removeListener` method.
23
+ The events flow is described in the following diagram:
24
+
25
+ ```mermaid
26
+ flowchart LR
27
+ onDeviceConnecting["onDeviceConnecting *(iOS only)*"]
28
+ onDeviceConnected["onDeviceConnected"]
29
+ onDocumentRequestReceived["onDocumentRequestReceived"]
30
+ onDeviceDisconnected["onDeviceDisconnected"]
31
+ onError["onError"]
32
+
33
+ onDeviceConnecting -- "Verifier app connects" --> onDeviceConnected
34
+
35
+ onDeviceConnected -- "Verifier app sends request" --> onDocumentRequestReceived
36
+ onDeviceConnected -- "Verifier sends END (0x02)" --> onDeviceDisconnected
37
+ onDeviceConnected -- "Error status or abrupt disconnection" --> onError
38
+
39
+ onDocumentRequestReceived -- "Verifier sends END (0x02)" --> onDeviceDisconnected
40
+ onDocumentRequestReceived -- "Error status or abrupt disconnection" --> onError
41
+ ```
42
+
43
+ Listeners can be added using the `addListener` method and removed by using the returned reference by calling the `remove` method.
22
44
 
23
45
  ```typescript
24
46
  import { ISO18013_5 } from '@pagopa/io-react-native-iso18013';
25
47
 
26
- ISO18013_5.addListener('event', () => console.log('event occurred'));
48
+ const listener = ISO18013_5.addListener('event', () =>
49
+ console.log('event occurred')
50
+ );
27
51
 
28
- ISO18013_5.removeListener('event');
52
+ listener.remove();
29
53
  ```
30
54
 
31
55
  #### `onDeviceConnecting`
@@ -105,7 +129,9 @@ ISO18013_5.addListener(
105
129
  );
106
130
  ```
107
131
 
108
- ### `start`
132
+ ## Methods
133
+
134
+ #### `start`
109
135
 
110
136
  Starts the proximity flow and starts the bluetooth service. This method also accepts optional parameters to configure the initialization on Android, along with the possibility
111
137
  to specify a certificates of array to verify the reader app.
@@ -116,7 +142,7 @@ import { ISO18013_5 } from '@pagopa/io-react-native-iso18013';
116
142
  await ISO18013_5.start();
117
143
  ```
118
144
 
119
- ### `getQrCodeString`
145
+ #### `getQrCodeString`
120
146
 
121
147
  Returns the QR code string which contains a base64url encoded CBOR object which encodes the bluetooth engagement data.
122
148
  It can be used to display the QR code in the UI which will be scanned by the verifier app.
@@ -128,25 +154,37 @@ const qrCodeString = await ISO18013_5.getQrCodeString();
128
154
  console.log(qrCodeString);
129
155
  ```
130
156
 
131
- ### `generateResponse`
157
+ #### `generateResponse`
132
158
 
133
159
  Generates a response that will be sent to the verifier app containing the requested documents.
134
160
 
135
161
  ```typescript
136
162
  import { ISO18013_5 } from '@pagopa/io-react-native-iso18013';
137
163
 
138
- const response = await ISO18013_5.generateResponse({
139
- documents: [
140
- {
141
- type: 'mDL',
142
- data: 'base64url-encoded-data',
164
+ const documents = [
165
+ {
166
+ issuerSignedContent: 'base64url-or-base64-encoded-content',
167
+ alias: 'key-alias',
168
+ docType: 'docType',
169
+ },
170
+ ];
171
+
172
+ const acceptedFields = {
173
+ 'org.iso.18013.5.1.mDL': {
174
+ 'org.iso.18013.5.1': {
175
+ hair_colour: true,
176
+ given_name_national_character: true,
177
+ family_name_national_character: true,
178
+ given_name: true,
143
179
  },
144
- ],
145
- });
180
+ },
181
+ };
182
+
183
+ const response = await ISO18013_5.generateResponse(documents, acceptedFields);
146
184
  console.log(response);
147
185
  ```
148
186
 
149
- ### `sendResponse`
187
+ #### `sendResponse`
150
188
 
151
189
  Sends the response generate by `generateResponse` to the verifier app.
152
190
 
@@ -156,24 +194,21 @@ import { ISO18013_5 } from '@pagopa/io-react-native-iso18013';
156
194
  await ISO18013_5.sendResponse(response);
157
195
  ```
158
196
 
159
- ### `sendErrorResponse`
197
+ #### `sendErrorResponse`
160
198
 
161
199
  Sends an error response to the verifier app. The supported error codes are defined in the Table 20 of the ISO 18013-5 standard and are coded in the `ErrorCode` enum.
162
200
 
163
201
  ```typescript
164
202
  import { ISO18013_5, ErrorCode } from '@pagopa/io-react-native-iso18013';
165
203
 
166
- await ISO18013_5.sendErrorResponse({
167
- errorCode: ErrorCode.SESSION_ENCRYPTION,
168
- errorMessage: 'An error occurred while encrypting the session',
169
- });
204
+ await ISO18013_5.sendErrorResponse(ErrorCode.SESSION_ENCRYPTION);
170
205
  ```
171
206
 
172
- ### `close`
207
+ #### `close`
173
208
 
174
209
  Closes the QR engagement by releasing the resources allocated during the `start` method.
175
210
  Before starting a new flow, it is necessary to call this method to ensure that the previous flow is properly closed.
176
- The listeners can be removed using the `removeListener` method.
211
+ Listeners can be added using the `addListener` method and removed using the `removeListener` method.
177
212
 
178
213
  ```typescript
179
214
  import { ISO18013_5 } from '@pagopa/io-react-native-iso18013';
@@ -181,9 +216,9 @@ import { ISO18013_5 } from '@pagopa/io-react-native-iso18013';
181
216
  await ISO18013_5.close();
182
217
  ```
183
218
 
184
- ## Proximity Flow Schema
219
+ ## Proximity Sequence Diagram
185
220
 
186
- This section describes a high level overview of the interactions between an app implementing the `io-react-native-proximity` library and a verifier app.
221
+ This section describes a high level overview of the happy flow interactions between an app implementing the `io-react-native-proximity` library and a verifier app.
187
222
 
188
223
  ```mermaid
189
224
  sequenceDiagram
@@ -216,19 +251,60 @@ sequenceDiagram
216
251
  proximity->>+verifier: Sends the error response code
217
252
  verifier->>+verifier: Shows the received error response code
218
253
  end
219
- verifier->>+app: Closes the connection
220
- proximity->>+app: Calls the onDeviceDisconnected callback
221
- ```
222
-
223
- ## Error Codes
224
-
225
- | Type | Platform | Description |
226
- | ------------------------------- | ----------- | ---------------------------------------------------------------------------- |
227
- | DRH_NOT_DEFINED | Android | The device retrieval helper hasn't been initialized, call the `start` method |
228
- | QR_ENGAGEMENT_NOT_DEFINED_ERROR | Android | The QR engagement hasn't been initialized, call the `start` method |
229
- | START_ERROR | Android/iOS | An error occurred while initializing the required resources |
230
- | GET_QR_CODE_ERROR | Android/iOS | An error occurred while generating the engagement QR code |
231
- | GENERATE_RESPONSE_ERROR | Android/iOS | An error occurred while generating the response for the verifier app |
232
- | SEND_RESPONSE_ERROR | Android/iOS | An error occurred while sending the response to the verifier app |
233
- | SEND_ERROR_RESPONSE_ERROR | Android/iOS | An error occurred while sending the error response to the verifier app |
234
- | CLOSE_ERROR | Android | An error occured while closing the required resources |
254
+ alt The verifier sends the END (0x02) termination flag
255
+ verifier->>+app: Closes the connection
256
+ proximity->>+app: Calls the onDeviceDisconnected callback
257
+ app->>+proximity: Calls close()
258
+ else The verifier app closes the connection without the END (0x02) termination flag
259
+ verifier->>+app: Closes the connection
260
+ proximity->>+app: Calls the onError callback
261
+ app->>+proximity: Calls close()
262
+ end
263
+ ```
264
+
265
+ ## Errors
266
+
267
+ This table contains the list of error codes that can be thrown by the `ISO18013_5` module which are mapped via the `ModuleErrorCodes` type:
268
+
269
+ | Type | Platform | Description |
270
+ | ------------------------- | ----------- | ---------------------------------------------------------------------------- |
271
+ | DRH_NOT_DEFINED | Android | The device retrieval helper hasn't been initialized, call the `start` method |
272
+ | QR_ENGAGEMENT_NOT_DEFINED | Android | The QR engagement hasn't been initialized, call the `start` method |
273
+ | START_ERROR | Android/iOS | An error occurred while initializing the required resources |
274
+ | GET_QR_CODE_ERROR | Android/iOS | An error occurred while generating the engagement QR code |
275
+ | SEND_RESPONSE_ERROR | Android/iOS | An error occurred while sending the response for the verifier app |
276
+ | SEND_ERROR_RESPONSE_ERROR | Android/iOS | An error occurred while sending the error response to the verifier app |
277
+ | GENERATE_RESPONSE_ERROR | Android/iOS | An error occurred while generating the response for the verifier app |
278
+ | CLOSE_ERROR | Android | An error occured while closing the required resources |
279
+ | EUNSPECIFIED | Android | Default error when no other error is specified |
280
+
281
+ An error can be parsed using the `ModuleErrorSchema` with type `ModuleErrorCodes` exposed by the `ISO18013_5` module. The error can be parsed as follows:
282
+
283
+ ```typescript
284
+ import { ISO18013_5 } from '@pagopa/io-react-native-iso18013';
285
+ try {
286
+ await ISO18013_5.func();
287
+ } catch (error) {
288
+ const parsedError = ISO18013_5.ModuleErrorSchema.parse(error); // Or ModuleErrorSchema.safeParse(error) for safe parsing
289
+ console.log(JSON.stringify(parsedError, null, 2));
290
+ }
291
+ ```
292
+
293
+ The parsed object will contain properties from both iOS and Android platforms:
294
+
295
+ ```typescript
296
+ {
297
+ code: string; // Defined in ModuleErrorCodes
298
+ message: string;
299
+ name: string;
300
+ userInfo?: Record<string, any> | null;
301
+ nativeStackAndroid?: Array<{
302
+ lineNumber: number;
303
+ file: string;
304
+ methodName: string;
305
+ class: string;
306
+ }>;
307
+ domain?: string;
308
+ nativeStackIOS?: Array<string>;
309
+ };
310
+ ```
@@ -0,0 +1,35 @@
1
+ import z from 'zod';
2
+ import { GenericModuleErrorSchema } from '../../schema';
3
+
4
+ /**
5
+ * Schema for parsing the payload returned by the `onError` event in Proximity `Events`, along with its type definition.
6
+ */
7
+ export const OnErrorPayloadSchema = z.string().catch('Unknown error');
8
+
9
+ export type OnErrorPayload = z.infer<typeof OnErrorPayloadSchema>;
10
+
11
+ /**
12
+ * Error codes which the ISO18013_5 module uses to reject a promise.
13
+ */
14
+ const ModuleErrorCodesSchema = z.enum([
15
+ 'DRH_NOT_DEFINED', // Android only
16
+ 'QR_ENGAGEMENT_NOT_DEFINED', // Android only
17
+ 'START_ERROR',
18
+ 'GET_QR_CODE_ERROR',
19
+ 'SEND_RESPONSE_ERROR',
20
+ 'SEND_ERROR_RESPONSE_ERROR',
21
+ 'GENERATE_RESPONSE_ERROR',
22
+ 'CLOSE_ERROR', // Android only
23
+ 'EUNSPECIFIED', // Android only default when no other error is specified
24
+ ]);
25
+
26
+ export type ModuleErrorCodes = z.infer<typeof ModuleErrorCodesSchema>;
27
+
28
+ /**
29
+ * Schema which can be used to parse a rejected promise error by the ISO18013_5 module.
30
+ */
31
+ export const ModuleErrorSchema = GenericModuleErrorSchema(
32
+ ModuleErrorCodesSchema
33
+ );
34
+
35
+ export type ModuleError = z.infer<typeof ModuleErrorSchema>;