sokko-g/docs/STORAGE_SCHEMA.md
Shinuwa 2e6d8a2c0c
All checks were successful
Deploy Sokko G / deploy (push) Successful in 7s
keepsafe rework & alert ajustments
2026-07-26 17:48:14 +02:00

384 lines
7.4 KiB
Markdown

# 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` :
```json
{
"toolboxes": [],
"links": {},
"setting:toolboxOrder": [],
"setting:storageBudgetBytes": 536870912,
"setting:toastPosition": "right"
}
```
Entrée type dans `modules` :
```json
{
"key": "tbx1:mod1",
"data": {}
}
```
## Toolbox
Les toolboxes sont stockées dans `kv/toolboxes`.
```json
{
"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`.
```json
{
"mhwilds": "tbx1",
"diablo4": "tbx2"
}
```
## Outil Bloc Notes
Type : `notepad`
```json
{
"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 :
```json
{
"items": [
{
"id": "item1",
"label": "Potion",
"qtyTarget": 10,
"qtyCurrent": 3
}
]
}
```
Format avec catégories :
```json
{
"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`
```json
{
"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`
```json
{
"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 :
```json
{
"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 Liens
Type : `links`
```json
{
"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`
```json
{
"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`
```json
{
"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 :
```json
{
"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`.