「暗号化+バックアップ版」Apollo Client の Reactive variables データと SQLite のデータを暗号化し バックアップ ➡︎ リストア する方法をご紹介しています。
開発環境(Expo Bare)
- “typescript”: “^5.2.2”
- “expo”: “~49.0.13”,
- “react”: “18.2.0”,
- “react-native”: “0.72.6”,
- “expo-router”: “^2.0.0”,
- “react-native-paper”: “^5.10.6”,
- “@apollo/client“: “^3.8.5”,
- “expo-sqlite”: “~11.3.3”,
- “crypto-js“: “^4.2.0”,
- “expo-sharing“: “~11.5.0”,
- “expo-file-system”: “~15.4.5”,
※24/02/13 追記Expo SDK@50 にアップグレードして node_modules/expo-router/_ctx.ios.tsx: Expected fromDir to be of type string, got undefined エラーが発生した場合は使い方がほぼ同じである rn-crypto-js を代わりに使っても良いと思います。
セットアップする
@apollo/client (フロントエンド ONLY)
// _layout.tsx
export default function RootLayout() {
const client = useApolloNoPersistClient();
...
return (
<SafeAreaProvider>
<ApolloProvider client={client}>
<PaperProvider theme={paperTheme}>
<RootLayoutNav />
<StatusBar style={preferredTheme === 'dark' ? 'light' : 'dark'} />
</PaperProvider>
</ApolloProvider>
</SafeAreaProvider>
);
}
// useApolloNoPersistClient.tsx
import {useState, useEffect} from 'react';
import {ApolloClient, InMemoryCache, NormalizedCacheObject} from '@apollo/client';
export const useApolloNoPersistClient = () => {
const [client, setClient] = useState<ApolloClient<NormalizedCacheObject>>(
{} as ApolloClient<NormalizedCacheObject>,
);
useEffect(() => {
async function init() {
setClient(new ApolloClient({cache: new InMemoryCache(), connectToDevTools: true}));
}
init().catch(err => {
console.log(err);
});
}, []);
return client;
};
expo-sqlite
詳細は下記をご参考ください。
crypto-js (暗号化ライブラリ)
inlineRequires: true 設定を追加する
// metro.config.js
...
module.exports = {
...config,
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),
},
};
react-native-get-random-values を追加する
yarn add react-native-get-random-values
crypto-jsをインポートする前に react-native-get-random-valuesをインポートする
// _layout.tsx
import 'react-native-get-random-values'; // <-- 追加する (Line1)
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {LogBox, AppState, Platform} from 'react-native';
。。。
crypto-jsを追加する
npm install crypto-js
プロジェクトをリビルドする
# For iOS npx pod-install npx react-native run-ios # For Android npx react-native run-android
expo-sharing / expo-file-system
割愛します。(expo-sharing、expo-file-system)
バックアップする
- Step1データを抽出する
// Reactive Variables const backupRVLists = [ {rvCommon: {userId:'123456', preferredTheme: 'light', point: 0, ...} ]; // SQLite const backupDBLists = [{items: items}]; const backupLists = [...backupRVLists, ...backupDBLists];※ items 抽出方法(例)
- Step2暗号化する
const ciphertextOfBackuped = CryptoJS.AES.encrypt( JSON.stringify(backupLists), 'secret key 123', ).toString();
- Step3プラットフォーム別バックアップする
自身の
iCound・Dropbox・Google Driveなど外部の媒体に保存します。if (Platform.OS === 'ios') { jcommonMapper.backupIOS(ciphertextOfBackuped); } else if (Platform.OS === 'android') { jcommonMapper.backupAndroid(ciphertextOfBackuped); } - Step3-1jcommonMapper.backupAndroid()
import {Share} from 'react-native'; import * as FileSystem from 'expo-file-system'; import * as Sharing from 'expo-sharing'; export const jcommonMapper = { ... backupAndroid: async (jsonData: string) => { const fileUrl = FileSystem.documentDirectory + `kotango.xxxxxxxx.json`; FileSystem.writeAsStringAsync(fileUrl, jsonData).then(async () => { if (await Sharing.isAvailableAsync()) { try { Sharing.shareAsync(fileUrl, { UTI: '.json', dialogTitle: 'Kotango | データバックアップ', mimeType: 'application/json', }); } catch (err) { console.log('!@# backup/err:', err); } } }); }, ... } - Step3-2jcommonMapper.backupIOS()
export const jcommonMapper = { ... backupIos: async (jsonData: string) => { const fileUrl = FileSystem.documentDirectory + `kotango.xxxxxxxx.json`; FileSystem.writeAsStringAsync(fileUrl, jsonData).then(async () => { try { const result = await Share.share({url: fileUrl}); if (result.action === Share.sharedAction) { console.log('成功しました!'); } else if (result.action === Share.dismissedAction) { // iOS only console.log('キャンセルされました!!'); } } catch (error: any) { console.log('!@# error:', error); } }); }, ... } - Step4バックアップファイル(最終版)を確認する
復元時に暗号化キーを使って復号化しますので、大事に保管してください。

暗号化済みのバックアップファイル
動作デモ
復元する
リリースする
※上記の詳細は以下のアプリに実装されています!



コメント