「暗号化+バックアップ版」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バックアップファイル(最終版)を確認する
復元時に暗号化キーを使って復号化しますので、大事に保管してください。
動作デモ
復元する
リリースする
※上記の詳細は以下のアプリに実装されています!
コメント