Plugin SDK

Déclarez des parcours, schémas, contributions d’éditeur et traitements via le contrat public.

Sur cette page

Définition du plugin

PluginDefinition et definePlugin sont exportés par @bracten/sdk. Le module ESM possède un export par défaut. plugin:pack assemble les imports statiques du SDK et des dépendances JavaScript avant signature ; le package installé est autonome, y compris hors du checkout.

src/index.ts
import { definePlugin } from "@bracten/sdk";

export default definePlugin({
  priority: 10,
  hooks: {
    async beforeContentSave(entry, context) {
      if (entry.type === "post" && entry.status === "published" && !entry.excerpt) {
        context.failValidation("Ajoutez un extrait avant publication.");
      }
    },
  },
});

Contributions disponibles

CléContrat
contentTypes / taxonomies / settingsSchémas de contenu, classements, champs de réglages et valeurs validées.
migrations / activate / deactivateÉvolutions versionnées et lifecycle transactionnel.
endpointsGET, POST ou PUT ; public explicite ou permission privée, schémas JSON d’entrée et de sortie facultatifs.
adminPages / publicPagesSections déclaratives texte, formulaires, tableaux et liens.
blocks / fieldTypesBlocs à copie native de secours et champs structurés versionnés.
jobs / commandsHandlers de tâches durables et commandes CLI de l’extension.
filterscontent.title et render.head ; anciennes signatures conservées.
hooks / eventsHooks nommés de contenu, médias, utilisateurs, activation et rendu ; six événements métier durables, dont auth.login.
rolesRôles déclarés sans attribution automatique aux utilisateurs.
widgets / adminMenu / settingsSectionsVue d’ensemble, liens vers des pages déclarées et sections de réglages.
toolbarActions / integrationsActions privées d’éditeur ou de médiathèque, liens vers les espaces d’intégration.
webhooksÉvénements nommés avec payload validé et outbox transactionnelle.
storageProviders / cacheProviders / emailProvidersJusqu’à cinq factories par catégorie, choisies dans la configuration serveur.
priorityOrdre croissant, défaut 10, puis identifiant de plugin.

Les permissions du manifest commencent par l’identifiant du plugin. Elles sont attribuées initialement aux rôles système possédant plugins.manage ; les autres rôles les reçoivent explicitement. L’activation et chaque action privée revalident les droits.

Contexte et services

PluginContext fournit pluginId, publicUrl, settings.get/set, database.query(sql, parameters), failValidation(message) et services. PluginRequestContext ajoute user, query et visibility.clause. Le runtime fournit authorize(permission) pour relire les droits ; une opération système ne devient pas un utilisateur implicite. database.query retourne un tableau de lignes et utilise la transaction en cours.

ServiceUsage
email.enqueueEnregistrer un e-mail dans l’outbox avec la transaction métier.
jobs.enqueue / schedule / unscheduleTâches déclarées du module, reprises et déduplication facultative.
storage.put / get / list / deleteObjets propres au plugin, immuables, maximum 10 Mo et purge après sept jours.
cache.get / set / delete / invalidateCache isolé par plugin, TTL et tags ; les effets cache ne sont pas transactionnels.
accounts.registerCréer un compte sans rôle ni permission fournis par le client.
access.setRule / grant / revokeDéfinir les groupes d’accès et leurs attributions.
webhooks.publishInscrire un événement déclaré dans l’outbox de la transaction.
observability.metric / reportMesures bornées et rapports expurgés dans l’espace de l’extension.
serviceInfo()Identifier les providers configurés sans exposer leurs secrets.

Les providers optionnels doivent être testés avant emploi. Les clés de stockage font au plus 200 caractères, avec segments de 100 caractères maximum composés de lettres, chiffres, points, tirets ou soulignements ; un segment commence par une lettre, un chiffre, un tiret ou un soulignement. Les chemins relatifs ascendants sont refusés.

Les factories utilisent PluginProviderContext : pluginId, settings, options et dataDirectory, sans services CMS pour éviter une dépendance circulaire au démarrage. storageProviders retourne { identity, storage }, cacheProviders son contrat de cache et emailProviders un objet deliver({ to, subject, text }, deliveryId), avec close() facultatif. L’identité du stockage décrit un jeu de données stable sans secret. deliveryId reste identique pendant les reprises, sans garantie exactement une fois pour l’effet externe.

Le guide des fournisseurs SDK détaille la sélection serveur, les capabilities réservées aux factories officielles, la fermeture des ressources et la reprise. Les services métier continuent d’utiliser email.enqueue, storage et cache indépendamment du fournisseur choisi.

Routes et pages déclaratives

ContributionAdresse
Page admin/admin/#extensions/<plugin>/<page>
Page publique/extensions/<plugin>/<page>
Endpoint privé/api/v1/extensions/<plugin>/endpoints/<name>
Endpoint public/api/v1/public-extensions/<plugin>/endpoints/<name>
Registre adminGET /api/v1/extensions

Les pages ne chargent pas de JavaScript arbitraire du plugin dans le navigateur. Les champs et actions sont validés puis rendus par les composants du CMS. Une action et sa page ont des contrôles indépendants ; masquer un bouton ne protège pas un endpoint.

Les mutations publiques exigent Origin exact, jeton signé expirant obtenu sur /api/v1/public-extensions/<plugin>/token et champ anti-robot vide. Le corps est limité à 64 Ko. Les limites durables sont 40 mutations ou 240 lectures par plugin et adresse distante sur quinze minutes ; ces appels partagent leur compteur.

Un endpoint peut déclarer schema.input et schema.output avec PluginJsonSchema. L’entrée est validée avant le handler et la sortie avant commit ; une sortie invalide annule ses écritures. L’ancien input: FieldDefinition[] reste compatible mais ne peut pas coexister avec schema.input. Le sous-ensemble accepte des schémas inline bornés, sans $ref, téléchargement externe ni coercition implicite. Les schémas des endpoints actifs et autorisés alimentent l’OpenAPI de l’instance ; sans déclaration, seul le transport JSON peut être décrit.

Requêtes publiques et accès réservés

Clause paramétrée après un paramètre existant
const guard = context.visibility.clause("c", 1);
const sql = "SELECT c.id, c.title, c.slug FROM content c " +
  "WHERE c.type = $1 AND c.status = 'published' AND " + guard.sql +
  " ORDER BY c.published_at DESC, c.id LIMIT 20";
const rows = await context.database.query(sql, ["post", ...guard.parameters]);

offset indique le nombre de paramètres déjà présents. Appliquez la même clause avant total, facettes et relations ; ne filtrez jamais seulement après LIMIT. Une règle portée par un plugin désactivé continue à fermer le contenu. Aucun rôle administrateur ne contourne automatiquement ces règles de diffusion.

Distribution et limites

Les modules de confiance peuvent techniquement sortir des helpers ; leur approbation reste nécessaire. Il n’existe pas de chargement de composants admin tiers, de middleware HTTP arbitraire ou de sous-processus isolé fourni par ce contrat.

Le guide des contributions SDK précise les registres, rôles, schémas, événements et providers, avec leurs limites. Consultez aussi les extensions officielles, les blocs, les champs, les hooks et le packaging.

Rechercher dans les guides

Saisissez un mot-clé.

↑↓ ParcourirEntrée OuvrirEsc Fermer