Skip to content
English

Le projet et ses formats ​

Le projet de l'élève est le dossier /workspace (fichiers et dépôt .git), dans l'IndexedDB du navigateur. Cette page décrit l'objet qui le représente, son cycle de vie et les trois formats par lesquels il entre et sort de CapyCode : le projet de départ, le lien de partage et l'archive ZIP.

L'objet Workspace ​

Workspace (src/services/workspace.ts) réunit le système de fichiers (fs, un VirtualFileSystem) et le dépôt (git, un GitService) d'un projet :

MembreRôle
rootracine (/workspace)
path(rel), relative(path)conversions entre chemin relatif (celui de Git, des liens, des ZIP) et absolu
setAuthor({ name, email })identité des commits (aujourd'hui une identité par défaut ; demain celle de l'utilisateur Capytale)
batch(task)lot de fichiers et de Git : une seule notification de chaque à la fin

L'application a un projet, workspace. Les services de projet (src/services/project/) reçoivent le Workspace sur lequel agir au lieu d'importer les singletons : ils marchent sur un projet de test, et marcheront sur un projet stocké ailleurs (par Capytale) le jour venu.

Le cycle de vie ​

Ensuite, à tout moment, depuis le menu Fichier ou la palette (useProject) :

  • Nouveau projet : purge du workspace après confirmation ; le projet reste vide (sans dépôt Git).
  • Exporter : exportArchive → téléchargement de capycode-project.zip.
  • Importer une archive (menu, ou ZIP déposé sur la fenêtre) : importArchive, après confirmation.
  • Déposer des fichiers (autres qu'un ZIP) sur la fenêtre : ils sont ajoutés au projet.
  • Partager : ShareModal construit un lien ; ouvrir un lien dans un onglet déjà ouvert le charge aussi (hashchange).

useProject (composable) porte les confirmations, messages et fichier à ouvrir ; les services de src/services/project/ font le travail sur le Workspace. Les stores suivent seuls, par les notifications.

Purge complète

Importer un ZIP ou un instantané purge entièrement le workspace avant d'écrire (purgeWorkspace, qui notifie un reset) : il ne reste rien de l'ancien projet, ni fichier, ni branche. L'instantané mémoire de Pyodide, lui, est dans une autre base IndexedDB et n'est pas touché.

Le projet de départ ​

src/services/project/defaults.ts. À la toute première visite (pas de préférence capycode_seeded, pas de dépôt), CapyCode crée un dépôt sur main, un main.py (texte dans la langue de l'interface) et un premier commit.

Ce projet est reconnu ensuite (hasCustomContent) : tant qu'il est intact, ouvrir un lien de partage le remplace sans demander de confirmation. La préférence capycode_seeded évite de le recréer quand l'élève a volontairement vidé son projet.

L'instantané et le lien de partage ​

src/services/project/snapshot.ts et shareLink.ts.

  • Construction (ShareModal) : collectFiles (fichiers texte, hors fichiers cachés ; il renvoie à part les fichiers binaires écartés), la liste des extensions activées choisies par l'utilisateur, et au choix collectCommits (les n derniers commits de la branche active ou de toutes les branches, le premier avec son arborescence, les suivants en différences) et collectBranches.
  • Lien : encodeShareLink compresse le JSON avec fflate (DEFLATE au niveau maximal, encodé en Base64URL) dans le fragment #capycode=…, jamais envoyé au serveur. Le format ne transporte que du texte, et un lien doit rester court : il est fait pour du code. Un fichier qui n'est pas de l'UTF-8 valide (decodeUtf8, src/utils/text.ts, décodage strict) est donc écarté, de l'état courant comme des commits (getCommitTreeSnapshot), plutôt que transmis corrompu ; ShareModal le signale et renvoie vers l'export ZIP.
  • Ouverture : decodeShareLink décompresse et valide la structure (isProjectSnapshot) ; un lien illisible, tronqué ou d'une version inconnue est refusé avec un message, jamais interprété à moitié. Les chemins qui sortiraient du projet (..) sont ignorés. Les extensions spécifiées dans l'instantané sont automatiquement activées.
  • Restauration : restoreSnapshot purge le projet, rejoue les commits (mêmes messages, auteurs et dates ; les identifiants de commit, eux, changent), recrée les branches, puis écrit l'état courant des fichiers (modifications non commitées comprises), le tout dans un seul workspace.batch.

Format versionné

SNAPSHOT_VERSION vaut 2. Toute évolution du format passe par une nouvelle version. Voir la recette.

L'archive ZIP ​

src/services/project/archive.ts. C'est la sauvegarde fidèle : tous les fichiers, .git compris, lus et écrits en binaire (Uint8Array). Les objets Git sont compressés : les décoder en texte les corromprait.

À l'import :

  • l'archive est lue entièrement avant de toucher au projet : une archive invalide laisse le projet intact ;
  • un dossier unique qui englobe tout (projet/…, quand on zippe un dossier) est retiré ;
  • les fichiers ajoutés par les systèmes d'exploitation (__MACOSX/, .DS_Store, Thumbs.db) sont ignorés, et les chemins qui sortiraient du projet neutralisés ;
  • le workspace est purgé puis rempli dans un seul vfs.batch.

Où est stocké quoi ​

DonnéeOùEffacée par
Fichiers et dépôt du projetIndexedDB capycode-fs (LightningFS), sous /workspaceNouveau projet, import, lien de partage
Préférences (thème, langue, tailles, capycode_seeded…)localStorage, par src/utils/storage.tsEffacement des données du site
Instantané mémoire de PyodideIndexedDB basthon-python3 (géré par Basthon)Basthon, quand Pyodide change de version
Interface, noyaux, RuffCaches du service workerNouvelle version déployée

Rien n'est envoyé à un serveur : le projet n'existe que dans ce navigateur, d'où l'importance de l'export ZIP (et, à terme, d'une sauvegarde par Capytale).