Naar hoofdinhoud gaan

Registratie van een serverplug-instap

Schema-id: plugin-step@1 Machineleesbaar schema: plugin-step.schema.json

De canonieke registratiewrapper voor een serverplug-instap (sectie 6.6) — logica aan de serverkant die draait wanneer een record van een tabel wordt aangemaakt, bijgewerkt of verwijderd. De wrapper zegt wanneer en hoe de logica draait; een BS Lang-implementatie bevat daarnaast het script inline, dat naast dit schema ook door de BS Lang-grammatica wordt gevalideerd. Een registratie wordt op dezelfde manier gevalideerd, of ze nu uit een ontwerper komt, uit een API-aanroep, van een AI-assistent of uit een oplossingsimport.

Structuur​

VeldTypeVerplichtOpmerkingen
logicalNametekenreeksjaMet uitgeversvoorvoegsel, in kleine letters snake_case.
displayNametekenreeksjaLeesbare naam van de stap.
publisherPrefixtekenreeksjaHet voorvoegsel van de eigenaar-uitgever, waarmee logicalName een naamruimte moet krijgen — niet dat van de bewaakte tabel. Een standaardtabel zoals account heeft bewust geen voorvoegsel, en valideren daartegen maakte het onmogelijk om een stap op zo'n tabel een naam te geven.
entitytekenreeksjaDe tabel waarvan schrijfacties de stap activeren.
messagetekenreeksjaCreate, Update of Delete.
stagetekenreeksjaPreValidation, PreOperation of PostOperation.
executionModetekenreeksjaSynchronous (inline, binnen de schrijfactie) of Asynchronous (in de wachtrij gezet via de outbox en uitgevoerd nadat de schrijfactie is vastgelegd). Een asynchrone stap moet PostOperation zijn: die draait nadat de record al is opgeslagen, dus er valt niets meer te weigeren.
rankgeheel getaljaUitvoeringsvolgorde tussen stappen op dezelfde tabel + bericht + fase; lager draait eerst.
isEnabledbooleaansjaEen uitgeschakelde stap wordt opgeslagen maar nooit uitgevoerd.
implementationobjectjaPrecies één implementatie (zie hieronder).

Implementatie​

VeldTypeVerplichtOpmerkingen
typetekenreeksjaBsLangScript of DotNetAssembly.
scripttekenreeksbij BsLangScriptDe BS Lang-broncode.
assemblyReferencetekenreeksbij DotNetAssemblyDe opslagsleutel van de geüploade assembly.
typeNametekenreeksbij DotNetAssemblyHet plug-intype dat moet worden geïnstantieerd.

Fasen​

  • PreValidation — draait vóór de bewerking; grove controles op vorm en beveiliging.
  • PreOperation — draait vlak vóór de schrijfactie; kan veldwaarden op de record wijzigen of de hele bewerking weigeren.
  • PostOperation — draait vlak na de schrijfactie; voor doorwerkende of afhankelijke wijzigingen.

Een stap weigert een bewerking door throwValidationError("reason") aan te roepen. Dat stopt de schrijfactie en geeft de reden terug aan de aanroeper.

Voorbeeld​

{
"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.\"); }"
}
}

Hostfuncties voor BS Lang-scripts​

Een BsLangScript-stap leest en wijzigt de record via deze hostfuncties:

FunctieDoel
getValue("field")De huidige waarde van een veld op de record die wordt geschreven.
setValue("field", value)De waarde van een veld wijzigen (alleen gehonoreerd in PreOperation).
getPreValue("field")De vorige waarde van het veld (bij updates en verwijderingen).
throwValidationError("message")De bewerking weigeren en terugdraaien.
message() / stage() / entityName()De huidige bewerking, fase en tabel.
userId() / depth()De gebruiker die de stap activeerde en de recursiediepte.

Andere tabellen bereiken​

De functies hierboven zien alleen de record die wordt geschreven. Deze bereiken de rest van de omgeving, en elk daarvan draait als de gebruiker die de stap activeerde — een script is geen manier om een recht te omzeilen, en een stap waarvan de aanroeper een tabel niet mag lezen, krijgt daar niets uit terug.

FunctieDoel
getRecord("table", id)Eén record als object, of leeg als die er niet is. .id staat erop.
queryRecords("table", "field", value)De rijen waarin een veld gelijk is aan een waarde, als lijst van objecten. Begrensd op 200.
runQuery({ … })Voert een volledig parsware-query@1-document uit — geneste EN/OF-filters met tien operators, joins, sorteringen, paginering, of een aggregate die groepen teruggeeft. Dezelfde querytaal die Geavanceerd zoeken produceert en een opgeslagen query bewaart. Rijen begrensd op 200; een aggregatie niet. Een gekoppelde kolom lees je onder zijn alias (row.acct.par_industry), en de 'from' van een koppeling moet tussen aanhalingstekens, omdat from een sleutelwoord is in BS Lang.
runSavedQuery("name")Voert een opgeslagen query uit op logische naam. De complexiteit zit in een ontwerper en reist mee in de oplossing, dus het script noemt alleen de vraag.
countRecords("table", "field", value)Hoeveel het er zijn, zonder ze op te halen — een echte COUNT, dus correct voorbij de grens van 200 rijen die queryRecords beperkt.
createRecord("table", { field: value, … })Maakt een record aan en geeft de id ervan terug.
updateRecord("table", id, { field: value, … })Wijzigt de genoemde velden, en alleen die.
deleteRecord("table", id)Verwijdert een record.

Een schrijfactie die zo wordt gedaan, doorloopt de gewone regels, dus een stap die is geregistreerd op de tabel waarnaar wordt geschreven, draait op zijn beurt. Die nesting is begrensd op een diepte van acht, en depth() vertelt een script waar het is — maar de limiet is een vangnet, geen ontwerp. Een stap die schrijft naar de tabel die hij bewaakt, activeert zichzelf, en de oplossing is een voorwaarde of een andere tabel.

Gedeelde logica importeren​

Het script van een stap mag een oplossingsscript op naam importeren, precies zoals een clientbedrijfsregel dat doet, zodat een regel die door meerdere stappen wordt afgedwongen maar één keer wordt geschreven:

import 'par_approval_rules';

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

Beide soorten aanhalingstekens werken. De module moet een oplossingsscript in dezelfde omgeving zijn; al het andere faalt bij het opslaan van de stap in plaats van bij het uitvoeren.