Saltar al contenido principal

Registro de pasos de complemento de servidor

Id del esquema: plugin-step@1 Esquema legible por máquina: plugin-step.schema.json

El contenedor de registro canónico de un paso de complemento de servidor (sección 6.6): lógica del lado del servidor que se ejecuta cuando se crea, actualiza o elimina un registro de una entidad. El contenedor indica cuándo y cómo se ejecuta la lógica; una implementación en BS Lang incluye además el script en línea, que se valida con la gramática de BS Lang además de con este esquema. Un registro se valida de forma idéntica tanto si procede de un diseñador como de una llamada a la API, de un asistente de IA o de una importación de solución.

Forma​

CampoTipoObligatorioNotas
logicalNamestringsíCon el prefijo del editor, en snake_case en minúsculas.
displayNamestringsíNombre legible del paso.
publisherPrefixstringsíEl prefijo del editor propietario, que debe servir de espacio de nombres a logicalName; no el de la tabla observada. Una tabla estándar como account no lleva prefijo a propósito, y validar con ella hacía imposible dar nombre a un paso sobre una de esas tablas.
entitystringsíLa entidad cuyas escrituras desencadenan el paso.
messagestringsíCreate, Update o Delete.
stagestringsíPreValidation, PreOperation o PostOperation.
executionModestringsíSynchronous (en línea, dentro de la escritura) o Asynchronous (en cola a través de la bandeja de salida y ejecutado después de confirmarse la escritura). Un paso asíncrono debe ser PostOperation: se ejecuta cuando el registro ya está guardado, así que no le queda nada que rechazar.
rankintegersíOrden de ejecución entre los pasos de la misma entidad + mensaje + fase; el menor se ejecuta primero.
isEnabledbooleansíUn paso deshabilitado se almacena pero nunca se ejecuta.
implementationobjectsíExactamente una implementación (vea más abajo).

Implementación​

CampoTipoObligatorioNotas
typestringsíBsLangScript o DotNetAssembly.
scriptstringcuando es BsLangScriptEl código fuente de BS Lang.
assemblyReferencestringcuando es DotNetAssemblyLa clave de almacenamiento del ensamblado cargado.
typeNamestringcuando es DotNetAssemblyEl tipo de complemento que se instancia.

Fases​

  • PreValidation: se ejecuta antes de la operación; comprobaciones generales de forma y de seguridad.
  • PreOperation: se ejecuta justo antes de la escritura; puede cambiar valores de campos del registro o rechazar la operación entera.
  • PostOperation: se ejecuta justo después de la escritura; para cambios en cascada o dependientes.

Un paso rechaza una operación llamando a throwValidationError("reason"), lo que detiene la escritura y devuelve el motivo al llamador.

Ejemplo​

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

Funciones de host para scripts de BS Lang​

Un paso BsLangScript lee y cambia el registro mediante estas funciones de host:

FunciónFinalidad
getValue("field")El valor actual de un campo del registro que se está escribiendo.
setValue("field", value)Cambia el valor de un campo (solo se tiene en cuenta en PreOperation).
getPreValue("field")El valor anterior del campo (en actualizaciones y eliminaciones).
throwValidationError("message")Rechaza la operación y la revierte.
message() / stage() / entityName()La operación, la fase y la entidad actuales.
userId() / depth()El usuario que la desencadenó y la profundidad de recursión.

Acceder a otras tablas​

Las funciones anteriores solo ven el registro que se está escribiendo. Las siguientes acceden al resto del entorno, y todas ellas se ejecutan como el usuario que desencadenó el paso: un script no es una forma de saltarse un permiso, y un paso cuyo llamador no puede leer una tabla no obtiene nada de ella.

FunciónFinalidad
getRecord("table", id)Un registro como objeto, o vacío si no existe. Incluye .id.
queryRecords("table", "field", value)Las filas en las que un campo es igual a un valor, como una lista de objetos. Limitado a 200.
runQuery({ … })Ejecuta un documento parsware-query@1 completo: filtros and/or anidados con diez operadores, combinaciones, ordenaciones, paginación o un aggregate que devuelve grupos. El mismo lenguaje de consulta que genera Búsqueda avanzada y que almacena una consulta guardada. Filas limitadas a 200; un agregado no. Una columna combinada se lee con su alias (row.acct.par_industry), y el 'from' de un vínculo debe ir entre comillas porque from es una palabra clave de BS Lang.
runSavedQuery("name")Ejecuta una consulta guardada por su nombre lógico. La complejidad reside en un diseñador y viaja en la solución, así que el script solo nombra la pregunta.
countRecords("table", "field", value)Cuántos hay, sin obtenerlos: un COUNT real, así que es correcto por encima del límite de 200 filas que acota queryRecords.
createRecord("table", { field: value, … })Crea un registro y devuelve su id.
updateRecord("table", id, { field: value, … })Cambia los campos indicados, y solo esos.
deleteRecord("table", id)Elimina un registro.

Una escritura hecha de esta forma ejecuta las reglas habituales, así que un paso registrado en la tabla que se escribe se ejecutará a su vez. Ese anidamiento está limitado a una profundidad de ocho y depth() indica a un script dónde se encuentra, pero el límite es una red de seguridad, no un diseño. Un paso que escribe en la tabla que observa se desencadenará a sí mismo, y la solución es una condición o una tabla distinta.

Importar lógica compartida​

El script de un paso puede importar con import un script de solución por su nombre, exactamente igual que una regla de negocio de cliente, de modo que una regla que aplican varios pasos se escribe una sola vez:

import 'par_approval_rules';

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

Funcionan los dos estilos de comillas. El módulo debe ser un script de solución del mismo entorno; cualquier otra cosa falla al guardar el paso, no al ejecutarlo.