funifier-mcp 0.3.19 → 0.3.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/funifier.mdc +1 -0
- package/.github/copilot-instructions.md +1 -0
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +30 -0
- package/datasource-funifier-docs/.coverage.json +13 -5
- package/datasource-funifier-docs/knowledge/guides/server-utils.md +718 -0
- package/datasource-funifier-docs/knowledge/guides/trigger-examples.md +6 -6
- package/datasource-funifier-docs/knowledge/guides/triggers-guide.md +74 -11
- package/datasource-funifier-docs/knowledge/index.md +1 -0
- package/datasource-funifier-docs/knowledge/modules/trigger.md +29 -1
- package/dist/mcp/bundle.js +106 -106
- package/package.json +1 -1
- package/skills/funifier/SKILL.md +1 -0
- package/skills/funifier/references/create-trigger.md +28 -16
- package/skills/funifier/references/debug.md +0 -6
- package/skills/funifier/references/help.md +0 -6
- package/skills/funifier/references/server-utils.md +94 -0
|
@@ -34,7 +34,7 @@ Este documento reúne exemplos de produção de triggers Funifier — código Gr
|
|
|
34
34
|
|
|
35
35
|
Todas herdadas de `triggers-guide.md` §1.5 — releia antes de copiar qualquer exemplo. As mais relevantes aqui:
|
|
36
36
|
|
|
37
|
-
> ⚠️ **`throw`
|
|
37
|
+
> ⚠️ **`throw` só cancela em `before_*` de coleção de banco (`/v3/database/{collection}`), e apenas em instâncias atualizadas.** No restante (player, action, `after_*`, bulk) a rejeição é em `after_create` + `database.delete` (§8, e `triggers-guide.md` §8). A interrupção é **version-dependent** — confirme com a sonda de `triggers-guide.md` §8 antes de depender dela.
|
|
38
38
|
> ⚠️ **Em Groovy use `.id`, não `._id`** → todos os exemplos abaixo seguem essa regra.
|
|
39
39
|
> ⚠️ **Nunca `track` a mesma ação que disparou o trigger** → loop infinito; filtre por `entity.actionId` no início (§10).
|
|
40
40
|
|
|
@@ -247,13 +247,13 @@ void trigger(event, entity, player, database) {
|
|
|
247
247
|
## 7. `custom__c | before_create` — Normalizar Campos
|
|
248
248
|
|
|
249
249
|
Quando usar: enriquecer/normalizar um documento `__c` antes de salvar.
|
|
250
|
-
Não usar quando: precisa **rejeitar** o documento → §8 (`
|
|
250
|
+
Não usar quando: precisa **rejeitar** o documento de forma portável → §8 (`after_create` + delete funciona em qualquer instância).
|
|
251
251
|
Depende de: —
|
|
252
252
|
Disponível em: Trigger.
|
|
253
253
|
|
|
254
254
|
### Descrição
|
|
255
255
|
|
|
256
|
-
`
|
|
256
|
+
Normaliza email/nome/ID antes de persistir. Métodos auxiliares extraídos para clareza. **Nota:** em instâncias atualizadas, um `throw` aqui também **rejeita** o documento (modo estrito — `triggers-guide.md` §8, Modo A), mas isso é version-dependent; para rejeição garantida em qualquer instância, use o padrão `after_create` do §8.
|
|
257
257
|
|
|
258
258
|
### Uso
|
|
259
259
|
|
|
@@ -288,7 +288,7 @@ String extractNumeric(Object value) {
|
|
|
288
288
|
|
|
289
289
|
### Armadilhas conhecidas
|
|
290
290
|
|
|
291
|
-
- **
|
|
291
|
+
- **Contar com `throw` no `before_create` em qualquer instância** → só rejeita no modo estrito (instâncias atualizadas; `triggers-guide.md` §8). Para portabilidade, valide/rejeite em `after_create` (§8) ou confirme o suporte com a sonda de §8 antes.
|
|
292
292
|
|
|
293
293
|
---
|
|
294
294
|
|
|
@@ -301,7 +301,7 @@ Disponível em: Trigger.
|
|
|
301
301
|
|
|
302
302
|
### Descrição
|
|
303
303
|
|
|
304
|
-
|
|
304
|
+
Padrão **portável** (funciona em toda instância, atualizada ou não): o documento já foi salvo (`triggers-guide.md` §1.5, Modo B). Se inválido, deleta e devolve a mensagem no `entity`. `BusinessException` centraliza o cleanup das múltiplas validações. Em instâncias atualizadas, a mesma validação pode rodar em `before_create` com `throw` (Modo A — aborta antes de salvar e não exige delete), mas o `after_create` abaixo é a escolha segura quando o suporte é desconhecido.
|
|
305
305
|
|
|
306
306
|
### Uso
|
|
307
307
|
|
|
@@ -346,7 +346,7 @@ public class BusinessException extends Exception {
|
|
|
346
346
|
|
|
347
347
|
### Armadilhas conhecidas
|
|
348
348
|
|
|
349
|
-
- **Usar `before_create` aqui** → `throw`
|
|
349
|
+
- **Usar `before_create` aqui sem confirmar suporte** → `throw` só impede o save no modo estrito (version-dependent; `triggers-guide.md` §8). Em instância antiga o documento salva. Correção: `after_create` + delete, ou sondar o suporte antes (§8 do guia).
|
|
350
350
|
- **Esquecer `entity.clear()`** → o documento rejeitado mantém os dados. Correção: limpar e devolver só `message`.
|
|
351
351
|
|
|
352
352
|
---
|
|
@@ -13,7 +13,7 @@ Este documento descreve os conceitos de triggers Funifier — assinatura do scri
|
|
|
13
13
|
- Consulte ao **criar uma trigger** e precisar entender `event`, `entity`, `script`.
|
|
14
14
|
- Consulte ao precisar saber **quais variáveis** o script recebe (`event`, `entity`, `player`, `database`, `manager`, `context`).
|
|
15
15
|
- Consulte ao escolher o **evento certo** (incl. eventos de bulk/CSV).
|
|
16
|
-
- Consulte ao precisar **rejeitar uma
|
|
16
|
+
- Consulte ao precisar **rejeitar/abortar uma operação** — incluindo o novo modo estrito (`before_*` de coleções de banco interrompem via `throw`) e por que `throw` não cancela nos demais casos.
|
|
17
17
|
- Consulte ao precisar ler a **origem de uma conquista** (`context.extra`).
|
|
18
18
|
|
|
19
19
|
### 1.3 Quando NÃO consultar
|
|
@@ -33,12 +33,12 @@ Este documento descreve os conceitos de triggers Funifier — assinatura do scri
|
|
|
33
33
|
| Escolher a entidade | Entidades disponíveis | §5 |
|
|
34
34
|
| Saber o tipo do `entity` para cada combinação | Combinações Evento × Entidade | §6 |
|
|
35
35
|
| Saber qual ação/conquista originou o evento | `context.extra` (cadeia de conquistas) | §7 |
|
|
36
|
-
|
|
|
36
|
+
| Abortar/rejeitar uma operação | Modo estrito (`before_*` de banco via `throw`) ou `after_create` + delete | §8 |
|
|
37
37
|
| Processar import/insert em lote | `entity` como List (bulk) | §9 |
|
|
38
38
|
|
|
39
39
|
### 1.5 Restrições globais críticas
|
|
40
40
|
|
|
41
|
-
> ⚠️ **`throw`
|
|
41
|
+
> ⚠️ **`throw` cancela a operação APENAS em `before_create`/`before_update`/`before_delete` de coleções de banco (`POST`/`PUT`/`DELETE /v3/database/{collection}`).** Nesses três eventos o `DatabaseRest` roda a trigger em **modo estrito** (`TriggerManager.executeStrict`): qualquer exceção lançada no script aborta a operação — o documento **não** é gravado/removido e a API responde **HTTP 500** com `{ "message": "<mensagem>", "statusCode": 500 }` (§8). **Em todo o resto** — player, action, swap, quiz, achievement disparados pelos managers, eventos `*_bulk`/`csv_*` (inclusive bulk insert em coleção de banco), e qualquer evento `after_*` — `throw` **NÃO** cancela: o documento persiste e a exceção só vai para o `trigger_log`. → Nesses casos, para rejeitar, use `after_create` + `database.delete(...)` (§8). ⚠️ O modo estrito é **version-dependent** — nem toda instância recebeu a atualização; **sonde antes de depender dele** (§8) ou use o `after_create` por padrão.
|
|
42
42
|
|
|
43
43
|
> ⚠️ **Em Groovy, acesse o ID com `entity.id`, não `entity._id`.** Consequência: `_id` retorna `null` (`patterns.md` §10). → Use `.id` em código; `_id` só no JSON/documento. Vale para `entity`, `player`, `ActionLog`, `Achievement`.
|
|
44
44
|
|
|
@@ -168,7 +168,7 @@ Eventos definem **quando** a trigger roda. Os oficiais aparecem no dropdown do S
|
|
|
168
168
|
|
|
169
169
|
### Armadilhas conhecidas
|
|
170
170
|
|
|
171
|
-
- **`before_create` esperando bloquear via `throw`** → não cancela (§1.5/§8).
|
|
171
|
+
- **`before_create` esperando bloquear via `throw`** → só cancela em coleções de banco (`/v3/database/{collection}`); para player/action/etc. não cancela (§1.5/§8).
|
|
172
172
|
- **`POST` esperando acionar `before_update`** → `POST` dispara `before_create` (§1.5).
|
|
173
173
|
|
|
174
174
|
---
|
|
@@ -277,19 +277,39 @@ Exemplo de uso em `trigger-examples.md` (Exemplo 2 — taggear conquista com ori
|
|
|
277
277
|
|
|
278
278
|
---
|
|
279
279
|
|
|
280
|
-
## 8.
|
|
280
|
+
## 8. Abortar uma Operação e Rejeitar Documentos
|
|
281
281
|
|
|
282
|
-
Quando usar: ao precisar validar e **rejeitar** uma
|
|
283
|
-
Não usar quando: só precisa enriquecer/normalizar →
|
|
284
|
-
Depende de: `database.delete(...)
|
|
282
|
+
Quando usar: ao precisar validar e **rejeitar/abortar** uma operação.
|
|
283
|
+
Não usar quando: só precisa enriquecer/normalizar → mutação direta no `before_create`.
|
|
284
|
+
Depende de: modo estrito (`executeStrict` — `modules/trigger.md` §2.5.1) ou `database.delete(...)` + BusinessException.
|
|
285
285
|
Disponível em: Trigger.
|
|
286
286
|
|
|
287
287
|
### Descrição
|
|
288
288
|
|
|
289
|
-
|
|
289
|
+
Existem **dois modos**, e qual vale depende de **onde** a trigger roda:
|
|
290
|
+
|
|
291
|
+
**Modo A — estrito (`throw` aborta).** Vale **só** para `before_create`/`before_update`/`before_delete` de **coleções de banco** acionadas pela Database API (`POST`/`PUT`/`DELETE /v3/database/{collection}`). O `DatabaseRest` roda essas triggers via `TriggerManager.executeStrict`: lançar exceção no script **aborta a operação** — o documento não é gravado/removido e a API devolve **HTTP 500** com `{ "message": "<mensagem>", "statusCode": 500 }` (corpo `CallbackMessage`). É o caminho preferido para rejeitar documentos `__c`.
|
|
292
|
+
|
|
293
|
+
**Modo B — persistência garantida (`throw` não cancela).** Vale para **todo o resto**: player, action, swap, quiz, achievement disparados pelos managers; eventos `after_*`; e os eventos de lote (`*_bulk`/`csv_*`, inclusive bulk insert em coleção de banco). Aqui o Funifier persiste o documento antes de rodar a trigger e `throw` não faz rollback — a rejeição se faz em `after_create`, deletando o documento já salvo e devolvendo a mensagem no `entity`.
|
|
290
294
|
|
|
291
295
|
### Uso
|
|
292
296
|
|
|
297
|
+
**Modo A — `before_create`/`before_update`/`before_delete` de coleção `__c` (Database API):**
|
|
298
|
+
|
|
299
|
+
```groovy
|
|
300
|
+
void trigger(event, entity, player, database) {
|
|
301
|
+
// entity é um HashMap do documento __c (em before_delete, é a lista de ids)
|
|
302
|
+
if (entity.get("email") == null) {
|
|
303
|
+
throw new RuntimeException("E-mail é obrigatório"); // aborta o POST; volta como message no 500
|
|
304
|
+
}
|
|
305
|
+
entity.put("email", entity.get("email").toString().toLowerCase()); // enriquecimento normal persiste
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
> ⚠️ No modo estrito, **qualquer** exceção aborta — inclusive `TimeoutException` (estouro do `timeout`, default 5s) e erros de sandbox. Um `before_*` frágil (NPE, token bloqueado) **bloqueia todas as gravações** naquela coleção. Mantenha o script enxuto e proteja com null-checks. Apenas a **primeira** mensagem é devolvida.
|
|
310
|
+
|
|
311
|
+
**Modo B — `after_create` (rejeição com cleanup), para qualquer entidade:**
|
|
312
|
+
|
|
293
313
|
```groovy
|
|
294
314
|
void trigger(event, entity, player, database) {
|
|
295
315
|
try {
|
|
@@ -313,10 +333,53 @@ public class BusinessException extends Exception {
|
|
|
313
333
|
|
|
314
334
|
`BusinessException` centraliza o cleanup quando há múltiplas validações. Para uma validação simples, o `database.delete` + `entity.clear()` + `entity.put("message", ...)` direto basta.
|
|
315
335
|
|
|
336
|
+
### ⚠️ Disponibilidade — recurso version-dependent
|
|
337
|
+
|
|
338
|
+
O **Modo A (estrito)** depende da versão do Funifier Engine da instância: `executeStrict` foi adicionado no `DatabaseRest` em uma atualização recente e **nem toda instância já recebeu**. Em uma instância antiga, um `before_create` com `throw` numa coleção de banco **não aborta** — o documento é salvo (comporta-se como Modo B). Portanto:
|
|
339
|
+
|
|
340
|
+
- **Nunca assuma** que o Modo A está disponível. Antes de entregar uma trigger que depende dele, **sonde** a instância conectada (abaixo) ou, na dúvida, use o **Modo B** (`after_create` + delete), que funciona em qualquer versão.
|
|
341
|
+
- Ao gerar código para o usuário, **declare explicitamente** qual modo está usando e que o Modo A exige instância atualizada.
|
|
342
|
+
|
|
343
|
+
### Como detectar suporte (sonda)
|
|
344
|
+
|
|
345
|
+
Cria uma trigger descartável que sempre lança exceção, tenta um insert e observa o resultado — depois limpa tudo:
|
|
346
|
+
|
|
347
|
+
```
|
|
348
|
+
# 1. cria a trigger-sonda numa coleção de teste
|
|
349
|
+
funifier_save type=trigger payload={
|
|
350
|
+
"name": "__probe_strict_mode__",
|
|
351
|
+
"entity": "probe_strict__c",
|
|
352
|
+
"event": "before_create",
|
|
353
|
+
"active": true,
|
|
354
|
+
"script": "void trigger(event, entity, player, database){ throw new RuntimeException(\"__STRICT_PROBE_BLOCKED__\"); }"
|
|
355
|
+
}
|
|
356
|
+
# guarde o _id retornado da trigger
|
|
357
|
+
|
|
358
|
+
# 2. tenta inserir um documento na coleção de teste (passa por DatabaseRest.insert → executeStrict)
|
|
359
|
+
funifier_database action=insert collection=probe_strict__c payload={"probe": true}
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
Interpretação:
|
|
363
|
+
|
|
364
|
+
| Resultado do insert | Conclusão |
|
|
365
|
+
|---|---|
|
|
366
|
+
| Erro **HTTP 500** com `message` contendo `__STRICT_PROBE_BLOCKED__` | **Modo A suportado** — `throw` em `before_*` de banco interrompe. |
|
|
367
|
+
| Sucesso (documento criado) | **Modo A NÃO suportado** (instância antiga) — use o Modo B. |
|
|
368
|
+
|
|
369
|
+
```
|
|
370
|
+
# 3. limpeza — sempre execute, qualquer que seja o resultado
|
|
371
|
+
funifier_database action=delete collection=probe_strict__c filter={"probe": true} # remove o doc, se foi salvo
|
|
372
|
+
funifier_delete type=trigger id=<_id da trigger-sonda>
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
> Se a sonda não puder ser executada (sem permissão de escrita / ambiente de produção sensível), **assuma o Modo B** e avise o usuário que o Modo A não foi confirmado.
|
|
376
|
+
|
|
316
377
|
### Armadilhas conhecidas
|
|
317
378
|
|
|
318
|
-
- **
|
|
319
|
-
- **
|
|
379
|
+
- **Esperar que `throw` aborte fora do modo estrito** (player, action, eventos `after_*`, bulk) → o documento persiste mesmo assim. Correção: `after_create` + delete (`trigger-examples.md` Exemplo 5b).
|
|
380
|
+
- **Assumir o Modo A sem sondar** → em instância antiga o documento é salvo apesar do `throw`, e o erro passa despercebido. Correção: sondar (acima) ou usar Modo B por padrão.
|
|
381
|
+
- **`before_create` frágil em coleção de banco** → como ele agora roda em modo estrito, um erro acidental (NPE/timeout) passa a **derrubar todos os inserts** da coleção. Correção: null-check defensivo e lógica simples.
|
|
382
|
+
- **Esquecer `entity.clear()`** (modo B) → o documento rejeitado retém dados (sensíveis, no caso de signup). Correção: limpar e devolver só `message`.
|
|
320
383
|
|
|
321
384
|
---
|
|
322
385
|
|
|
@@ -106,6 +106,7 @@ A Funifier funciona como um **backend de aplicações**. Independentemente do ti
|
|
|
106
106
|
| Java Managers | `guides/java-managers.md` | Referência de managers Java | Métodos disponíveis em cada manager (PlayerManager, ActionManager, etc.) para uso em triggers, schedulers e public endpoints |
|
|
107
107
|
| Java Entities | `guides/java-entities.md` | Referência de entidades Java | Campos e tipos dos objetos (Player, Achievement, ActionLog, etc.) e mapeamento para coleções MongoDB |
|
|
108
108
|
| Java Libraries | `guides/java-libraries.md` | Bibliotecas e utilitários Java | JsonUtil, Guid, DateUtil, Unirest, EmailBuilder, Jongo — métodos e exemplos de uso |
|
|
109
|
+
| Server-side Utils | `guides/server-utils.md` | Classes utilitárias do pacote `com.funifier.engine.util` | CpfUtil, AesCrypt, BCrypt, PgpCrypt, OtpAuthUtil, DiffUtil, ExpressionUtils, MustacheUtils, StringUtil, FormatterUtil, ParserUtil, HttpUtil, UrlUtil, ExcelUtil, PaginationUtil, FileUtil — use quando precisar validar CPF, criptografar campo, renderizar template, comparar objetos, gerar Excel ou fazer HTTP em código server-side |
|
|
109
110
|
| Permission Audit | `guides/permission-audit.md` | Auditoria de permissões de API | Cross-check código↔Funifier: manifest de chamadas → missing scopes, excess tokens, danger findings; gramática de scope (SecurityFilter), keyword `database`, auth context, remediação |
|
|
110
111
|
|
|
111
112
|
---
|
|
@@ -25,7 +25,7 @@ Quem dispara o módulo (encontrado no código — `getTriggerManager().execute(.
|
|
|
25
25
|
- `AchievementManager.evaluateLevelUp` — `(level, before/after_win)` no instante do level up.
|
|
26
26
|
- `CharacterStarManager.evaluateLevelUp` — `(character_star_stats_level, before/after_win)`.
|
|
27
27
|
- `DatabaseManager.bulkInsert` — `(<collection>, before_bulk)`, `(<collection>, before_create)`, `(<collection>, after_create)` por item, `(<collection>, after_bulk)` no final.
|
|
28
|
-
- `DatabaseRest.insert/update/delete` — `(<collection>, before_create|after_create|before_update|after_update|before_delete|after_delete)`.
|
|
28
|
+
- `DatabaseRest.insert/update/delete` — `(<collection>, before_create|after_create|before_update|after_update|before_delete|after_delete)`. **Os três eventos `before_*` rodam em modo estrito** via `TriggerManager.executeStrict(...)` (não `execute`): se o script registrar qualquer exceção, a operação é abortada (§2.5.1).
|
|
29
29
|
- `CatalogManager.purchase` / `PurchaseManager.buy` — `(catalog_item, before_purchase_validation)`, `(catalog_item, before_win)`, `(catalog_item, after_win)`.
|
|
30
30
|
- `SwapManager.*` — `(swap, before/after_create|delete|win)`, `(swap, before_acquire_validation)`, `(swap_counter_offer, ...)`.
|
|
31
31
|
- `MysteryBoxManager.execute` — `(mystery_box, before_win)`, `(mystery_box, before_lose)`, `(mystery_box, before_win_reward)`, `(mystery_box, after_win|after_lose)`.
|
|
@@ -169,6 +169,34 @@ flowchart LR
|
|
|
169
169
|
Exception (catch-all) → exceptions.add; future.cancel(true); shutdownNow
|
|
170
170
|
```
|
|
171
171
|
|
|
172
|
+
### 2.5.1 `execute` vs `executeStrict` — interrupção do fluxo (modo estrito)
|
|
173
|
+
|
|
174
|
+
O `TriggerRunner.run(...)` sempre **coleta** as exceções do script na lista `exceptions` do `Map` de retorno — ele nunca propaga. Quem decide o que fazer com essa lista é o método do `TriggerManager` que foi chamado:
|
|
175
|
+
|
|
176
|
+
| Método | Quem chama | Comportamento com `exceptions` não-vazia |
|
|
177
|
+
|---|---|---|
|
|
178
|
+
| `execute(...)` | Todos os disparos (action, achievement, swap, quiz, bulk/CSV, `after_*`, etc.) | **Ignora** — apenas grava no `trigger_log` e segue o loop. A persistência **não** é afetada. |
|
|
179
|
+
| `executeStrict(...)` | **Somente** `DatabaseRest.insert/update/delete` nos eventos `before_create`/`before_update`/`before_delete` | **Aborta** — relança `exceptions.get(0)` como `FunifierException` (`Response.Status.INTERNAL_SERVER_ERROR`). |
|
|
180
|
+
|
|
181
|
+
`executeStrict` (em `TriggerManager`):
|
|
182
|
+
|
|
183
|
+
```
|
|
184
|
+
[1] Para cada trigger de (entity, event):
|
|
185
|
+
[2] result = runner.run(...) # mesma execução do execute()
|
|
186
|
+
[3] List exceptions = result.get("exceptions")
|
|
187
|
+
[4] Se exceptions != null && !exceptions.isEmpty():
|
|
188
|
+
[5] throw new FunifierException(exceptions.get(0), INTERNAL_SERVER_ERROR)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Consequências para coleções de banco (`/v3/database/{collection}`) nos eventos `before_*`:
|
|
192
|
+
|
|
193
|
+
- **Qualquer** entrada em `exceptions` aborta a operação — não só um `throw` explícito do script, mas também `TimeoutException` (estouro do `timeout`, default 5s), `SecurityException` (token bloqueado pelo `SecureASTCustomizer`) e `CompilationFailedException`. Um `before_*` frágil (NPE, erro de sandbox) **bloqueia todas as gravações** naquela coleção.
|
|
194
|
+
- A operação não acontece: o documento **não** é gravado (create/update) nem removido (delete).
|
|
195
|
+
- A resposta HTTP é gerada pelo `FunifierExceptionMapper` → **500** com corpo `CallbackMessage`: `{ "message": "<exceptions[0]>", "statusCode": 500, "data": null }` (o mapper sempre força `INTERNAL_SERVER_ERROR`, ignorando o status passado ao `FunifierException`). Apenas a **primeira** mensagem é devolvida.
|
|
196
|
+
- **Não vale para bulk:** `DatabaseManager.bulkInsert` continua usando `execute(...)` (não estrito) para `before_bulk`/`before_create` por item — inserts em lote **não** são interrompidos por `throw`.
|
|
197
|
+
|
|
198
|
+
> ⚠️ **Disponibilidade version-dependent.** `executeStrict` foi adicionado ao `DatabaseRest` em uma atualização recente do Engine e **nem toda instância já recebeu**. Em uma instância antiga, `DatabaseRest` ainda chama `execute(...)` e o `before_*` não interrompe. Antes de gerar/depender de uma trigger que aborta via `throw`, confirme o suporte com a sonda de feature em `guides/triggers-guide.md` §8.
|
|
199
|
+
|
|
172
200
|
### 2.6 Sub-pipeline — `getScript(trigger)` — wrapper de imports
|
|
173
201
|
|
|
174
202
|
`TriggerRunner.getScript` constrói um script que envelopa o `trigger.script` do usuário em uma classe `FunifierTrigger` Groovy com:
|