Skip to content

9️⃣.2️⃣ Création de la base SQLite locale et de la table cards

Nous allons maintenant créer la base de données locale SQLite et définir la table cards qui stockera les données métier hors-ligne.

L'objectif est simple :

  • que l'application puisse lire et écrire des cartes sans réseau,
  • avec une structure proche de celle utilisée dans Supabase.

9️⃣.2️⃣.1️⃣ Schéma de la table cards

La table locale cards doit contenir :

  • les données métier,
  • les métadonnées nécessaires à la synchronisation.

Colonnes retenues

ColonneTypeRôle
idTEXTIdentifiant unique (UUID généré côté app)
nameTEXTNom de la carte
rarityTEXTRareté (ex: common, rare, epic…)
elixir_costINTEGERCoût en élixir
roleTEXTRôle / catégorie
hitpointsINTEGERPoints de vie
damageINTEGERDégâts
arenaINTEGERArène
is_favoriteINTEGER1 = favorite, 0 = non
created_atTEXTCréation (ISO string)
updated_atTEXTDernière modification (ISO string)
syncedINTEGER1 = synchronisé, 0 = modification locale

👉 Le champ synced nous aidera à savoir quelles cartes doivent être envoyées au backend.

9️⃣.2️⃣.2️⃣ Création d'un service SQLite centralisé

Pour éviter de disperser le code SQLite dans les stores ou les composants, nous allons créer un service dédié.

Créez le fichier src/services/sqliteService.ts.

9️⃣.2️⃣.3️⃣ Initialisation de la base SQLite

src/services/sqliteService.ts
ts
import {
  CapacitorSQLite,
  SQLiteConnection,
  SQLiteDBConnection
} from '@capacitor-community/sqlite'

/**
 * Connexion SQLite globale
 */
const sqlite = new SQLiteConnection(CapacitorSQLite)

let db: SQLiteDBConnection | null = null

/**
 * Initialise la base SQLite locale
 * - ouvre la base
 * - crée la table cards si nécessaire
 */
export async function initDB() {
    
  // Ouverture (ou création) de la base locale
  db = await sqlite.createConnection(
    'cards-db', // nom de la base
    false,
    'no-encryption',
    1,
    false
  )

    await db.open()
  
    // Création de la table cards
    const createTableSQL = `
        CREATE TABLE IF NOT EXISTS cards (
                                             id TEXT PRIMARY KEY NOT NULL,
                                             name TEXT NOT NULL,
                                             rarity TEXT NOT NULL,
                                             elixir_cost INTEGER NOT NULL,
                                             role TEXT NOT NULL,
                                             hitpoints INTEGER NOT NULL,
                                             damage INTEGER NOT NULL,
                                             arena INTEGER NOT NULL,
                                             is_favorite INTEGER NOT NULL,
                                             created_at TEXT NOT NULL,
                                             updated_at TEXT NOT NULL,
                                             synced INTEGER NOT NULL
        );
    `
    await db.execute(createTableSQL)
}

/**
 * Accès sécurisé à la base
 */
export function getDB(): SQLiteDBConnection {
  if (!db) {
    throw new Error('SQLite DB not initialized')
  }
  return db
}
  • SQLite est ouvert une seule fois,
  • La table est créée si elle n'existe pas.
  • le service expose uniquement ce qui est nécessaire pour accéder à la base.

9️⃣.2️⃣.4️⃣ Initialiser SQLite au lancement de l'app

SQLite doit être prêt avant toute lecture ou écriture.

👉 Comme pour l'auth et le réseau, on initialise une seule fois dans src/main.ts.

De plus, nous allons encapsuler l'initialisation avec un bootstrap asynchrone. Sans ça, on a uen erreur au build car await n'est pas autorisé au top-level.

src/main.ts
ts
import {createApp} from 'vue'
import App from './App.vue'
import router from './router';

import {IonicVue} from '@ionic/vue';
import {createPinia} from 'pinia';
import {useAuthStore} from '@/stores/authStore';
import {useNetworkStore} from '@/stores/networkStore';
import { defineCustomElements as jeepSqlite } from 'jeep-sqlite/loader'
import { initDB } from '@/services/sqliteService'

// ...

async function bootstrap() {
// 🔹 Création de l’app
    const app = createApp(App)
        .use(IonicVue)

// 🔹 IMPORTANT : on garde une référence à Pinia
    const pinia = createPinia()
    app.use(pinia)

// 🔹 Initialisation réseau (1 seule fois)
    const networkStore = useNetworkStore(pinia)
    networkStore.init()

// 🔹 Router inchangé
    app.use(router)

// 🔹 INITIALISATION AUTH (1 seule fois)
    const authStore = useAuthStore(pinia)
    authStore.init()

// Initialisation SQLite
    await initDB() 

// 🔹 Mount final inchangé
    router.isReady().then(() => {
        app.mount('#app')
    })
}

bootstrap()

⚠️ Attention !

L'initialisation de SQLite doit être fait avant toute synchronisation ou lecture locale.

🔜 La suite...

Nous avons maintenant une base SQLite locale prête à l'emploi, une table cards créée, et l'application peut stocker des cartes hors-ligne.

Nous allons ensuite :

  • lire les cartes depuis SQLite,
  • écrire / modifier / supprimer localement,
  • sans encore parler de Supabase.