- Accueil
- Documentation
- Extensions
- Gestion des plugins et mécanique d'installation
Gestion des plugins et mécanique d'installation
Ce document décrit comment les opérations xcsh plugin modifient l’état des plugins sur le disque et comment les plugins installés deviennent des capacités d’exécution (les outils aujourd’hui, la résolution de chemin pour les hooks et commandes est disponible).
Périmètre et architecture
Section intitulée « Périmètre et architecture »Deux implémentations de gestion des plugins coexistent dans la base de code :
- Chemin actif utilisé par les commandes CLI :
PluginManager(src/extensibility/plugins/manager.ts) - Module auxiliaire historique : fonctions d’installation (
src/extensibility/plugins/installer.ts)
L’exécution des commandes xcsh plugin ... passe par PluginManager.
installer.ts documente toujours des vérifications de sécurité importantes et le comportement du système de fichiers, mais ce n’est pas le chemin utilisé par src/commands/plugin.ts + src/cli/plugin-cli.ts.
Cycle de vie : de l’invocation CLI à la disponibilité à l’exécution
Section intitulée « Cycle de vie : de l’invocation CLI à la disponibilité à l’exécution »xcsh plugin <action> ... -> src/commands/plugin.ts -> runPluginCommand(...) in src/cli/plugin-cli.ts -> PluginManager method (install/list/uninstall/link/...) -> mutate ~/.xcsh/plugins/{package.json,node_modules,xcsh-plugins.lock.json} -> runtime discovery: discoverAndLoadCustomTools(...) -> getAllPluginToolPaths(cwd) -> custom tool loader imports tool modulesPoints d’entrée des commandes
Section intitulée « Points d’entrée des commandes »src/commands/plugin.tsdéfinit la commande, les indicateurs et les transmet àrunPluginCommand.src/cli/plugin-cli.tsfait correspondre les sous-commandes aux méthodes dePluginManager:install,uninstall,list,link,doctor,features,config,enable,disable
- Il n’existe pas d’action
updateexplicite ; la mise à jour s’effectue en réexécutantinstallavec une nouvelle spécification de paquet ou de version.
Modèle sur disque
Section intitulée « Modèle sur disque »L’état global des plugins réside dans ~/.xcsh/plugins :
package.json— manifeste des dépendances utilisé parbun install/bun uninstallnode_modules/— paquets de plugins installés ou liens symboliquesxcsh-plugins.lock.json— état d’exécution :- activation/désactivation par plugin
- ensemble de fonctionnalités sélectionné par plugin
- paramètres de plugin persistés
Les remplacements locaux au projet résident dans :
<cwd>/.xcsh/plugin-overrides.json
Les remplacements sont en lecture seule du point de vue du gestionnaire/chargeur (aucun chemin d’écriture ici) et peuvent désactiver des plugins ou remplacer les fonctionnalités et paramètres pour ce projet.
Analyse des spécifications de plugins et interprétation des métadonnées
Section intitulée « Analyse des spécifications de plugins et interprétation des métadonnées »Grammaire des spécifications d’installation
Section intitulée « Grammaire des spécifications d’installation »parsePluginSpec (parser.ts) prend en charge :
pkg->features: null(comportement par défaut)pkg[*]-> activer toutes les fonctionnalités du manifestepkg[]-> n’activer aucune fonctionnalité optionnellepkg[a,b]-> activer les fonctionnalités nommées@scope/pkg@1.2.3[feat]-> paquet scopé et versionné avec sélection explicite de fonctionnalités
extractPackageName supprime le suffixe de version pour la recherche du chemin sur disque après l’installation.
Source du manifeste et champs requis
Section intitulée « Source du manifeste et champs requis »Le manifeste est résolu comme suit :
package.json.xcsh- repli sur
package.json.pi - repli sur
{ version: package.version }
Implications :
- Il n’existe pas de validation de schéma stricte dans le gestionnaire ou le chargeur.
- Un paquet sans manifeste
xcsh/piest toujours installable et listable. - Le chargement des plugins à l’exécution (
getEnabledPlugins) ignore les paquets sans manifestexcsh/pi. manifest.versionest toujours écrasé par laversiondu paquet.
Un JSON package.json malformé constitue une erreur bloquante au moment de la lecture ; une structure de manifeste malformée peut échouer plus tard uniquement lorsque des champs spécifiques sont consommés.
Flux d’installation/mise à jour (PluginManager.install)
Section intitulée « Flux d’installation/mise à jour (PluginManager.install) »- Analyser la syntaxe des crochets de fonctionnalités à partir de la spécification d’installation.
- Valider le nom du paquet par rapport à l’expression régulière et à la liste de refus des métacaractères shell.
- S’assurer que le
package.jsondu plugin existe (carte des dépendances privéesxcsh-plugins). - Exécuter
bun install <packageSpec>dans~/.xcsh/plugins. - Lire le
node_modules/<name>/package.jsondu paquet installé. - Résoudre le manifeste et calculer
enabledFeatures:[*]: toutes les fonctionnalités déclarées (ounullsi aucune carte de fonctionnalités)[a,b]: valide que chaque fonctionnalité existe dans la carte des fonctionnalités du manifeste[]: liste de fonctionnalités vide- spécification brute :
null(utiliser la politique par défaut plus tard dans le chargeur)
- Mettre à jour l’entrée d’état d’exécution dans le fichier de verrouillage :
{ version, enabledFeatures, enabled: true }.
Sémantique de mise à jour
Section intitulée « Sémantique de mise à jour »Étant donné que la mise à jour est pilotée par l’installation :
xcsh plugin install pkg@newVersionmet à jour la dépendance et la version dans le fichier de verrouillage.- Les paramètres existants sont préservés ; l’entrée d’état est écrasée pour la version, les fonctionnalités et l’activation.
- Il n’existe pas de logique de « vérification des mises à jour » ni de migration transactionnelle.
Flux de suppression (PluginManager.uninstall)
Section intitulée « Flux de suppression (PluginManager.uninstall) »- Valider le nom du paquet.
- Exécuter
bun uninstall <name>dans le répertoire des plugins. - Supprimer l’état d’exécution du plugin dans le fichier de verrouillage :
config.plugins[name]config.settings[name]
Si la commande de désinstallation échoue, l’état d’exécution n’est pas modifié.
Flux de listage (PluginManager.list)
Section intitulée « Flux de listage (PluginManager.list) »- Lire la carte des dépendances des plugins depuis
~/.xcsh/plugins/package.json. - Charger la configuration d’exécution du fichier de verrouillage (fichier manquant -> valeurs par défaut vides).
- Charger les remplacements du projet (
<cwd>/.xcsh/plugin-overrides.json, erreurs d’analyse ou de lecture -> objet vide avec avertissement). - Pour chaque dépendance avec un
package.jsonrésolvable :- construire un enregistrement
InstalledPlugin - fusionner l’état des fonctionnalités et de l’activation :
- base issue du fichier de verrouillage (ou valeurs par défaut)
- les remplacements du projet peuvent remplacer la sélection de fonctionnalités
- la liste
disableddu projet masque le plugin comme désactivé
- construire un enregistrement
Il s’agit de l’état effectif utilisé par la sortie de statut CLI et les opérations de paramètres et fonctionnalités.
Flux de liaison (PluginManager.link)
Section intitulée « Flux de liaison (PluginManager.link) »link prend en charge le développement local de plugins en créant un lien symbolique d’un paquet local vers ~/.xcsh/plugins/node_modules/<pkg.name>.
Comportement :
- Résoudre
localPathpar rapport au répertoire de travail courant du gestionnaire. - Exiger un
package.jsonlocal et un champname. - S’assurer que les répertoires de plugins existent.
- Pour les noms scopés, créer le répertoire de scope.
- Supprimer le chemin existant à l’emplacement du lien cible.
- Créer le lien symbolique.
- Ajouter une entrée dans le fichier de verrouillage d’exécution, activée avec les fonctionnalités par défaut (
null).
Mise en garde : l’implémentation actuelle de PluginManager.link n’applique pas la vérification de limite de chemin cwd présente dans installer.ts historique (normalizedPath.startsWith(normalizedCwd)), la confiance est donc de la responsabilité de l’appelant.
Chargement à l’exécution : du plugin installé aux capacités invocables
Section intitulée « Chargement à l’exécution : du plugin installé aux capacités invocables »Porte de découverte
Section intitulée « Porte de découverte »getEnabledPlugins(cwd) (plugins/loader.ts) lit :
- le manifeste des dépendances des plugins (
package.json) - l’état d’exécution du fichier de verrouillage
- les remplacements du projet via
getConfigDirPaths("plugin-overrides.json", { user: false, cwd })
Filtrage :
- ignorer si aucun
package.jsonde plugin - ignorer si le manifeste (
xcsh/pi) est absent - ignorer si désactivé globalement dans le fichier de verrouillage
- ignorer si désactivé au niveau du projet
Résolution des chemins de capacités
Section intitulée « Résolution des chemins de capacités »Pour chaque plugin activé :
resolvePluginToolPaths(plugin)resolvePluginHookPaths(plugin)resolvePluginCommandPaths(plugin)
Chaque résolveur inclut des entrées de base ainsi que des entrées de fonctionnalités :
- liste de fonctionnalités explicite -> uniquement les fonctionnalités sélectionnées
enabledFeatures === null-> activer les fonctionnalités marquéesdefault: true
Les fichiers manquants sont ignorés silencieusement (protection par existsSync).
Différences de câblage à l’exécution actuelles
Section intitulée « Différences de câblage à l’exécution actuelles »- Les outils sont câblés dans l’exécution aujourd’hui via
discoverAndLoadCustomTools(custom-tools/loader.ts), qui appellegetAllPluginToolPaths(cwd). - Les chemins sont dédupliqués par chemin absolu résolu lors de la découverte des outils personnalisés (ensemble
seen, le premier chemin l’emporte). - Les résolveurs de hooks et commandes existent et sont exportés, mais ce chemin de code ne les câble pas actuellement dans un registre d’exécution de la même façon que les outils.
Détails de la gestion des verrous et de l’état
Section intitulée « Détails de la gestion des verrous et de l’état »PluginManager met en cache la configuration d’exécution en mémoire par instance (#runtimeConfig) et la charge paresseusement une seule fois.
Comportement au chargement :
- fichier de verrouillage manquant ->
{ plugins: {}, settings: {} } - échec de lecture ou d’analyse du fichier de verrouillage -> avertissement + mêmes valeurs par défaut vides
Comportement à la sauvegarde :
- écrit le JSON complet du fichier de verrouillage avec indentation à chaque mutation
Il n’existe pas de verrouillage inter-processus ni de stratégie de fusion ; des writers concurrents peuvent s’écraser mutuellement.
Vérifications de sécurité et limites de confiance
Section intitulée « Vérifications de sécurité et limites de confiance »Validation des entrées et des paquets
Section intitulée « Validation des entrées et des paquets »Le chemin actif du gestionnaire applique la validation des noms de paquets :
- expression régulière pour les spécifications de paquets scopés et non scopés (avec version optionnelle)
- liste de refus explicite des métacaractères shell (
[;&|$(){}[]<>\]`)
Cela limite le risque d’injection de commandes lors de l’invocation de bun install/uninstall.
Limite de confiance du système de fichiers
Section intitulée « Limite de confiance du système de fichiers »- Le code du plugin s’exécute en cours de processus lorsque les modules d’outils personnalisés sont importés ; aucun bac à sable n’est utilisé.
- Les chemins relatifs du manifeste sont joints au répertoire du paquet plugin et seule leur existence est vérifiée.
- Le paquet plugin lui-même est du code de confiance une fois installé.
Vérifications exclusives à l’installateur historique
Section intitulée « Vérifications exclusives à l’installateur historique »installer.ts inclut des vérifications supplémentaires au moment de la liaison qui ne sont pas reproduites dans PluginManager.link :
- le chemin local doit être résolu à l’intérieur du répertoire de travail courant du projet
- protections supplémentaires contre le parcours de nom de paquet et de chemin pour le nommage de la cible du lien symbolique
Étant donné que le CLI utilise PluginManager, ces protections de liaison plus strictes ne sont pas actuellement sur le chemin principal.
Comportement en cas d’échec, de succès partiel et de rollback
Section intitulée « Comportement en cas d’échec, de succès partiel et de rollback »Le gestionnaire de plugins n’est pas transactionnel.
| Étape de l’opération | Comportement en cas d’échec | Rollback |
|---|---|---|
bun install échoue | l’installation s’interrompt avec stderr | N/A (aucune écriture d’état encore effectuée) |
| L’installation réussit, puis la validation du manifeste ou des fonctionnalités échoue | la commande échoue | Aucun rollback de désinstallation ; la dépendance peut rester dans node_modules/package.json |
| L’installation réussit, puis l’écriture du fichier de verrouillage échoue | la commande échoue | Aucun rollback du paquet installé |
bun uninstall réussit, puis l’écriture du fichier de verrouillage échoue | la commande échoue | Le paquet est supprimé, un état d’exécution obsolète peut subsister |
link supprime l’ancienne cible puis la création du lien symbolique échoue | la commande échoue | Aucune restauration du lien ou répertoire précédent |
En pratique, doctor --fix peut corriger certains écarts (bun install, nettoyage de configuration orpheline, nettoyage de fonctionnalités invalides), mais il s’agit d’une opération au mieux.
Résumé du comportement en cas de manifeste malformé ou manquant
Section intitulée « Résumé du comportement en cas de manifeste malformé ou manquant »- Champ
xcsh/pimanquant :- installation/listage : toléré (manifeste minimal)
- découverte des plugins activés à l’exécution : ignoré en tant que non-plugin
- Fonctionnalité manquante référencée par la spécification d’installation ou
features --set/--enable: erreur bloquante avec liste des fonctionnalités disponibles plugin-overrides.jsoninvalide : ignoré avec repli sur{}dans les chemins du gestionnaire et du chargeur- Chemins de fichiers d’outils, hooks ou commandes référencés par le manifeste mais manquants : ignorés silencieusement lors de l’expansion du résolveur ; signalés comme erreurs uniquement par
doctor
Différences de modes et précédence
Section intitulée « Différences de modes et précédence »--dry-run(installation) : renvoie un résultat d’installation synthétique, aucune écriture sur le système de fichiers, le réseau ou l’état.--json: formatage de la sortie uniquement, aucun changement de comportement.- Les remplacements du projet ont toujours la priorité sur le fichier de verrouillage global pour la vue des fonctionnalités et paramètres.
- L’activation effective est
runtimeEnabled && !projectDisabled.
Fichiers d’implémentation
Section intitulée « Fichiers d’implémentation »src/commands/plugin.ts— déclaration de commande CLI et correspondance des indicateurssrc/cli/plugin-cli.ts— dispatch des actions, gestionnaires de commandes destinés à l’utilisateursrc/extensibility/plugins/manager.ts— implémentation active de install/remove/list/link/state/doctorsrc/extensibility/plugins/installer.ts— auxiliaires d’installation historiques et vérifications de sécurité supplémentaires pour la liaisonsrc/extensibility/plugins/loader.ts— découverte des plugins activés et résolution des chemins d’outils, hooks et commandessrc/extensibility/plugins/parser.ts— auxiliaires d’analyse des spécifications d’installation et des noms de paquetssrc/extensibility/plugins/types.ts— contrats de types pour les manifestes, l’exécution et les remplacementssrc/extensibility/custom-tools/loader.ts— câblage à l’exécution des modules d’outils fournis par les plugins