ScaleRocket/Mobile

Stockage

Stockage sécurisé des tokens avec SecureStore, préférences avec AsyncStorage et uploads de fichiers avec Supabase ou Convex.

Stockage

ScaleRocket Mobile utilise différentes solutions de stockage selon le type de données.

SecureStore (Tokens)

Les tokens d'authentification sont stockés avec expo-secure-store, qui fournit un stockage chiffré sur l'appareil. C'est plus sécurisé qu'AsyncStorage pour les données sensibles.

// lib/supabase.ts
import * as SecureStore from "expo-secure-store";

const SecureStoreAdapter = {
  getItem: (key: string) => SecureStore.getItemAsync(key),
  setItem: (key: string, value: string) => SecureStore.setItemAsync(key, value),
  removeItem: (key: string) => SecureStore.deleteItemAsync(key),
};

Le client Supabase utilise cet adaptateur automatiquement :

createClient(supabaseUrl, supabaseAnonKey, {
  auth: {
    storage: SecureStoreAdapter,
    autoRefreshToken: true,
    persistSession: true,
    detectSessionInUrl: false,
  },
});

Note : SecureStore nécessite un build de développement. Il ne fonctionne pas dans Expo Go.

Limites de SecureStore

  • iOS : Données stockées dans le Keychain (chiffrées, sauvegardées sur iCloud si activé)
  • Android : Données stockées dans SharedPreferences avec chiffrement Android Keystore
  • Limite de taille : 2KB par valeur. Pour des données plus volumineuses, utilisez AsyncStorage ou le stockage de fichiers

AsyncStorage (Préférences)

Pour les données non sensibles comme les préférences utilisateur, les paramètres de thème ou l'état d'onboarding, utilisez @react-native-async-storage/async-storage :

npx expo install @react-native-async-storage/async-storage
import AsyncStorage from "@react-native-async-storage/async-storage";

// Sauvegarder une préférence
await AsyncStorage.setItem("theme", "dark");
await AsyncStorage.setItem("onboarding_complete", "true");

// Lire une préférence
const theme = await AsyncStorage.getItem("theme");

// Supprimer une préférence
await AsyncStorage.removeItem("theme");

Upload de fichiers

Utilisez Supabase Storage pour uploader des fichiers depuis l'appareil :

import * as ImagePicker from "expo-image-picker";
import { supabase } from "../lib/supabase";

async function uploadAvatar() {
  const result = await ImagePicker.launchImageLibraryAsync({
    mediaTypes: ImagePicker.MediaTypeOptions.Images,
    quality: 0.8,
  });

  if (result.canceled) return;

  const file = result.assets[0];
  const fileName = `${user.id}/avatar.jpg`;

  const formData = new FormData();
  formData.append("file", {
    uri: file.uri,
    name: "avatar.jpg",
    type: "image/jpeg",
  } as any);

  const { error } = await supabase.storage
    .from("avatars")
    .upload(fileName, formData, { upsert: true });

  if (error) throw error;
}

Obtenez une URL publique pour les fichiers uploadés :

const { data } = supabase.storage
  .from("avatars")
  .getPublicUrl(`${user.id}/avatar.jpg`);

const avatarUrl = data.publicUrl;

Utilisez Convex File Storage pour uploader des fichiers :

import * as ImagePicker from "expo-image-picker";
import { useMutation } from "convex/react";
import { api } from "../convex/_generated/api";

async function uploadAvatar() {
  const result = await ImagePicker.launchImageLibraryAsync({
    mediaTypes: ImagePicker.MediaTypeOptions.Images,
    quality: 0.8,
  });

  if (result.canceled) return;

  const file = result.assets[0];

  // Obtenir l'URL d'upload depuis Convex
  const uploadUrl = await generateUploadUrl();

  // Uploader le fichier
  const response = await fetch(file.uri);
  const blob = await response.blob();
  const uploadResult = await fetch(uploadUrl, {
    method: "POST",
    body: blob,
    headers: { "Content-Type": "image/jpeg" },
  });

  const { storageId } = await uploadResult.json();

  // Sauvegarder le storage ID dans le profil utilisateur
  await saveAvatar({ storageId });
}

Quand utiliser quoi

Type de donnéesSolutionExemple
Tokens d'authSecureStoreTokens de session, clés API
Préférences utilisateurAsyncStorageThème, langue, état d'onboarding
FichiersSupabase Storage / Convex FilesAvatars, documents, images
État de l'appÉtat React / contexteDonnées de l'écran actuel, champs de formulaire

On this page