sokko-g/docs/STORAGE_SCHEMA.md
Shinuwa e306bfc5d6
All checks were successful
Deploy Sokko G / deploy (push) Successful in 7s
add task planner & alert improvments
2026-07-27 22:44:08 +02:00

9.2 KiB

Storage Schema

Ce document décrit les données persistées dans IndexedDB pour les toolboxes. Il doit être mis à jour à chaque ajout ou modification d'outil.

IndexedDB

Base : sokkog

Object stores :

  • kv : données globales simples.
  • modules : données des outils, séparées par toolbox et par module.

Clés principales dans kv :

{
  "toolboxes": [],
  "links": {},
  "setting:toolboxOrder": [],
  "setting:storageBudgetBytes": 536870912,
  "setting:toastPosition": "right"
}

Entrée type dans modules :

{
  "key": "tbx1:mod1",
  "data": {}
}

Toolbox

Les toolboxes sont stockées dans kv/toolboxes.

{
  "id": "tbx1",
  "name": "Monster Hunter Wilds",
  "gameId": "mhwilds",
  "icon": "/static/img/toolbox-icons/toolbox.png",
  "modules": [
    {
      "id": "mod1",
      "type": "checklist",
      "title": "Armures"
    }
  ],
  "layout": "two",
  "updatedAt": "2026-07-25T12:00:00.000Z"
}

Notes :

  • gameId est vide pour une toolbox libre.
  • icon est utilisé uniquement pour les toolboxes libres.
  • layout vaut généralement one ou two.
  • Les données lourdes des outils ne sont pas stockées dans la toolbox, mais dans modules.

Liens Jeu / Toolbox

Les associations entre pages jeux et toolboxes sont stockées dans kv/links.

{
  "mhwilds": "tbx1",
  "diablo4": "tbx2"
}

Outil Bloc Notes

Type : notepad

{
  "text": "Notes rapides..."
}

Stockage compact :

  • si text est vide, l'entrée de module peut être supprimée.

Outil Checklist

Type : checklist

Format simple, sans catégorie :

{
  "items": [
    {
      "id": "item1",
      "label": "Potion",
      "qtyTarget": 10,
      "qtyCurrent": 3
    }
  ]
}

Format avec catégories :

{
  "hideCompletedSections": true,
  "hideCompletedSectionsFully": false,
  "sections": [
    {
      "id": "section1",
      "title": "Rey Dau alpha",
      "hideWhenComplete": false,
      "collapsed": false,
      "items": [
        {
          "id": "item1",
          "label": "Casque",
          "qtyTarget": 1,
          "qtyCurrent": 0
        }
      ]
    }
  ]
}

Stockage compact :

  • qtyTarget est omis si la valeur vaut 1.
  • qtyCurrent est omis si la valeur vaut 0.
  • hideCompletedSections est omis si false.
  • hideCompletedSectionsFully est omis si false.
  • title est omis si vide.
  • hideWhenComplete est omis si non défini.
  • collapsed est omis si false.

Outil Images

Type : images

{
  "images": [
    {
      "id": "image1",
      "label": "Map zone nord",
      "dataUrl": "data:image/webp;base64,..."
    }
  ]
}

Stockage compact :

  • label est facultatif.
  • label est omis si vide.
  • createdAt n'est pas stocké.
  • Le nom de fichier original n'est pas stocké.

Outil Annotation d'images

Type : imageAnnotation

{
  "image": "data:image/webp;base64,...",
  "markers": [
    {
      "id": "marker1",
      "x": 42.5,
      "y": 68,
      "label": "Entrée"
    }
  ]
}

Stockage compact :

  • un seul visuel par outil.
  • x et y sont des pourcentages entre 0 et 100.
  • label est facultatif.
  • label est omis si vide.

Outil Timer

Type : timer

Structure initiale :

{
  "activeTab": "stopwatch",
  "scrollResults": true,
  "sortResults": true,
  "stopwatch": {
    "elapsedMs": 12000,
    "startedAt": 1760000000000,
    "laps": [
      {
        "id": "timer1",
        "label": "Phase 1",
        "elapsedMs": 9000
      }
    ]
  },
  "countdowns": [
    {
      "id": "timer2",
      "label": "Boss",
      "type": "daily_time",
      "alertMode": "visible",
      "time": "12:03:00",
      "targetAt": 1760000000000
    },
    {
      "id": "timer3",
      "label": "Event",
      "type": "time_pattern",
      "pattern": "X:45:00"
    },
    {
      "id": "timer4",
      "label": "Event",
      "type": "interval",
      "intervalMs": 1800000,
      "anchorAt": 1760000000000
    }
  ]
}

Types de compte à rebours :

  • duration : durée ponctuelle, avec durationMs et targetAt.
  • daily_time : occurrence ponctuelle à une heure précise, avec time au format HH:MM:SS et targetAt.
  • time_pattern : prochaine occurrence automatique correspondant à un pattern HH:MM:SS, où chaque segment peut valoir X.
  • interval : prochaine occurrence automatique toutes les X millisecondes, avec intervalMs et anchorAt.

Pour time_pattern, un segment X situé après un segment plus large fixé cible le premier instant de l'occurrence. Exemple : X:24:X cible hh:24:00 et se répète toutes les heures.

Stockage compact :

  • activeTab est omis si la valeur vaut stopwatch.
  • scrollResults est omis si false.
  • sortResults est omis si false.
  • stopwatch est omis tant que le chrono est à zéro et qu'aucune étape n'est enregistrée.
  • elapsedMs est omis si 0.
  • startedAt est omis si le chrono n'est pas lancé.
  • laps est omis tant qu'aucune étape n'est enregistrée.
  • countdowns est omis tant qu'aucun compte à rebours n'est configuré.
  • countdowns[].alertMode vaut off, visible ou site, et est omis si off.
  • L'activation d'une alerte est bloquée dans l'interface si la fréquence configurée est inférieure à 5 minutes pour les comptes à rebours récurrents (time_pattern et interval). Le blocage ne dépend pas du temps restant avant la prochaine échéance.

Outil Task Planner

Type : taskPlanner

{
  "sortMode": "manual",
  "weeklyResetDay": 1,
  "resetTime": "00:00",
  "lastResetAt": 1760000000000,
  "tasks": [
    {
      "id": "task1",
      "title": "Quête 1",
      "description": "Préparer la route.",
      "type": "daily",
      "checked": true,
      "checkedAt": 1760000000000
    },
    {
      "id": "task2",
      "title": "Quête 2",
      "type": "weekly",
      "weeklyResetDay": 3
    }
  ],
  "relations": [
    {
      "id": "relation1",
      "fromTaskId": "task1",
      "toTaskId": "task2"
    },
    {
      "id": "relation2",
      "fromTaskId": "task2",
      "toTaskId": "task1",
      "dependency": true
    }
  ]
}

Notes :

  • type vaut unique, daily ou weekly.
  • sortMode vaut manual ou type. Le tri par type affiche quotidiennes, hebdo, puis uniques.
  • weeklyResetDay suit les jours JavaScript : 0 dimanche, 1 lundi, ..., 6 samedi.
  • resetTime est global à l'outil et vaut HH:MM.
  • weeklyResetDay sur une tâche hebdo surcharge le jour global.
  • relations stocke les parents directionnels. fromTaskId désigne la tâche enfant, toTaskId son parent.
  • une tâche ne conserve qu'un seul parent.
  • dependency: true marque aussi ce parent comme pré requis.
  • Les pré requis sont non bloquants : ils affichent un avertissement si le parent requis n'est pas effectué.

Stockage compact :

  • sortMode est omis si la valeur vaut manual.
  • weeklyResetDay global est omis si la valeur vaut 1.
  • resetTime est omis si la valeur vaut 00:00.
  • lastResetAt est omis si la valeur vaut 0.
  • description est omis si vide.
  • checked et checkedAt sont omis si la tâche n'est pas effectuée.
  • weeklyResetDay unitaire est omis si non défini.
  • relations est omis si vide.
  • relations[].dependency est omis si false.

Outil Liens

Type : links

{
  "links": [
    {
      "id": "link1",
      "title": "Build rogue",
      "url": "https://example.com/build"
    }
  ]
}

Stockage compact :

  • title est facultatif.
  • title est omis si vide.
  • url est obligatoire.

Outil Compteurs

Type : counters

{
  "counters": [
    {
      "id": "counter1",
      "label": "Victoire",
      "value": 12
    },
    {
      "id": "counter2",
      "label": "Défaite",
      "value": -2
    }
  ]
}

Notes :

  • value est numérique.
  • Les valeurs négatives sont acceptées.
  • Les compteurs sans libellé ne sont pas conservés.

Outil Calculateur

Type : calculator

{
  "scrollResults": true,
  "entries": [
    {
      "id": "calc1",
      "label": "Lingots de fer",
      "value": 100
    },
    {
      "id": "calc2",
      "parentId": "calc1",
      "label": "Minerais de fer",
      "value": 500
    }
  ]
}

Stockage compact :

  • scrollResults est omis si false.
  • parentId est omis si vide.
  • label peut être vide.
  • value est numérique.
  • Si un parentId ne pointe vers aucune entrée existante, il est réinitialisé à vide.

Export

L'export d'une toolbox remappe les identifiants pour produire des IDs courts et indépendants.

Exemple :

{
  "toolbox": {
    "id": "t1",
    "name": "MHW",
    "modules": [
      {
        "id": "m1",
        "type": "checklist",
        "title": "Armures"
      }
    ],
    "updatedAt": "2026-07-25T12:00:00.000Z"
  },
  "modules": {
    "m1": {
      "items": [
        {
          "id": "i1",
          "label": "Casque"
        }
      ]
    }
  }
}

A maintenir à chaque update

Quand un outil change de structure :

  • mettre à jour ce document ;
  • mettre à jour les normalisations dans website/src/features/toolboxes/storage/toolboxStorage.js ;
  • mettre à jour les textes dans website/public/data/site.json si nécessaire ;
  • mettre à jour la validation dans tests/helpers/data-validation.mjs si nécessaire ;
  • vérifier import/export ;
  • lancer npm run check.