Skip to content

Commit 02f1fe8

Browse files
committed
feat(js-module): create AsyncStorageError handle throw it
1 parent a1cdce8 commit 02f1fe8

File tree

2 files changed

+168
-22
lines changed

2 files changed

+168
-22
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
export class AsyncStorageError extends Error {
2+
private constructor(
3+
public errorMessage: string,
4+
public type: AsyncStorageError.Type
5+
) {
6+
super(errorMessage);
7+
this.name = this.constructor.name;
8+
}
9+
10+
static nativeError(e: any): AsyncStorageError {
11+
const error = getNativeError(e);
12+
if (!error) {
13+
return new AsyncStorageError(
14+
e?.message ?? `Unknown error ${e}`,
15+
AsyncStorageError.Type.UnknownError
16+
);
17+
}
18+
19+
let errorType: AsyncStorageError.Type = AsyncStorageError.Type.UnknownError;
20+
21+
switch (error.type) {
22+
case "SqliteException":
23+
errorType = AsyncStorageError.Type.SqliteStorageError;
24+
break;
25+
case "OtherException":
26+
errorType = AsyncStorageError.Type.OtherStorageError;
27+
break;
28+
}
29+
30+
return new AsyncStorageError(error.message, errorType);
31+
}
32+
33+
static jsError(
34+
error: string,
35+
type: AsyncStorageError.Type
36+
): AsyncStorageError {
37+
return new AsyncStorageError(error, type);
38+
}
39+
}
40+
41+
export namespace AsyncStorageError {
42+
export enum Type {
43+
/**
44+
* Related to RN Native module itself, ex. not initialized or null at app boot
45+
*/
46+
NativeModuleError = "NativeModuleError",
47+
48+
/**
49+
* Error thrown from Sqlite itself
50+
* https://www.sqlite.org/rescode.html
51+
*/
52+
SqliteStorageError = "SqliteStorageError",
53+
54+
/**
55+
* Other errors related to Native Shared Storage
56+
* ex. Storage could not be initialized
57+
*/
58+
OtherStorageError = "OtherStorageError",
59+
60+
/**
61+
* Catch-all case, where we can't really tell what went wrong
62+
*/
63+
UnknownError = "UnknownError",
64+
}
65+
}
66+
67+
// Native module reject promises with special code
68+
function isNativeError(e: any): e is PotentialNativeError {
69+
return "message" in e && "code" in e && e?.code === "AsyncStorageError";
70+
}
71+
72+
function getNativeError(e: any): AsyncStorageNativeError | null {
73+
if (!isNativeError(e)) {
74+
return null;
75+
}
76+
77+
let errorType = e.userInfo ? e.userInfo["type"] : null;
78+
79+
if (errorType === "SqliteException") {
80+
return {
81+
type: "SqliteException",
82+
message: e.message,
83+
};
84+
} else if (errorType === "OtherException") {
85+
return {
86+
type: "OtherException",
87+
message: e.message,
88+
};
89+
}
90+
91+
return null;
92+
}
93+
94+
type AsyncStorageNativeError = {
95+
message: string;
96+
type: "SqliteException" | "OtherException";
97+
};
98+
99+
type PotentialNativeError = {
100+
message: string;
101+
code: "AsyncStorageError";
102+
userInfo: Record<string, any> | null;
103+
};

packages/async-storage/src/createAsyncStorage.ts

Lines changed: 65 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,52 +2,95 @@ import type { AsyncStorage } from "./AsyncStorage";
22
import NativeAsyncStorage, {
33
type Spec as NativeAsyncStorageSpec,
44
} from "./native-module/NativeAsyncStorage";
5+
import { AsyncStorageError } from "./AsyncStorageError";
56

67
class AsyncStorageImpl implements AsyncStorage {
78
constructor(private readonly dbName: string) {}
89

910
private get db(): NativeAsyncStorageSpec {
1011
const mod = NativeAsyncStorage;
1112
if (!mod) {
12-
throw new Error(`Native module is null, cannot create db`);
13+
throw AsyncStorageError.jsError(
14+
`Native module is null, cannot create db`,
15+
AsyncStorageError.Type.NativeModuleError
16+
);
1317
}
1418
return mod;
1519
}
1620

1721
getItem = async (key: string): Promise<string | null> => {
18-
const result = await this.db.getValues(this.dbName, [key]);
19-
const value = result[0] ?? null;
20-
return value?.value ?? null;
22+
try {
23+
const result = await this.db.getValues(this.dbName, [key]);
24+
const value = result[0] ?? null;
25+
return value?.value ?? null;
26+
} catch (e) {
27+
throw AsyncStorageError.nativeError(e);
28+
}
2129
};
2230

2331
setItem = async (key: string, value: string): Promise<void> => {
24-
await this.db.setValues(this.dbName, [{ key, value }]);
32+
try {
33+
await this.db.setValues(this.dbName, [{ key, value }]);
34+
} catch (e) {
35+
throw AsyncStorageError.nativeError(e);
36+
}
2537
};
2638

27-
removeItem = async (key: string): Promise<void> =>
28-
this.db.removeValues(this.dbName, [key]);
39+
removeItem = async (key: string): Promise<void> => {
40+
try {
41+
await this.db.removeValues(this.dbName, [key]);
42+
} catch (e) {
43+
throw AsyncStorageError.nativeError(e);
44+
}
45+
};
2946

30-
getMany = async (keys: string[]): Promise<Record<string, string | null>> =>
31-
this.db.getValues(this.dbName, keys).then((entries) =>
32-
entries.reduce<Record<string, string | null>>((values, current) => {
33-
values[current.key] = current.value;
34-
return values;
35-
}, {})
36-
);
47+
getMany = async (keys: string[]): Promise<Record<string, string | null>> => {
48+
try {
49+
return await this.db.getValues(this.dbName, keys).then((entries) =>
50+
entries.reduce<Record<string, string | null>>((values, current) => {
51+
values[current.key] = current.value;
52+
return values;
53+
}, {})
54+
);
55+
} catch (e) {
56+
throw AsyncStorageError.nativeError(e);
57+
}
58+
};
3759

3860
setMany = async (entries: Record<string, string>): Promise<void> => {
39-
await this.db.setValues(
40-
this.dbName,
41-
Object.entries(entries).map(([key, value]) => ({ key, value }))
42-
);
61+
try {
62+
await this.db.setValues(
63+
this.dbName,
64+
Object.entries(entries).map(([key, value]) => ({ key, value }))
65+
);
66+
} catch (e) {
67+
throw AsyncStorageError.nativeError(e);
68+
}
4369
};
4470

45-
removeMany = async (keys: string[]): Promise<void> =>
46-
this.db.removeValues(this.dbName, keys);
71+
removeMany = async (keys: string[]): Promise<void> => {
72+
try {
73+
await this.db.removeValues(this.dbName, keys);
74+
} catch (e) {
75+
throw AsyncStorageError.nativeError(e);
76+
}
77+
};
4778

48-
getAllKeys = (): Promise<string[]> => this.db.getKeys(this.dbName);
79+
getAllKeys = async (): Promise<string[]> => {
80+
try {
81+
return await this.db.getKeys(this.dbName);
82+
} catch (e) {
83+
throw AsyncStorageError.nativeError(e);
84+
}
85+
};
4986

50-
clear = (): Promise<void> => this.db.clearStorage(this.dbName);
87+
clear = async (): Promise<void> => {
88+
try {
89+
return await this.db.clearStorage(this.dbName);
90+
} catch (e) {
91+
throw AsyncStorageError.nativeError(e);
92+
}
93+
};
5194
}
5295

5396
export function createAsyncStorage(databaseName: string): AsyncStorage {

0 commit comments

Comments
 (0)