Aller au contenu principal

Inscription d’une étape de plug-in serveur

Identifiant du schéma : plugin-step@1 Schéma lisible par machine : plugin-step.schema.json

L’enveloppe d’inscription canonique d’une étape de plug-in serveur (section 6.6) — une logique côté serveur qui s’exécute lorsqu’un enregistrement d’une table est créé, mis à jour ou supprimé. L’enveloppe indique quand et comment la logique s’exécute ; une implémentation BS Lang porte en plus le script en ligne, qui est validé par la grammaire BS Lang en plus de ce schéma. Une inscription est validée de manière identique, qu’elle provienne d’un concepteur, d’un appel d’API, d’un assistant IA ou d’une importation de solution.

Structure​

ChampTypeObligatoireRemarques
logicalNamestringouiPréfixé par l’éditeur, en snake-case minuscule.
displayNamestringouiNom lisible de l’étape.
publisherPrefixstringouiLe préfixe de l’éditeur propriétaire, dans l’espace de noms duquel doit se trouver logicalName — et non celui de la table surveillée. Une table standard telle que account est volontairement sans préfixe, et valider par rapport à elle rendait impossible de nommer une étape sur une telle table.
entitystringouiLa table dont les écritures déclenchent l’étape.
messagestringouiCreate, Update ou Delete.
stagestringouiPreValidation, PreOperation ou PostOperation.
executionModestringouiSynchronous (en ligne, au sein de l’écriture) ou Asynchronous (mise en file via l’outbox et exécutée après la validation de l’écriture). Une étape asynchrone doit être PostOperation : elle s’exécute alors que l’enregistrement est déjà sauvegardé, elle n’a donc plus rien à refuser.
rankintegerouiOrdre d’exécution parmi les étapes portant sur la même table + message + phase ; la plus basse s’exécute en premier.
isEnabledbooleanouiUne étape désactivée est stockée mais jamais exécutée.
implementationobjectouiExactement une implémentation (voir ci-dessous).

Implémentation​

ChampTypeObligatoireRemarques
typestringouiBsLangScript ou DotNetAssembly.
scriptstringsi BsLangScriptLe code source BS Lang.
assemblyReferencestringsi DotNetAssemblyLa clé de stockage de l’assembly téléversé.
typeNamestringsi DotNetAssemblyLe type de plug-in à instancier.

Phases d’exécution​

  • PreValidation — s’exécute avant l’opération ; vérifications grossières de forme et de sécurité.
  • PreOperation — s’exécute juste avant l’écriture ; peut modifier des valeurs de champ de l’enregistrement ou rejeter toute l’opération.
  • PostOperation — s’exécute juste après l’écriture ; pour les modifications en cascade ou dépendantes.

Une étape rejette une opération en appelant throwValidationError("reason"), ce qui arrête l’écriture et renvoie le motif à l’appelant.

Exemple​

{
"logicalName": "par_invoice_reject_negative",
"displayName": "Reject negative invoice total",
"entity": "par_invoice",
"message": "Create",
"stage": "PreOperation",
"executionMode": "Synchronous",
"rank": 1,
"isEnabled": true,
"implementation": {
"type": "BsLangScript",
"script": "if (getValue(\"par_total\") < 0) { throwValidationError(\"Total cannot be negative.\"); }"
}
}

Fonctions hôtes des scripts BS Lang​

Une étape BsLangScript lit et modifie l’enregistrement au moyen de ces fonctions hôtes :

FonctionRôle
getValue("field")La valeur actuelle d’un champ de l’enregistrement en cours d’écriture.
setValue("field", value)Modifie la valeur d’un champ (prise en compte uniquement en PreOperation).
getPreValue("field")La valeur précédente du champ (mises à jour et suppressions).
throwValidationError("message")Rejette l’opération et l’annule.
message() / stage() / entityName()L’opération, la phase et la table en cours.
userId() / depth()L’utilisateur déclencheur et la profondeur de récursion.

Accéder à d’autres tables​

Les fonctions ci-dessus ne voient que l’enregistrement en cours d’écriture. Celles-ci accèdent au reste de l’environnement, et chacune s’exécute en tant qu’utilisateur ayant déclenché l’étape — un script n’est pas un moyen de contourner une autorisation, et une étape dont l’appelant ne peut pas lire une table n’en obtient rien.

FonctionRôle
getRecord("table", id)Un enregistrement sous forme d’objet, ou vide s’il n’existe pas. Il porte .id.
queryRecords("table", "field", value)Les lignes où un champ est égal à une valeur, sous forme de liste d’objets. Limité à 200.
runQuery({ … })Exécute un document parsware-query@1 complet — filtres et/ou imbriqués avec dix opérateurs, jointures, tris, pagination, ou un aggregate qui renvoie des groupes. Le même langage de requête que celui qu’émet la recherche avancée et que stocke une requête enregistrée. Lignes limitées à 200 ; un agrégat ne l’est pas. Une colonne jointe se lit sous son alias (row.acct.par_industry), et le 'from' d’un lien doit être entre guillemets, car from est un mot-clé de BS Lang.
runSavedQuery("name")Exécute une requête enregistrée par son nom logique. La complexité réside dans un concepteur et voyage dans la solution : le script ne fait que nommer la question.
countRecords("table", "field", value)Combien il y en a, sans les récupérer — un vrai COUNT, donc exact au-delà de la limite de 200 lignes qui borne queryRecords.
createRecord("table", { field: value, … })Crée un enregistrement et renvoie son id.
updateRecord("table", id, { field: value, … })Modifie les champs nommés, et eux seuls.
deleteRecord("table", id)Supprime un enregistrement.

Une écriture effectuée ainsi applique les règles ordinaires : une étape inscrite sur la table écrite s’exécutera à son tour. Cette imbrication est limitée à une profondeur de huit, et depth() indique au script où il se trouve — mais la limite est un filet de sécurité, pas une conception. Une étape qui écrit dans la table qu’elle surveille se déclenchera elle-même ; la solution est une condition ou une autre table.

Importer une logique partagée​

Le script d’une étape peut import un script de solution par son nom, exactement comme une règle métier client, afin qu’une règle appliquée par plusieurs étapes ne soit écrite qu’une fois :

import 'par_approval_rules';

if (getValue('par_total') > par_approval_rules.limit()) { … }

Les deux styles de guillemets fonctionnent. Le module doit être un script de solution du même environnement ; toute autre chose échoue à l’enregistrement de l’étape plutôt qu’à son exécution.