feat: implement full scrip action engine with real executors

- SendEmail: real nodemailer transport with SMTP config, dynamic recipient resolution
  (static + ticket creator/owner lookup), Handlebars template support
- Webhook: HTTP POST/any method with configurable headers and JSON body
- FetchMetadata: external HTTP fetch, Handlebars URL/body templating,
  auto-adds result as comment/correspondence on ticket
- RunScript: arbitrary async JS execution with helpers (addComment,
  createTransaction, updateTicket, touchTicket), ticket context, and
  Drizzle ORM access
- SetCustomField: lookup by id/key/name, clear+insert value, record
  CustomFieldChange transaction
- CreateTransaction: insert arbitrary transaction record
- Add OnCustomFieldChange condition
- Pass condition_config to evaluator in engine

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Gjermund Høsøien Wiggen
2026-06-09 10:42:59 +02:00
parent 9e884546f2
commit e960df61ad
4 changed files with 371 additions and 15 deletions

View File

@@ -4,7 +4,7 @@ import type { Transaction } from '../models/transaction.ts';
import { tickets, queues, scrips, lifecycles, customFieldValues, customFields } from '../db/schema.ts';
import { eq, asc, inArray } from 'drizzle-orm';
import { getConditionEvaluator } from './conditions.ts';
import type { ConditionEvaluateContext } from './conditions.ts';
import type { ConditionConfig, ConditionEvaluateContext } from './conditions.ts';
import { getActionExecutor } from './actions.ts';
import type { ActionPayload } from './actions.ts';
import { TemplateRenderer } from './templates.ts';
@@ -103,7 +103,12 @@ export class ScripEngine {
continue;
}
if (!evaluator.evaluate(ticketRecord as unknown as Ticket, transactions, conditionContext)) {
if (!evaluator.evaluate(
ticketRecord as unknown as Ticket,
transactions,
conditionContext,
scrip.condition_config as ConditionConfig,
)) {
continue;
}