expo-storage
Version:
Simple way to store persistent data, which does not have size limitations of react-native async-storage.
94 lines • 3 kB
JavaScript
import { File, Paths } from 'expo-file-system';
const isValidKey = (key) => {
// Prevent path traversal and ensure safe filenames
const safeKeyRegex = /^[a-zA-Z0-9-_\.]+$/;
return Boolean(key) && safeKeyRegex.test(key);
};
const serializeValue = (value) => {
try {
return typeof value === 'string' ? value : JSON.stringify(value);
}
catch (_a) {
throw new Error('Unable to serialize value');
}
};
const getErrorMessage = (error) => {
if (error instanceof Error)
return error.message;
return String(error);
};
const isFileNotFoundError = (error) => {
return error instanceof Error && 'code' in error && error.code === 'ENOENT';
};
const ensureStorageDirectoryExists = async () => {
const storageDir = Paths.document;
if (!storageDir.exists) {
await storageDir.create({ intermediates: true });
}
};
export const Storage = {
setItem: async ({ key, value }) => {
if (!isValidKey(key)) {
throw new Error(`Invalid storage key ${key}`);
}
await ensureStorageDirectoryExists();
const serializedValue = serializeValue(value);
try {
const file = new File(Paths.document, key);
await file.write(serializedValue);
}
catch (error) {
throw new Error(`Failed to write to storage: ${getErrorMessage(error)}`);
}
},
getItem: async ({ key }) => {
if (!isValidKey(key)) {
throw new Error(`Invalid storage key ${key}`);
}
try {
const file = new File(Paths.document, key);
if (!file.exists) {
return null;
}
const value = await file.text();
return value;
}
catch (error) {
if (isFileNotFoundError(error)) {
return null;
}
throw new Error(`Failed to read from storage: ${getErrorMessage(error)}`);
}
},
removeItem: async ({ key }) => {
if (!isValidKey(key)) {
throw new Error(`Invalid storage key ${key}`);
}
try {
const file = new File(Paths.document, key);
if (file.exists) {
await file.delete();
}
}
catch (error) {
throw new Error(`Failed to remove from storage: ${getErrorMessage(error)}`);
}
},
getAllKeys: async () => {
try {
await ensureStorageDirectoryExists();
const storageDir = Paths.document;
const contents = await storageDir.list();
const keys = contents
.filter(item => item instanceof File)
.map(file => file.name)
.filter(key => isValidKey(key));
return keys;
}
catch (error) {
throw new Error(`Failed to list storage keys: ${getErrorMessage(error)}`);
}
}
};
export default Storage;
//# sourceMappingURL=index.js.map