MemoEasy
MemoEasy
Documentation technique

Format du fichier deck .zip

Ce document décrit la structure exacte du fichier .zip utilisé par MemoEasy pour importer et exporter des decks. Il s'adresse aux développeurs ou créateurs de contenu qui souhaitent générer des decks en dehors de l'application.

Contenu de l'archive

L'archive est un fichier ZIP standard contenant exactement deux éléments :

deck.zip
  ├── manifest.json  ← obligatoire
  └── images/  ← optionnel, absent si aucune image
        ├── photo-01.jpg
        └── schema.png
Nom du fichierLe fichier peut s'appeler comme tu veux, mais son extension doit être .zip. Le contenu du fichier est vérifié par son contenu, pas son nom.

manifest.json

Le fichier manifest.json est le cœur du deck. Il décrit le profil, les sujets, les fiches et les images.

manifest.json — exemple complet
{
  "format": "memoeasy.deck-bundle",
  "schemaVersion": 1,
  "exportedAt": "2025-03-15T10:30:00.000Z",
  "appVersion": "1.0.0",

  "deck": {
    "sourceProfileId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "Vocabulaire Japonais N5"
  },

  "tags": [
    {
      "id": "tag-uuid-1",
      "name": "Hiragana",
      "color": "#59f3d2",
      "createdAt": "2025-01-10T08:00:00.000Z"
    },
    {
      "id": "tag-uuid-2",
      "name": "Nombres",
      "color": "#ff7e72",
      "createdAt": "2025-01-10T08:01:00.000Z"
    }
  ],

  "cards": [
    {
      "id": "card-uuid-1",
      "question": "あ",
      "reponse": "a (première lettre hiragana)",
      "niveau": 0,
      "dateDepart": "2025-03-01T00:00:00.000Z",
      "prochaineRevision": "2025-03-01T00:00:00.000Z",
      "createdAt": "2025-03-01T09:00:00.000Z",
      "tagIds": ["tag-uuid-1"],
      "imageFile": null
    },
    {
      "id": "card-uuid-2",
      "question": "一 (いち)",
      "reponse": "1 — un",
      "niveau": 0,
      "dateDepart": "2025-03-01T00:00:00.000Z",
      "prochaineRevision": "2025-03-01T00:00:00.000Z",
      "createdAt": "2025-03-01T09:05:00.000Z",
      "tagIds": ["tag-uuid-1", "tag-uuid-2"],
      "imageFile": "photo-01.jpg"
    }
  ],

  "images": [
    {
      "file": "photo-01.jpg",
      "size": 48320
    }
  ]
}

Description des champs

Racine

formatREQ
string
Doit valoir exactement "memoeasy.deck-bundle". Identifiant du format, vérifié à l'import.
schemaVersionREQ
number
Version du schéma. Actuellement 1. Un schéma inconnu bloque l'import.
exportedAtREQ
string — ISO 8601
Date et heure de création du deck. Format : "YYYY-MM-DDTHH:mm:ss.sssZ".
appVersionREQ
string
Version de l'application source. Valeur libre, par exemple "1.0.0". Utilisé à des fins d'information uniquement.

deck

deck.sourceProfileIdREQ
string — UUID v4
Identifiant du profil d'origine. Doit être un UUID v4 valide. Utilisé pour traçabilité uniquement — l'import crée un nouveau profil avec un ID distinct.
deck.nameREQ
string
Nom du deck. Utilisé comme nom du profil lors de l'import si aucun profil cible n'est spécifié. Chaîne non vide.

tags[ ]

idREQ
string — UUID v4
Identifiant unique du sujet dans ce deck. Référencé par les fiches dans tagIds. Ne doit pas être dupliqué.
nameREQ
string
Nom affiché du sujet. Chaîne non vide.
colorREQ
string — couleur CSS
Couleur du sujet. Valeur CSS valide, par ex. "#59f3d2" ou "rgb(89, 243, 210)".
createdAtREQ
string — ISO 8601
Date de création du sujet.

cards[ ]

idREQ
string — UUID v4
Identifiant unique de la fiche dans ce deck.
questionREQ
string
Texte du recto (question). Peut contenir des sauts de ligne.
reponseREQ
string
Texte du verso (réponse). Peut contenir des sauts de ligne.
niveauREQ
number — entier ≥ 0
Niveau de maîtrise de la fiche. Mettre 0 pour les nouvelles fiches (non encore révisées).
dateDepartREQ
string — ISO 8601
Date de départ du cycle de révision. Mettre la date de création du deck pour les nouvelles fiches.
prochaineRevisionREQ
string — ISO 8601
Date à laquelle la fiche doit être proposée à la révision. Mettre la date de création du deck pour que la fiche soit immédiatement disponible.
createdAtREQ
string — ISO 8601
Date de création de la fiche.
tagIdsREQ
string[ ] — UUID v4
Liste des IDs de sujets associés à cette fiche. Au moins un sujet est obligatoire. Tous les IDs doivent référencer des sujets déclarés dans tags. Pas de doublons.
imageFileREQ
string | null
Nom du fichier image associé (ex. "photo-01.jpg"), ou null si aucune image. Le fichier doit être présent dans le dossier images/ de l'archive et déclaré dans images[].

images[ ]

fileREQ
string
Nom du fichier image, correspondant exactement au nom dans images/ et dans cards[].imageFile.
sizeREQ
number — octets
Taille non compressée du fichier image en octets.

Limites acceptées par l'import

L'application vérifie ces limites à l'import et rejette le fichier si elles sont dépassées.

Taille du .zip (compressé)
40 Mo maximum
Total non compressé
200 Mo maximum
Nombre d'entrées dans l'archive
2 000 entrées maximum
Taille du manifest.json
2 Mo maximum
Taille d'une image (non compressée)
15 Mo maximum
Ratio de compression
100:1 maximum (protection zip-bomb)
Formats d'imageLes formats recommandés sont JPEG et PNG. Les noms de fichiers ne doivent contenir que des caractères alphanumériques, tirets et underscores, avec une extension reconnue.

Codes d'erreur de l'import

Si l'import échoue, l'application retourne l'un de ces codes.

BUNDLE_READ_FAILED
Impossible de lire le fichier source. URI vide, schéma réseau non autorisé, ou accès refusé.
BUNDLE_TOO_LARGE
Le fichier .zip dépasse la limite de 40 Mo compressés.
ZIP_CORRUPTED
L'archive n'est pas un ZIP valide, ou contient des chemins non sûrs (traversal de répertoire).
ARCHIVE_LIMIT_EXCEEDED
L'archive dépasse le nombre d'entrées maximum, la taille non compressée totale, ou le ratio de compression.
ENTRY_TOO_LARGE
Une entrée individuelle (manifest ou image) dépasse sa limite de taille.
MANIFEST_MISSING
Le fichier manifest.json est absent de l'archive.
MANIFEST_INVALID
Le manifest est présent mais invalide : JSON malformé, champ manquant, format incorrect, tagId inconnu, ou tagIds dupliqués.
UNSUPPORTED_SCHEMA_VERSION
La valeur de schemaVersion n'est pas supportée par cette version de l'app.
PROFILE_NOT_FOUND
Un profil cible a été spécifié pour la fusion mais n'existe pas dans l'application.
IMPORT_WRITE_FAILED
L'écriture en base de données a échoué. Les images déjà copiées sont supprimées automatiquement.