@m3r/sdk 0.5.0

ctx.entryPoints

O Core consulta a extensão no meio da tela ou do save. BEFORE e ACTION podem negar.

O Core consulta a extensão no meio da tela ou do save. Síncrono. O handler devolve { allow, patches?, messages?, ui? }.

src/index.ts
import { SdkEntryPoint } from "@m3r/sdk";

ctx.subscriptions.add(
  ctx.entryPoints.on(SdkEntryPoint.SalesOrderBeforeSave, (payload) => {
    if (!payload.document?.observation) {
      return {
        allow: false,
        messages: [{ severity: "error", text: "Informe a observação.", field: "observation" }]
      };
    }
    return { allow: true };
  })
);

O mesmo código entra em m3r.json → entryPoints[] (IP.SALES.ORDER.BEFORE_SAVE ou o const — o validate resolve os dois).

API

MétodoQuem chamaNota
on(SdkEntryPoint.*, handler)você, no activateTypo → SdkValidationError.
invoke(code, payload)o runtime, não a extensãoSem handler = { allow: true }. Vários handlers: o primeiro allow: false ganha; patches/UI mesclam.
removeAll()host no stop

Resultado

CampoTipoRegra
allowbooleanfalse só vale se o IP canDeny.
messages{ severity, text, field? }[]error | warning | info.
patchesobjetoEm vendas: só observation, customerName, deliveryDate.
ui.setFieldrecordValores na tela.
ui.hideField / disableFieldstring[]
ui.addButton / addTabarrayopenScreen:, openModal: ou openReport: do seu contrato.

AFTER_* e ON_LOAD: devolva allow: true. Negar aí é ignorado ou inválido.

Payload (vendas)

{
  source: "erp" | "sdk" | "pdv" | "portal",
  filialId?, companyId?,
  document?: {
    id?, code?, status?, observation?,
    customerName?, customerId?, deliveryDate?, orderDocType?
  },
  items?, field?, value?
}

IP.EXT.SCREEN.ON_LOAD usa screen, table, values e o mesmo document se a tela abriu a partir de um pedido.

Famílias

FamíliaExemplosPode negar?
PROCESS BEFORE_* / VALIDATESalesOrderBeforeSave, SalesItemValidateSim.
PROCESS AFTER_*SalesOrderAfterSaveNão.
ACTIONSalesOrderActionSave, SalesOrderActionFulfillSim.
SCREEN / FIELDSalesOrderScreenOnLoad, OnFieldChangeNão. Use ui.

Wired ≠ catalogado

IPs de purchase, stock, financial e fiscal existem no catálogo — você declara no manifest. O Core só invoca os wired. Confira GET /developer/sdk/catalog e ctx.capabilities.entryPoints.

Vendas (o que o ERP já chama): BEFORE_CREATE, AFTER_CREATE, BEFORE_SAVE, AFTER_SAVE, BEFORE_FULFILL, AFTER_FULFILL, BEFORE_CANCEL, AFTER_CANCEL, ACTION.SAVE, ACTION.FULFILL, ACTION.CANCEL, SCREEN.ON_LOAD, SCREEN.ON_FIELD_CHANGE, SCREEN.BEFORE_SUBMIT, TOOLBAR, QUICK_SALE.SCREEN.ON_LOAD, FULFILL.SCREEN.ON_LOAD, LIST.ON_LOAD, LIST.ROW_ACTION, RETURN.BEFORE_CREATE, PDV.BEFORE_CLOSE, PDV.AFTER_CLOSE, IP.EXT.SCREEN.ON_LOAD. VALIDATE, TAB, conversão de orçamento, itens e PDV SCREEN.ON_LOAD não estão wired.

Lista completa com wired, tela, serviço, alias PE e timeout: Catálogo de IPs. Const: SdkEntryPoint no pacote. O catálogo SDK descreve limites e enums.

Pode / não pode

Pode

  • Recusar save com allow: false + messages.
  • Completar observação via patches.
  • Abrir modal da extensão com ui.addButton → openModal:demo.auditoria.novo.
  • Gravar a sua tabela no AFTER_SAVE com ctx.ext.records (allow: true).

Não pode

  • ctx.entryPoints.on("IP.SALES.ORDR.BEFORE_SAVE") — typo, exception.
  • Patch de preço, item ou campo livre.
  • SQL / React.
  • Inventar IP. Se não está em SdkEntryPoint, não compile.