@evervault/react-native 2.6.0 → 2.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/package.json +3 -2
  2. package/src/Card/Cvc.test.tsx +41 -0
  3. package/src/Card/Cvc.tsx +58 -0
  4. package/src/Card/Expiry.tsx +26 -0
  5. package/src/Card/Holder.tsx +27 -0
  6. package/src/Card/Number.test.tsx +76 -0
  7. package/src/Card/Number.tsx +54 -0
  8. package/src/Card/Root.test.tsx +341 -0
  9. package/src/Card/Root.tsx +150 -0
  10. package/src/Card/index.ts +28 -0
  11. package/src/Card/schema.ts +41 -0
  12. package/src/Card/types.ts +57 -0
  13. package/src/Card/utils.test.ts +271 -0
  14. package/src/Card/utils.ts +129 -0
  15. package/src/EvervaultProvider.test.tsx +24 -0
  16. package/src/EvervaultProvider.tsx +43 -0
  17. package/src/Input.test.tsx +420 -0
  18. package/src/Input.tsx +182 -0
  19. package/src/ThreeDSecure/Frame.test.tsx +87 -0
  20. package/src/ThreeDSecure/Frame.tsx +50 -0
  21. package/src/ThreeDSecure/Root.test.tsx +67 -0
  22. package/src/ThreeDSecure/Root.tsx +23 -0
  23. package/src/ThreeDSecure/config.ts +3 -0
  24. package/src/ThreeDSecure/context.ts +6 -0
  25. package/src/ThreeDSecure/event.ts +19 -0
  26. package/src/ThreeDSecure/index.ts +17 -0
  27. package/src/ThreeDSecure/session.test.ts +524 -0
  28. package/src/ThreeDSecure/session.ts +184 -0
  29. package/src/ThreeDSecure/types.ts +80 -0
  30. package/src/ThreeDSecure/useThreeDSecure.test.tsx +244 -0
  31. package/src/ThreeDSecure/useThreeDSecure.ts +64 -0
  32. package/src/__mocks__/NativeEvervault.ts +13 -0
  33. package/src/__mocks__/react-native-webview.tsx +6 -0
  34. package/src/context.ts +14 -0
  35. package/src/index.ts +21 -0
  36. package/src/sdk.test.ts +122 -0
  37. package/src/sdk.ts +71 -0
  38. package/src/specs/NativeEvervault.ts +67 -0
  39. package/src/useEvervault.test.tsx +31 -0
  40. package/src/useEvervault.ts +14 -0
  41. package/src/utils.ts +41 -0
@@ -0,0 +1,80 @@
1
+ import { ThreeDSecureEvent } from "./event";
2
+
3
+ export interface ThreeDSecureCallbacks {
4
+ /**
5
+ * The error event will be fired if the component fails to load.
6
+ */
7
+ onError?(error: Error): void;
8
+
9
+ /**
10
+ * The 'requestChallenge' event will be fired if the 3DS authentication process requires a challenge.
11
+ * If you'd like to fail the authentication, you should call `preventDefault` on the passed event.
12
+ */
13
+ onRequestChallenge?(event: ThreeDSecureEvent): void;
14
+
15
+ /**
16
+ * The 'failure' event will be fired if the 3DS authentication process fails. You should use this event to handle the failure and inform the user and prompt them to try again.
17
+ * If the user cancels the 3DS authentication process this event will be fired.
18
+ */
19
+ onFailure?(error: Error): void;
20
+
21
+ /**
22
+ * The 'success' event will be fired once the 3DS authentication process has been completed successfully.
23
+ * You should use this event to trigger your backend to finalize the payment.
24
+ * Your backend can use the [Retrieve 3DS Session](https://docs.evervault.com/api-reference#retrieveThreeDSSession) endpoint to retrieve the cryptogram for the session and complete the payment.
25
+ */
26
+ onSuccess?(): void;
27
+ }
28
+
29
+ export interface ThreeDSecureOptions extends ThreeDSecureCallbacks {
30
+ /**
31
+ * If set to `true` (or a function that returns `true`), the authentication will fail if a challenge is required.
32
+ */
33
+ failOnChallenge?: boolean | (() => Promise<boolean>);
34
+ }
35
+
36
+ export interface ThreeDSecureInitialState {
37
+ session: ThreeDSecureSession | null;
38
+ isVisible: boolean;
39
+ }
40
+
41
+ export interface ThreeDSecureSession {
42
+ cancel(): Promise<void>;
43
+ get(): Promise<ThreeDSecureSessionResponse>;
44
+ sessionId: string;
45
+ }
46
+
47
+ export type SessionStatus = "action-required" | "failure" | "success";
48
+
49
+ export interface ThreeDSecureSessionResponse {
50
+ nextAction: {
51
+ creq?: string;
52
+ type: string;
53
+ url?: string;
54
+ };
55
+ status: SessionStatus;
56
+ }
57
+
58
+ export interface ThreeDSecureSessionsParams {
59
+ appId: string;
60
+ options?: ThreeDSecureOptions;
61
+ intervalRef: React.MutableRefObject<NodeJS.Timeout | null>;
62
+ sessionId: string;
63
+ setIsVisible: (show: boolean) => void;
64
+ }
65
+
66
+ export interface ThreeDSecureState extends ThreeDSecureInitialState {
67
+ /**
68
+ * The `cancel()` function is used to cancel the ongoing 3DS authentication process.
69
+ * This can be particularly useful for canceling a session when a custom cancel button is triggered.
70
+ */
71
+ cancel(): Promise<void>;
72
+
73
+ /**
74
+ * The `start()` function is used to kick off the 3DS authentication process.
75
+ *
76
+ * @param sessionId The 3DS session ID. A 3DS session can be created using the [Evervault API](https://docs.evervault.com/api-reference#createThreeDSSession).
77
+ * @param options The options to be used for the 3DS authentication process.
78
+ */
79
+ start(sessionId: string, options?: ThreeDSecureOptions): void;
80
+ }
@@ -0,0 +1,244 @@
1
+ import { PropsWithChildren } from "react";
2
+ import { EvervaultProvider } from "../EvervaultProvider";
3
+ import { act, renderHook } from "@testing-library/react-native";
4
+ import { useThreeDSecure } from "./useThreeDSecure";
5
+ import { ThreeDSecureEvent } from "./event";
6
+
7
+ function wrapper({ children }: PropsWithChildren) {
8
+ return (
9
+ <EvervaultProvider teamId="team_123" appId="app_123">
10
+ {children}
11
+ </EvervaultProvider>
12
+ );
13
+ }
14
+
15
+ const callbacks = {
16
+ onSuccess: vi.fn(),
17
+ onError: vi.fn(),
18
+ onFailure: vi.fn(),
19
+ };
20
+
21
+ beforeEach(() => {
22
+ vi.clearAllMocks();
23
+ });
24
+
25
+ it("returns the correct state", () => {
26
+ const { result } = renderHook(() => useThreeDSecure(), {
27
+ wrapper,
28
+ });
29
+
30
+ expect(result.current).toEqual({
31
+ start: expect.any(Function),
32
+ cancel: expect.any(Function),
33
+ session: null,
34
+ isVisible: false,
35
+ });
36
+ });
37
+
38
+ it("starts a session when action is required", async () => {
39
+ const { result } = renderHook(() => useThreeDSecure(), {
40
+ wrapper,
41
+ });
42
+
43
+ vi.spyOn(global, "fetch").mockResolvedValue({
44
+ json: () => Promise.resolve({ status: "action-required" }),
45
+ } as any);
46
+
47
+ await act(() => result.current.start("session_123", callbacks));
48
+
49
+ expect(result.current.session).toEqual({
50
+ sessionId: "session_123",
51
+ cancel: expect.any(Function),
52
+ get: expect.any(Function),
53
+ });
54
+ expect(result.current.isVisible).toBe(true);
55
+ });
56
+
57
+ it("fails the session when failOnChallenge is true and a challenge is required", async () => {
58
+ const { result } = renderHook(() => useThreeDSecure(), {
59
+ wrapper,
60
+ });
61
+
62
+ vi.spyOn(global, "fetch").mockResolvedValue({
63
+ json: () => Promise.resolve({ status: "action-required" }),
64
+ } as any);
65
+
66
+ const onRequestChallenge = vi.fn();
67
+
68
+ await act(() =>
69
+ result.current.start("session_123", {
70
+ ...callbacks,
71
+ onRequestChallenge,
72
+ failOnChallenge: true,
73
+ })
74
+ );
75
+
76
+ expect(callbacks.onFailure).toHaveBeenCalled();
77
+ expect(onRequestChallenge).not.toHaveBeenCalled();
78
+ });
79
+
80
+ it("fails the session when failOnChallenge is a function that returns true and a challenge is required", async () => {
81
+ const { result } = renderHook(() => useThreeDSecure(), {
82
+ wrapper,
83
+ });
84
+
85
+ vi.spyOn(global, "fetch").mockResolvedValue({
86
+ json: () => Promise.resolve({ status: "action-required" }),
87
+ } as any);
88
+
89
+ const onRequestChallenge = vi.fn();
90
+
91
+ await act(() =>
92
+ result.current.start("session_123", {
93
+ ...callbacks,
94
+ onRequestChallenge,
95
+ failOnChallenge: () => Promise.resolve(true),
96
+ })
97
+ );
98
+
99
+ expect(callbacks.onFailure).toHaveBeenCalled();
100
+ expect(onRequestChallenge).not.toHaveBeenCalled();
101
+ });
102
+
103
+ it("fails the session when failOnChallenge resolves true at hook level and a challenge is required", async () => {
104
+ const { result } = renderHook(
105
+ () =>
106
+ useThreeDSecure({
107
+ failOnChallenge: () => Promise.resolve(true),
108
+ }),
109
+ {
110
+ wrapper,
111
+ }
112
+ );
113
+
114
+ vi.spyOn(global, "fetch").mockResolvedValue({
115
+ json: () => Promise.resolve({ status: "action-required" }),
116
+ } as any);
117
+
118
+ const onRequestChallenge = vi.fn();
119
+ await act(() =>
120
+ result.current.start("session_123", {
121
+ ...callbacks,
122
+ onRequestChallenge,
123
+ })
124
+ );
125
+
126
+ expect(onRequestChallenge).not.toHaveBeenCalled();
127
+ expect(callbacks.onFailure).toHaveBeenCalled();
128
+ });
129
+
130
+ it("fails the session when onRequestChallenge is called and defaultPrevented is true", async () => {
131
+ const { result } = renderHook(() => useThreeDSecure(), {
132
+ wrapper,
133
+ });
134
+
135
+ vi.spyOn(global, "fetch").mockResolvedValue({
136
+ json: () => Promise.resolve({ status: "action-required" }),
137
+ } as any);
138
+
139
+ let onRequestChallenge = vi.fn((event: ThreeDSecureEvent) =>
140
+ event.preventDefault()
141
+ );
142
+ await act(() =>
143
+ result.current.start("session_123", {
144
+ ...callbacks,
145
+ onRequestChallenge,
146
+ })
147
+ );
148
+ expect(onRequestChallenge).toHaveBeenCalled();
149
+ expect(callbacks.onFailure).toHaveBeenCalled();
150
+
151
+ let onFailure = vi.fn();
152
+ onRequestChallenge = vi.fn();
153
+ await act(() =>
154
+ result.current.start("session_123", {
155
+ onFailure,
156
+ onRequestChallenge,
157
+ })
158
+ );
159
+ expect(onRequestChallenge).toHaveBeenCalled();
160
+ expect(onFailure).not.toHaveBeenCalled();
161
+ });
162
+
163
+ it("calls the success callback when the session is successful", async () => {
164
+ const { result } = renderHook(() => useThreeDSecure(), {
165
+ wrapper,
166
+ });
167
+
168
+ vi.spyOn(global, "fetch").mockResolvedValue({
169
+ json: () => Promise.resolve({ status: "success" }),
170
+ } as any);
171
+
172
+ await act(() => result.current.start("session_123", callbacks));
173
+
174
+ expect(callbacks.onSuccess).toHaveBeenCalled();
175
+ });
176
+
177
+ it("calls the failure callback when the session fails on start", async () => {
178
+ const { result } = renderHook(() => useThreeDSecure(), {
179
+ wrapper,
180
+ });
181
+
182
+ vi.spyOn(global, "fetch").mockResolvedValue({
183
+ json: () => Promise.resolve({ status: "failure" }),
184
+ } as any);
185
+
186
+ await act(() => result.current.start("session_123", callbacks));
187
+
188
+ expect(callbacks.onFailure).toHaveBeenCalled();
189
+ });
190
+
191
+ it("calls the error callback when the fetch fails on start", async () => {
192
+ const { result } = renderHook(() => useThreeDSecure(), {
193
+ wrapper,
194
+ });
195
+
196
+ vi.spyOn(global, "fetch").mockRejectedValue(new Error("Session failed"));
197
+
198
+ await act(() => result.current.start("session_123", callbacks));
199
+
200
+ expect(callbacks.onError).toHaveBeenCalled();
201
+ });
202
+
203
+ it("silently fails if the session is not found", async () => {
204
+ const { result } = renderHook(() => useThreeDSecure(), {
205
+ wrapper,
206
+ });
207
+
208
+ const consoleWarnSpy = vi.spyOn(console, "warn");
209
+
210
+ await act(() => result.current.cancel());
211
+
212
+ expect(result.current.session).toBeNull();
213
+ expect(result.current.isVisible).toBe(false);
214
+ expect(consoleWarnSpy).toHaveBeenCalledWith("No 3DS session to cancel");
215
+ });
216
+
217
+ it("cancels the session when the user cancels", async () => {
218
+ const { result } = renderHook(() => useThreeDSecure(), {
219
+ wrapper,
220
+ });
221
+
222
+ vi.spyOn(global, "fetch").mockResolvedValue({
223
+ json: () => Promise.resolve({ status: "action-required" }),
224
+ } as any);
225
+
226
+ await act(() => result.current.start("session_123", callbacks));
227
+
228
+ expect(result.current.session).toEqual({
229
+ sessionId: "session_123",
230
+ cancel: expect.any(Function),
231
+ get: expect.any(Function),
232
+ });
233
+ expect(result.current.isVisible).toBe(true);
234
+
235
+ await act(() => result.current.session?.cancel());
236
+
237
+ expect(result.current.session).toEqual({
238
+ sessionId: "session_123",
239
+ cancel: expect.any(Function),
240
+ get: expect.any(Function),
241
+ });
242
+ expect(result.current.isVisible).toBe(false);
243
+ expect(callbacks.onFailure).toHaveBeenCalled();
244
+ });
@@ -0,0 +1,64 @@
1
+ import { useCallback, useMemo, useState } from "react";
2
+ import { useRef } from "react";
3
+ import { startSession, threeDSecureSession } from "./session";
4
+ import {
5
+ ThreeDSecureOptions,
6
+ ThreeDSecureSession,
7
+ ThreeDSecureState,
8
+ } from "./types";
9
+ import { useEvervault } from "../useEvervault";
10
+
11
+ export interface UseThreeDSecureOptions {
12
+ failOnChallenge?: boolean | (() => Promise<boolean>);
13
+ }
14
+
15
+ export function useThreeDSecure(
16
+ options?: UseThreeDSecureOptions
17
+ ): ThreeDSecureState {
18
+ const { appId } = useEvervault();
19
+ const intervalRef = useRef<NodeJS.Timeout | null>(null);
20
+ const [session, setSession] = useState<ThreeDSecureSession | null>(null);
21
+ const [isVisible, setIsVisible] = useState(false);
22
+
23
+ const failOnChallenge = options?.failOnChallenge ?? false;
24
+
25
+ const start = useCallback<ThreeDSecureState["start"]>(
26
+ (sessionId, options) => {
27
+ const startOptions: ThreeDSecureOptions = {
28
+ ...options,
29
+ failOnChallenge: options?.failOnChallenge ?? failOnChallenge,
30
+ };
31
+
32
+ const session = threeDSecureSession({
33
+ sessionId,
34
+ appId,
35
+ options: startOptions,
36
+ intervalRef,
37
+ setIsVisible,
38
+ });
39
+
40
+ setSession(session);
41
+
42
+ startSession(session, startOptions, intervalRef, setIsVisible);
43
+ },
44
+ [appId, failOnChallenge]
45
+ );
46
+
47
+ const cancel = useCallback<ThreeDSecureState["cancel"]>(async () => {
48
+ if (session) {
49
+ await session.cancel();
50
+ } else {
51
+ console.warn("No 3DS session to cancel");
52
+ }
53
+ }, [session]);
54
+
55
+ return useMemo(
56
+ () => ({
57
+ start,
58
+ cancel,
59
+ session,
60
+ isVisible,
61
+ }),
62
+ [start, cancel, session, isVisible]
63
+ );
64
+ }
@@ -0,0 +1,13 @@
1
+ import type { Spec } from "../specs/NativeEvervault";
2
+
3
+ export const encryptedValue =
4
+ "ev:W98t:uu98aas09udya863ty9372y7y23h97rg6gfs678987";
5
+
6
+ export const NativeEvervault: Spec = {
7
+ initialize: vi.fn(),
8
+ encryptString: vi.fn(() => Promise.resolve(encryptedValue)),
9
+ encryptNumber: vi.fn(() => Promise.resolve(encryptedValue)),
10
+ encryptBoolean: vi.fn(() => Promise.resolve(encryptedValue)),
11
+ encryptObject: vi.fn(),
12
+ encryptArray: vi.fn(),
13
+ };
@@ -0,0 +1,6 @@
1
+ import { View } from "react-native";
2
+ import type { WebViewProps } from "react-native-webview";
3
+
4
+ export function WebView(props: WebViewProps) {
5
+ return <View testID="webview" {...props} />;
6
+ }
package/src/context.ts ADDED
@@ -0,0 +1,14 @@
1
+ import { createContext } from "react";
2
+ import type { Encrypted } from "./sdk";
3
+
4
+ export type EncryptFn = <T>(data: T) => Promise<Encrypted<T>>;
5
+
6
+ export interface EvervaultContextValue {
7
+ teamId: string;
8
+ appId: string;
9
+ encrypt: EncryptFn;
10
+ }
11
+
12
+ export const EvervaultContext = createContext<EvervaultContextValue | null>(
13
+ null
14
+ );
package/src/index.ts ADDED
@@ -0,0 +1,21 @@
1
+ import { sdk } from "./sdk";
2
+
3
+ export const verifyInstallation = sdk.verify;
4
+
5
+ export type { Encrypted } from "./sdk";
6
+
7
+ export {
8
+ EvervaultProvider,
9
+ type EvervaultProviderProps,
10
+ } from "./EvervaultProvider";
11
+
12
+ export type { EncryptFn } from "./context";
13
+ export { useEvervault } from "./useEvervault";
14
+
15
+ export type {
16
+ EvervaultInput,
17
+ BaseEvervaultInputProps as EvervaultInputProps,
18
+ } from "./Input";
19
+
20
+ export * from "./Card";
21
+ export * from "./ThreeDSecure";
@@ -0,0 +1,122 @@
1
+ import { NativeEvervault } from "./__mocks__/NativeEvervault";
2
+ import { sdk } from "./sdk";
3
+
4
+ describe("sdk", () => {
5
+ describe("verify", () => {
6
+ it("should return true", () => {
7
+ expect(sdk.verify()).toBe(true);
8
+ });
9
+ });
10
+
11
+ describe("initialize", () => {
12
+ it("throws an error if teamId is not provided", () => {
13
+ expect(() => sdk.initialize("", "appId")).toThrow("Team ID is required.");
14
+ });
15
+
16
+ it("throws an error if appId is not provided", () => {
17
+ expect(() => sdk.initialize("teamId", "")).toThrow("App ID is required.");
18
+ });
19
+
20
+ it("initializes the sdk", () => {
21
+ sdk.initialize("teamId", "appId");
22
+ expect(NativeEvervault.initialize).toHaveBeenCalledWith(
23
+ "teamId",
24
+ "appId"
25
+ );
26
+ });
27
+ });
28
+
29
+ describe("encrypt", () => {
30
+ it("encrypts an undefined value", async () => {
31
+ const result = await sdk.encrypt("instanceId", undefined);
32
+ expect(result).toBe(undefined);
33
+ expect(NativeEvervault.encryptString).not.toHaveBeenCalled();
34
+ expect(NativeEvervault.encryptNumber).not.toHaveBeenCalled();
35
+ expect(NativeEvervault.encryptBoolean).not.toHaveBeenCalled();
36
+ expect(NativeEvervault.encryptObject).not.toHaveBeenCalled();
37
+ expect(NativeEvervault.encryptArray).not.toHaveBeenCalled();
38
+ });
39
+
40
+ it("encrypts a null value", async () => {
41
+ const result = await sdk.encrypt("instanceId", null);
42
+ expect(result).toBe(null);
43
+ expect(NativeEvervault.encryptString).not.toHaveBeenCalled();
44
+ expect(NativeEvervault.encryptNumber).not.toHaveBeenCalled();
45
+ expect(NativeEvervault.encryptBoolean).not.toHaveBeenCalled();
46
+ expect(NativeEvervault.encryptObject).not.toHaveBeenCalled();
47
+ expect(NativeEvervault.encryptArray).not.toHaveBeenCalled();
48
+ });
49
+
50
+ it("encrypts a string", async () => {
51
+ await sdk.encrypt("instanceId", "hello");
52
+ expect(NativeEvervault.encryptString).toHaveBeenCalledWith(
53
+ "instanceId",
54
+ "hello"
55
+ );
56
+ assertType<Promise<string>>(sdk.encrypt("instanceId", "hello"));
57
+ });
58
+
59
+ it("encrypts a number", async () => {
60
+ await sdk.encrypt("instanceId", 123);
61
+ expect(NativeEvervault.encryptNumber).toHaveBeenCalledWith(
62
+ "instanceId",
63
+ 123
64
+ );
65
+ assertType<Promise<string>>(sdk.encrypt("instanceId", 123));
66
+ });
67
+
68
+ it("encrypts a boolean", async () => {
69
+ await sdk.encrypt("instanceId", true);
70
+ expect(NativeEvervault.encryptBoolean).toHaveBeenCalledWith(
71
+ "instanceId",
72
+ true
73
+ );
74
+ assertType<Promise<string>>(sdk.encrypt("instanceId", true));
75
+ });
76
+
77
+ it("encrypts an object", async () => {
78
+ await sdk.encrypt("instanceId", { a: 1, b: 2 });
79
+ expect(NativeEvervault.encryptObject).toHaveBeenCalledWith("instanceId", {
80
+ a: 1,
81
+ b: 2,
82
+ });
83
+ assertType<Promise<{ a: string; b: string }>>(
84
+ sdk.encrypt("instanceId", { a: 1, b: 2 })
85
+ );
86
+ });
87
+
88
+ it("encrypts a deep object", async () => {
89
+ await sdk.encrypt("instanceId", { a: 1, b: { c: 2, d: 3 } });
90
+ expect(NativeEvervault.encryptObject).toHaveBeenCalledWith("instanceId", {
91
+ a: 1,
92
+ b: { c: 2, d: 3 },
93
+ });
94
+ assertType<Promise<{ a: string; b: { c: string; d: string } }>>(
95
+ sdk.encrypt("instanceId", { a: 1, b: { c: 2, d: 3 } })
96
+ );
97
+ });
98
+
99
+ it("encrypts an array", async () => {
100
+ await sdk.encrypt("instanceId", [1, 2, 3]);
101
+ expect(NativeEvervault.encryptArray).toHaveBeenCalledWith(
102
+ "instanceId",
103
+ [1, 2, 3]
104
+ );
105
+ assertType<Promise<Array<string>>>(sdk.encrypt("instanceId", [1, 2, 3]));
106
+ });
107
+
108
+ it("throws an error if the data is not supported", async () => {
109
+ const fn = () => {};
110
+ await expect(() => sdk.encrypt("instanceId", fn)).rejects.toThrow(
111
+ "Unsupported data type."
112
+ );
113
+ assertType<() => Promise<never>>(() => sdk.encrypt("instanceId", fn));
114
+
115
+ const symbol = Symbol("test");
116
+ await expect(() => sdk.encrypt("instanceId", symbol)).rejects.toThrow(
117
+ "Unsupported data type."
118
+ );
119
+ assertType<() => Promise<never>>(() => sdk.encrypt("instanceId", symbol));
120
+ });
121
+ });
122
+ });
package/src/sdk.ts ADDED
@@ -0,0 +1,71 @@
1
+ import {
2
+ NativeEvervault,
3
+ Spec as NativeEvervaultSpec,
4
+ } from "./specs/NativeEvervault";
5
+
6
+ export type Encrypted<T> = T extends undefined
7
+ ? undefined
8
+ : T extends null
9
+ ? null
10
+ : T extends string | number | boolean
11
+ ? string
12
+ : T extends Function
13
+ ? never
14
+ : T extends object
15
+ ? {
16
+ [K in keyof T]: Encrypted<T[K]>;
17
+ }
18
+ : T extends Array<infer U>
19
+ ? Array<Encrypted<U>>
20
+ : never;
21
+
22
+ function getModule(): NativeEvervaultSpec {
23
+ if (!NativeEvervault) {
24
+ throw new Error("NativeEvervault is not available.");
25
+ }
26
+
27
+ return NativeEvervault;
28
+ }
29
+
30
+ export const sdk = {
31
+ verify() {
32
+ getModule();
33
+ return true;
34
+ },
35
+
36
+ initialize(teamId: string, appId: string): string {
37
+ const evervault = getModule();
38
+
39
+ if (!teamId) {
40
+ throw new Error("Team ID is required.");
41
+ }
42
+
43
+ if (!appId) {
44
+ throw new Error("App ID is required.");
45
+ }
46
+
47
+ return evervault.initialize(teamId, appId);
48
+ },
49
+
50
+ async encrypt<T>(instanceId: string, data: T): Promise<Encrypted<T>> {
51
+ const evervault = getModule();
52
+
53
+ if (data === undefined) {
54
+ return undefined as any;
55
+ } else if (data === null) {
56
+ return null as any;
57
+ } else if (typeof data === "string") {
58
+ return (await evervault.encryptString(instanceId, data)) as any;
59
+ } else if (typeof data === "number") {
60
+ return (await evervault.encryptNumber(instanceId, data)) as any;
61
+ } else if (typeof data === "boolean") {
62
+ return (await evervault.encryptBoolean(instanceId, data)) as any;
63
+ } else if (Array.isArray(data)) {
64
+ return (await evervault.encryptArray(instanceId, data)) as any;
65
+ } else if (typeof data === "object") {
66
+ return (await evervault.encryptObject(instanceId, data)) as any;
67
+ }
68
+
69
+ throw new Error("Unsupported data type.");
70
+ },
71
+ };