Appearance
Stockage persistant V2 et migration depuis V1
Les nouveaux développements utilisent la V2 du SDK app actuel (appli-2.0.js). Il ne s'agit pas d'une nouvelle version majeure du SDK ni de la version de ton appli. Les widgets n'ont pas ces services.
| Service | Méthodes | Forme racine |
|---|---|---|
kapp.dataStorageV2 | get(), set(data), delete() | objet ou liste ; lecture null si absent |
kapp.userDataStorageV2 | get(userId), set(userId, data), reset(labels), resetAll() | objet uniquement, par viewer |
kapp.logsStorageV2 | get(count = 100), add(data), clear() | chaque entrée est un objet ou une liste |
Les objets {}, {"0":"a","1":"b"}, les listes [], les imbrications et les valeurs JSON imbriquées (null, booléens, nombres finis, chaînes) sont préservés. Les valeurs simples à la racine sont refusées. Ne pas envoyer undefined, fonctions, dates, cycles ou nombres non finis. Les écritures remplacent le document entier. logsStorageV2.get() renvoie au plus 1 000 entrées, de la plus récente à la plus ancienne.
js
const state = (await kapp.dataStorageV2.get()) ?? { rounds: 0, byId: {}, roundsLog: [] };
state.rounds = Number(state.rounds ?? 0) + 1;
await kapp.dataStorageV2.set(state);
const data = await kapp.userDataStorageV2.get(user.id);
data.score = Number(data.score ?? 0) + 10;
await kapp.userDataStorageV2.set(user.id, data);
await kapp.logsStorageV2.add({ winner: user.id, inventory: {} });userDataStorageV2.get(userId) lit en serveur les données V2, sans cache User. Les lectures et écritures refusent les viewers qui bloquent l'appli. reset(labels: string[]) exige une liste non vide : les champs configurés reprennent leurs défauts typés et les champs libres, hors config, sont supprimés ; les autres champs sont conservés. resetAll() efface les viewers accessibles ; leurs défauts sont recréés à la prochaine lecture. Les blocages sont respectés et une config invalide fait échouer le reset avant modification. Les resets ne touchent pas les autres familles/channels/applis.
Copie initiale et versions de l'appli
- Le premier appel V2 (lecture ou écriture/reset) copie la famille V1 correspondante une seule fois pour cette installation. Les trois familles sont indépendantes. La copie et l'opération sont atomiques ; les appels concurrents ne dupliquent pas les historiques. Les dates d'historique sont conservées.
- La V1 reste intacte, avec son comportement historique. Les objets encore présents en BDD sont copiés fidèlement. Les viewers gardent leur contrat d'objet racine. Les objets déjà transformés en listes par la V1 ne sont pas réparables sans connaître le schéma de l'appli.
- La suppression/reset garde le marqueur de copie : aucune donnée V1 ne réapparaît. La désinstallation supprime les deux stockages et leurs marqueurs.
- Ouvrir une nouvelle version ne déclenche aucune copie : le nouveau brouillon succède à la version précédente sur le channel développeur. Son premier usage V2 migre ce channel s'il n'a pas déjà utilisé la V2 ; sinon il retrouve sa V2 existante.
- Publier ne copie aucune sauvegarde du développeur. Chaque streamer initialise sa propre installation au premier appel V2. Les versions suivantes de l'appli réutilisent ce stockage.
- Revenir au code V1 retrouve l'ancienne sauvegarde V1, sans les écritures V2. Revenir ensuite à V2 retrouve la V2 déjà initialisée. Prévoir cette différence avant un retour arrière.
Plugins, inspecteur et dépréciation
Avec le helper V3 3.0.0, KappappsHost.data() lit la V2 : côté streamer, {preferences, data, history} ; côté viewer, le même objet viewer qu'en V1 avec appli_data en V2. history est une liste de documents JSON. Les préférences et les autres données viewer gardent leur contrat. Le helper expose la nouvelle URL de l'hôte comme api.data ; il n'expose aucune méthode dataV2(). Si un hôte trop ancien ne fournit pas cette URL, data() refuse avec HOST_API_UNAVAILABLE : aucune bascule silencieuse vers V1.
Le choix V1/V2 de l'inspecteur DEV HUB cible la lecture et le reset. La consultation V2 seule ne copie rien (initialized: false). Son reset initialise puis efface la famille sélectionnée pour empêcher un réimport. Le reset administratif des viewers dans l'inspecteur vide tous les viewers du channel développeur, comme l'inspecteur V1.
Les services V1 ci-dessous, les alias appUsersData / appHistorics, User.getAppData() / setAppData() et les helpers V1/V2 sont dépréciés. Ces getters User et data() des helpers V1/V2 continuent à lire V1, même si l'appli écrit V2 : remplacer explicitement les getters par userDataStorageV2.get/set. Le SDK et les pages hôtes signalent ces usages par un avertissement en console.
Migrer l'appli et ses plugins ensemble
- Inventorier les lectures et écritures :
dataStorage,userDataStorage,logsStorage, aliasappUsersData/appHistorics,User.getAppData()/setAppData()et chaque plugin. Conserver une sauvegarde représentative de l'installation V1 avant les essais. - Dans un brouillon, passer les trois familles aux services
dataStorageV2,userDataStorageV2,logsStorageV2du SDK app actuel. Le suffixeV2reste nécessaire côté SDK pour cohabiter avec V1. Remplacer aussi les lecturesUser, même si les écritures ont déjà migré. - Charger tous les plugins concernés avec l'URL absolue
https://kappapps.app/assets/app-plugin/helper-v3.jset lire avecKappappsHost.data(). Traiter les rejets parerror.codeselon la référence plugins. Le helper V2 2.2.1 reste figé ; changer uniquement son URL sans migrer les écritures créerait des lectures et écritures dans deux stockages distincts. - Tester les sauvegardes existantes : objets vides, clés numériques, vraies listes, viewers déjà présents, historiques et première copie de chaque famille. Vérifier plugin streamer et viewers après écriture par l'appli, puis après redémarrage. Rejouer une éventuelle réparation applicative pour vérifier son idempotence ; les formes déjà perdues ne sont pas devinables automatiquement.
- Après la première copie V1 → V2, aucune synchronisation ultérieure : une ancienne version peut continuer à écrire V1 sans mettre V2 à jour. Coordonner les versions encore ouvertes et la bascule des deux côtés. Les anciennes API restent disponibles pour l'adoption progressive, sans migration forcée du catalogue.
- Tester le retour arrière avant adoption : revenir au helper V2 et aux écritures V1 retrouve la sauvegarde historique, sans les changements V2. Revenir ensuite à V3/V2 retrouve les données V2 déjà initialisées, sans importer les nouvelles écritures V1. Prévoir une réconciliation applicative si ces deux branches ont évolué.
Voir la réparation applicative idempotente et le changelog.
Référence V1 : uniquement pour lire une appli existante
Ne pas utiliser ces API dans une nouvelle appli ; elles servent à comprendre le code à migrer. Elles sont propres aux applis et lèvent AppMethodError dans un widget.
| V1 dépréciée | Forme | Équivalent V2 |
|---|---|---|
kapp.dataStorage.get() / set(data) / delete() | Objet global, set remplace tout, null si jamais écrit | kapp.dataStorageV2 |
kapp.userDataStorage.set(user_id, data), reset(labels), resetAll() ; user.getAppData() / setAppData(data) | Objet par viewer ; reset exige une liste non vide, resetAll() efface tout ; un User déjà chargé garde ses anciennes données en mémoire | kapp.userDataStorageV2 |
kapp.logsStorage.get(count = 100) / add(data) / clear() | Historique en ajout seulement | kapp.logsStorageV2 |
Les règles de reset V1 sont celles décrites plus haut pour V2 (défauts de player_stats.config.json, champs libres supprimés, viewers bloqués exclus, configuration invalide refusée avant modification).