@evervault/evervault-react-native 0.2.2 → 0.3.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 (105) hide show
  1. package/README.md +52 -12
  2. package/android/build.gradle +5 -3
  3. package/android/gradle.properties +1 -1
  4. package/android/src/main/java/com/evervaultsdk/EvervaultSdkModule.kt +34 -5
  5. package/android/src/main/java/com/evervaultsdk/EvervaultSdkPackage.kt +1 -1
  6. package/evervault-react-native.podspec +1 -1
  7. package/lib/commonjs/components/Card/Card.js +115 -0
  8. package/lib/commonjs/components/Card/Card.js.map +1 -0
  9. package/lib/commonjs/components/Card/CardCVC.js +53 -0
  10. package/lib/commonjs/components/Card/CardCVC.js.map +1 -0
  11. package/lib/commonjs/components/Card/CardExpiry.js +40 -0
  12. package/lib/commonjs/components/Card/CardExpiry.js.map +1 -0
  13. package/lib/commonjs/components/Card/CardHolder.js +38 -0
  14. package/lib/commonjs/components/Card/CardHolder.js.map +1 -0
  15. package/lib/commonjs/components/Card/CardNumber.js +63 -0
  16. package/lib/commonjs/components/Card/CardNumber.js.map +1 -0
  17. package/lib/commonjs/components/Card/context.js +23 -0
  18. package/lib/commonjs/components/Card/context.js.map +1 -0
  19. package/lib/commonjs/components/Card/index.js +20 -0
  20. package/lib/commonjs/components/Card/index.js.map +1 -0
  21. package/lib/commonjs/components/Card/types.js +6 -0
  22. package/lib/commonjs/components/Card/types.js.map +1 -0
  23. package/lib/commonjs/components/Card/utilities.js +85 -0
  24. package/lib/commonjs/components/Card/utilities.js.map +1 -0
  25. package/lib/commonjs/components/Common/Error.js +2 -0
  26. package/lib/commonjs/components/Common/Error.js.map +1 -0
  27. package/lib/commonjs/components/index.js +3 -0
  28. package/lib/commonjs/components/index.js.map +1 -0
  29. package/lib/commonjs/index.js +18 -16
  30. package/lib/commonjs/index.js.map +1 -1
  31. package/lib/commonjs/native.js +17 -0
  32. package/lib/commonjs/native.js.map +1 -0
  33. package/lib/commonjs/sdk.js +22 -0
  34. package/lib/commonjs/sdk.js.map +1 -0
  35. package/lib/module/components/Card/Card.js +110 -0
  36. package/lib/module/components/Card/Card.js.map +1 -0
  37. package/lib/module/components/Card/CardCVC.js +44 -0
  38. package/lib/module/components/Card/CardCVC.js.map +1 -0
  39. package/lib/module/components/Card/CardExpiry.js +34 -0
  40. package/lib/module/components/Card/CardExpiry.js.map +1 -0
  41. package/lib/module/components/Card/CardHolder.js +32 -0
  42. package/lib/module/components/Card/CardHolder.js.map +1 -0
  43. package/lib/module/components/Card/CardNumber.js +57 -0
  44. package/lib/module/components/Card/CardNumber.js.map +1 -0
  45. package/lib/module/components/Card/context.js +16 -0
  46. package/lib/module/components/Card/context.js.map +1 -0
  47. package/lib/module/components/Card/index.js +3 -0
  48. package/lib/module/components/Card/index.js.map +1 -0
  49. package/lib/module/components/Card/types.js +2 -0
  50. package/lib/module/components/Card/types.js.map +1 -0
  51. package/lib/module/components/Card/utilities.js +77 -0
  52. package/lib/module/components/Card/utilities.js.map +1 -0
  53. package/lib/module/components/Common/Error.js +2 -0
  54. package/lib/module/components/Common/Error.js.map +1 -0
  55. package/lib/module/components/index.js +2 -0
  56. package/lib/module/components/index.js.map +1 -0
  57. package/lib/module/index.js +2 -16
  58. package/lib/module/index.js.map +1 -1
  59. package/lib/module/native.js +11 -0
  60. package/lib/module/native.js.map +1 -0
  61. package/lib/module/sdk.js +15 -0
  62. package/lib/module/sdk.js.map +1 -0
  63. package/lib/typescript/src/components/Card/Card.d.ts +30 -0
  64. package/lib/typescript/src/components/Card/Card.d.ts.map +1 -0
  65. package/lib/typescript/src/components/Card/CardCVC.d.ts +6 -0
  66. package/lib/typescript/src/components/Card/CardCVC.d.ts.map +1 -0
  67. package/lib/typescript/src/components/Card/CardExpiry.d.ts +6 -0
  68. package/lib/typescript/src/components/Card/CardExpiry.d.ts.map +1 -0
  69. package/lib/typescript/src/components/Card/CardHolder.d.ts +7 -0
  70. package/lib/typescript/src/components/Card/CardHolder.d.ts.map +1 -0
  71. package/lib/typescript/src/components/Card/CardNumber.d.ts +8 -0
  72. package/lib/typescript/src/components/Card/CardNumber.d.ts.map +1 -0
  73. package/lib/typescript/src/components/Card/context.d.ts +13 -0
  74. package/lib/typescript/src/components/Card/context.d.ts.map +1 -0
  75. package/lib/typescript/src/components/Card/index.d.ts +3 -0
  76. package/lib/typescript/src/components/Card/index.d.ts.map +1 -0
  77. package/lib/typescript/src/components/Card/types.d.ts +13 -0
  78. package/lib/typescript/src/components/Card/types.d.ts.map +1 -0
  79. package/lib/typescript/src/components/Card/utilities.d.ts +8 -0
  80. package/lib/typescript/src/components/Card/utilities.d.ts.map +1 -0
  81. package/lib/typescript/src/components/Common/Error.d.ts +1 -0
  82. package/lib/typescript/src/components/Common/Error.d.ts.map +1 -0
  83. package/lib/typescript/src/components/index.d.ts +1 -0
  84. package/lib/typescript/src/components/index.d.ts.map +1 -0
  85. package/lib/typescript/src/index.d.ts +3 -2
  86. package/lib/typescript/src/index.d.ts.map +1 -1
  87. package/lib/typescript/src/native.d.ts +2 -0
  88. package/lib/typescript/src/native.d.ts.map +1 -0
  89. package/lib/typescript/src/sdk.d.ts +3 -0
  90. package/lib/typescript/src/sdk.d.ts.map +1 -0
  91. package/package.json +29 -23
  92. package/src/components/Card/Card.tsx +156 -0
  93. package/src/components/Card/CardCVC.tsx +47 -0
  94. package/src/components/Card/CardExpiry.tsx +39 -0
  95. package/src/components/Card/CardHolder.tsx +39 -0
  96. package/src/components/Card/CardNumber.tsx +64 -0
  97. package/src/components/Card/context.tsx +26 -0
  98. package/src/components/Card/index.ts +2 -0
  99. package/src/components/Card/types.ts +15 -0
  100. package/src/components/Card/utilities.ts +105 -0
  101. package/src/components/Common/Error.tsx +0 -0
  102. package/src/components/index.ts +1 -0
  103. package/src/index.tsx +3 -26
  104. package/src/native.ts +18 -0
  105. package/src/sdk.ts +17 -0
@@ -0,0 +1,39 @@
1
+ import { useEffect } from 'react';
2
+ import { TextInput } from 'react-native';
3
+ import { useCardContext } from './context';
4
+ import { BaseProps } from './Card';
5
+
6
+ export interface CardHolderProps extends BaseProps {
7
+ autoFocus?: boolean;
8
+ }
9
+
10
+ export function CardHolder({
11
+ autoFocus,
12
+ disabled,
13
+ placeholder,
14
+ readOnly,
15
+ }: CardHolderProps) {
16
+ const context = useCardContext();
17
+
18
+ const { onBlur, onChange } = context.register('name');
19
+
20
+ useEffect(() => {
21
+ context.setRegisteredFields((prev) => new Set(prev).add('name'));
22
+ // eslint-disable-next-line react-hooks/exhaustive-deps
23
+ }, []);
24
+
25
+ return (
26
+ <TextInput
27
+ id="name"
28
+ value={context.values.name}
29
+ readOnly={readOnly}
30
+ onBlur={onBlur}
31
+ autoFocus={autoFocus}
32
+ editable={disabled}
33
+ selectTextOnFocus={disabled}
34
+ placeholder={placeholder}
35
+ autoComplete="cc-name"
36
+ onChangeText={(v) => onChange(v)}
37
+ />
38
+ );
39
+ }
@@ -0,0 +1,64 @@
1
+ import { validateNumber } from '@evervault/card-validator';
2
+ import { useEffect, useMemo, useRef } from 'react';
3
+ import { TextInputMask } from 'react-native-masked-text';
4
+ import { useCardContext } from './context';
5
+ import { BaseProps } from './Card';
6
+
7
+ interface CardNumberProps extends BaseProps {
8
+ autoFocus?: boolean;
9
+ }
10
+
11
+ export function CardNumber({
12
+ autoFocus,
13
+ disabled,
14
+ placeholder,
15
+ readOnly,
16
+ style,
17
+ }: CardNumberProps) {
18
+ const context = useCardContext();
19
+ const ref = useRef<TextInputMask>(null);
20
+
21
+ const [innerValue, mask] = useMemo(() => {
22
+ const value = context.values.number;
23
+
24
+ const { brand } = validateNumber(value);
25
+
26
+ const masks = {
27
+ 'default': '9999 9999 9999 9999',
28
+ 'unionpay': '9999 9999 9999 9999 999',
29
+ 'american-express': '9999 999999 99999',
30
+ } as Record<string, string>;
31
+
32
+ if (brand && !!masks[brand]) {
33
+ return [value, masks[brand]];
34
+ }
35
+ return [value, masks.default];
36
+ }, [context.values.number]);
37
+
38
+ const { onBlur, onChange } = context.register('number');
39
+
40
+ useEffect(() => {
41
+ context.setRegisteredFields((prev) => new Set(prev).add('number'));
42
+ // eslint-disable-next-line react-hooks/exhaustive-deps
43
+ }, []);
44
+
45
+ return (
46
+ <TextInputMask
47
+ style={style}
48
+ ref={ref}
49
+ type="custom"
50
+ options={{ mask }}
51
+ id="number"
52
+ value={innerValue}
53
+ onChangeText={onChange}
54
+ onBlur={onBlur}
55
+ readOnly={readOnly}
56
+ inputMode="numeric"
57
+ autoFocus={autoFocus}
58
+ placeholder={placeholder}
59
+ editable={disabled}
60
+ selectTextOnFocus={disabled}
61
+ autoComplete="cc-number"
62
+ />
63
+ );
64
+ }
@@ -0,0 +1,26 @@
1
+ import { UseFormReturn } from 'shared';
2
+ import { Dispatch, SetStateAction, createContext, useContext } from 'react';
3
+ import { CardForm } from './types';
4
+ import { CardField } from 'types';
5
+
6
+ type Context<T> = {
7
+ values: CardForm;
8
+ register: UseFormReturn<T>['register'];
9
+ setRegisteredFields: Dispatch<SetStateAction<Set<CardField>>>;
10
+ };
11
+
12
+ export const CardContext = createContext<Context<CardForm>>({
13
+ values: {
14
+ name: '',
15
+ number: '',
16
+ cvc: '',
17
+ expiry: '',
18
+ },
19
+ register: () => ({
20
+ onChange: () => { },
21
+ onBlur: () => { },
22
+ }),
23
+ setRegisteredFields: () => { },
24
+ });
25
+
26
+ export const useCardContext = () => useContext(CardContext);
@@ -0,0 +1,2 @@
1
+ export { Card, type CardProps } from './Card';
2
+ export { CardPayload } from 'types';
@@ -0,0 +1,15 @@
1
+ import type { CardBrandName } from 'types';
2
+
3
+ export interface CardConfig {
4
+ autoFocus?: boolean;
5
+ acceptedBrands?: CardBrandName[];
6
+ }
7
+
8
+ export interface CardForm {
9
+ name: string;
10
+ number: string;
11
+ cvc: string;
12
+ expiry: string;
13
+ }
14
+
15
+ export { CardBrandName };
@@ -0,0 +1,105 @@
1
+ import {
2
+ validateNumber,
3
+ validateExpiry,
4
+ validateCVC,
5
+ CardNumberValidationResult,
6
+ } from '@evervault/card-validator';
7
+ import type { CardForm } from './types';
8
+ import type { CardBrandName, CardField, CardPayload } from 'types';
9
+ import { UseFormReturn } from 'shared';
10
+
11
+ export async function changePayload(
12
+ encrypt: (value: string) => Promise<string>,
13
+ form: UseFormReturn<CardForm>,
14
+ fields: CardField[]
15
+ ): Promise<CardPayload> {
16
+ const { name, number, expiry, cvc } = form.values;
17
+ const {
18
+ brand,
19
+ localBrands,
20
+ bin,
21
+ lastFour,
22
+ isValid: isValidCardNumber,
23
+ } = validateNumber(number);
24
+
25
+ return {
26
+ card: {
27
+ name,
28
+ brand,
29
+ localBrands,
30
+ bin,
31
+ lastFour,
32
+ number: isValidCardNumber ? await encryptedNumber(encrypt, number) : null,
33
+ expiry: formatExpiry(expiry),
34
+ cvc: await encryptedCVC(encrypt, cvc, number),
35
+ },
36
+ isValid: form.isValid,
37
+ isComplete: isComplete(form, fields),
38
+ errors: Object.keys(form.errors ?? {}).length > 0 ? form.errors : null,
39
+ };
40
+ }
41
+
42
+ export function isComplete(form: UseFormReturn<CardForm>, fields: CardField[]) {
43
+ if (fields.includes('name')) {
44
+ if (form.values.name.length === 0) return false;
45
+ }
46
+
47
+ if (fields.includes('number')) {
48
+ const cardValidation = validateNumber(form.values.number);
49
+ if (!cardValidation.isValid) return false;
50
+ }
51
+
52
+ if (fields.includes('expiry')) {
53
+ const expiryValidation = validateExpiry(form.values.expiry.replace(" / ", ""));
54
+ if (!expiryValidation.isValid) return false;
55
+ }
56
+
57
+ if (fields.includes('cvc')) {
58
+ const cvcValidation = validateCVC(form.values.cvc, form.values.number);
59
+ if (!cvcValidation.isValid) return false;
60
+ }
61
+
62
+ return true;
63
+ }
64
+
65
+ export function isAcceptedBrand(
66
+ acceptedBrands: CardBrandName[] | undefined,
67
+ cardNumberValidationResult: CardNumberValidationResult
68
+ ): boolean {
69
+ if (!acceptedBrands) return true;
70
+ const { brand, localBrands } = cardNumberValidationResult;
71
+
72
+ const isBrandAccepted = brand !== null && acceptedBrands.includes(brand);
73
+ const isLocalBrandAccepted = localBrands.some((localBrand) =>
74
+ acceptedBrands.includes(localBrand)
75
+ );
76
+
77
+ return isBrandAccepted || isLocalBrandAccepted;
78
+ }
79
+
80
+ function formatExpiry(expiry: string) {
81
+ const parsedExpiry = validateExpiry(expiry.replace(" / ", ""));
82
+
83
+ return {
84
+ month: parsedExpiry.month,
85
+ year: parsedExpiry.year,
86
+ };
87
+ }
88
+
89
+ async function encryptedNumber(
90
+ encrypt: (value: string) => Promise<string>,
91
+ number: string
92
+ ) {
93
+ return encrypt(number);
94
+ }
95
+
96
+ async function encryptedCVC(
97
+ encrypt: (value: string) => Promise<string>,
98
+ cvc: string,
99
+ cardNumber: string
100
+ ) {
101
+ const { isValid } = validateCVC(cvc, cardNumber);
102
+
103
+ if (!isValid) return null;
104
+ return encrypt(cvc);
105
+ }
File without changes
@@ -0,0 +1 @@
1
+ // export * from './Card';
package/src/index.tsx CHANGED
@@ -1,26 +1,3 @@
1
- import { NativeModules, Platform } from 'react-native';
2
-
3
- const LINKING_ERROR =
4
- `The package '@evervault/evervault-react-native' doesn't seem to be linked. Make sure: \n\n` +
5
- Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
6
- '- You rebuilt the app after installing the package\n' +
7
- '- You are not using Expo Go\n';
8
-
9
- const EvervaultSdk = NativeModules.EvervaultSdk
10
- ? NativeModules.EvervaultSdk
11
- : new Proxy(
12
- {},
13
- {
14
- get() {
15
- throw new Error(LINKING_ERROR);
16
- },
17
- }
18
- );
19
-
20
- export async function init(teamUuid: string, appUuid: string): Promise<void> {
21
- return EvervaultSdk.initialize(teamUuid, appUuid);
22
- }
23
-
24
- export async function encrypt(data: any): Promise<string> {
25
- return EvervaultSdk.encrypt(data);
26
- }
1
+ export { type CardProps, Card } from './components/Card/Card';
2
+ export { init, encrypt } from './sdk';
3
+ export type { CardPayload, CardExpiry } from 'types';
package/src/native.ts ADDED
@@ -0,0 +1,18 @@
1
+ import { NativeModules, Platform } from 'react-native';
2
+
3
+ const LINKING_ERROR =
4
+ `The package '@evervault/evervault-react-native' doesn't seem to be linked. Make sure: \n\n` +
5
+ Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
6
+ '- You rebuilt the app after installing the package\n' +
7
+ '- You are not using Expo Go\n';
8
+
9
+ export const EvervaultSdk = NativeModules.EvervaultSdk
10
+ ? NativeModules.EvervaultSdk
11
+ : new Proxy(
12
+ {},
13
+ {
14
+ get() {
15
+ throw new Error(LINKING_ERROR);
16
+ },
17
+ }
18
+ );
package/src/sdk.ts ADDED
@@ -0,0 +1,17 @@
1
+ import { Platform } from "react-native";
2
+ import { EvervaultSdk } from "./native";
3
+
4
+ export async function init(teamUuid: string, appUuid: string): Promise<void> {
5
+ return EvervaultSdk.initialize(teamUuid, appUuid);
6
+ }
7
+
8
+ export async function encrypt(data: any): Promise<string> {
9
+ if (Platform.OS === "android" && typeof data !== "string") {
10
+ throw new Error(`The Evervault SDK does not currently support encrypting non-string data on Android.
11
+ If this is required for your use case, please get in touch with us at support@evervault.com. Please do not
12
+ serialize other data types to strings and pass them to this method as this will result in the data
13
+ type being returned in it's stringified form when decryption occurs.`);
14
+ }
15
+
16
+ return EvervaultSdk.encrypt(data.toString());
17
+ }