Referentie

Elk gereedschap, op een plek

Deze pagina is de praktische referentie voor elk gereedschap in de sidebar van je Archestack-omgeving. Elke sectie behandelt wat het gereedschap doet, wanneer je ernaar zou grijpen, de stappen voor de meest voorkomende workflows en de valkuilen waar nieuwe gebruikers in stappen. De laatste sectie (Via-script-aanroepbare API's) documenteert het exacte oppervlak dat scripts kunnen aanroepen.

Schema Designer

Een visuele editor voor het database-schema, tabellen, kolommen, types, relaties, indexes, die naar een JSON-document auto-saved. Het schema is de bron van waarheid voor je applicatie; geen ander gereedschap ziet een kolom totdat je hem hier toevoegt en deployt.

Veelvoorkomende workflow: klik in de werkbalk op Add Table (icoonknop). Er opent een dialoog getiteld "Create New Table"; typ een naam (de hulptekst herinnert je aan "Lowercase with underscores recommended"), klik op Create. De tabel verschijnt op het canvas met een automatisch gegenereerde id SERIAL primary key. Selecteer de tabel, het rechterpaneel opent op de Columns-tab. Voeg kolommen toe vanuit het "Add column"-vak met gestippelde rand onderaan (naamveld, Type-dropdown, klik Add Column). Klik op elke kolom om uit te klappen en pas de toggles (PK, NULL, UQ), Length, en Default value aan.

Kolomtypes beschikbaar in het Type-dropdown: SERIAL, BIGSERIAL, INTEGER, BIGINT, SMALLINT, DECIMAL, NUMERIC, REAL, DOUBLE PRECISION, VARCHAR, CHAR, TEXT, BOOLEAN, DATE, TIME, TIMESTAMP, TIMESTAMPTZ, UUID, JSON, JSONB, BYTEA, INET, CIDR, MACADDR, MONEY, INTERVAL, plus geometrische en array-types. Length is alleen relevant voor VARCHAR en CHAR.

Foreign keys leven in de Relations-tab van het rechterpaneel (niet "Relationships"). Scroll naar "Add relationship": kies de FK-kolom op de huidige tabel, het relatietype (One-to-One / One-to-Many / Many-to-Many), de references-tabel, de references-kolom, en klik op Add Relationship. Elke relatie heeft On Delete en On Update-dropdowns (CASCADE / SET NULL / SET DEFAULT / RESTRICT / NO ACTION).

Auto-save: de indicator linksonder springt tussen "Auto saving..." en "Saved". Er is ook een Save-knop in de werkbalk (alleen geactiveerd wanneer er openstaande wijzigingen zijn) voor expliciet opslaan.

Andere werkbalk-knoppen: Add Group (visuele containers voor gerelateerde tabellen, eigenschappenpaneel getiteld "Group"), Add Text (vrije annotaties, eigenschappenpaneel getiteld "Text Annotation"), zoom-controls, package-filter, tabellenzoekveld.

Valkuilen: een kolom hernoemen produceert een destructief plan (drop + add), bewerk de SQL op de Generated SQL-tab van de deployment om RENAME COLUMN te gebruiken als je data wilt behouden. Een NOT NULL-kolom toevoegen aan een niet-lege tabel zonder default faalt, maak hem nullable, vul hem, en wijzig dan. De Deploy-werkbalk- knop brengt je naar een deployment-configpagina, niet direct in een deploy.

Database Deployments

Toont elke deployment met zijn status (Draft / Executing / Succeeded / Failed) en draait nieuwe. Route: /database-deployments/overview.

Knoppen rechtsboven: Refresh (lijst herladen), New Deployment (maak een nieuwe draft aan).

Vanuit Schema Designer: de groene Deploy-rakettknop in de werkbalk van Schema Designer brengt je naar /database-deployments/configure/new, een verse deployment-configuratiepagina.

Deployment-configuratiepagina: twee tabs.

  • Configuration - pre/post-deployment-scripteditors (PostgreSQL) met elk een Test Run-knop. Pre-script draait voor schema-wijzigingen; post-script daarna. Handig voor backfills, index-herbouw of staging-area-opschoning. Plus een Force Deploy (Allow Data Loss)-toggle voor destructieve operaties.
  • Generated SQL - toont de migratie die het platform heeft geproduceerd. De SQL is bewerkbaar. Een Regenerate-knop (refresh-icoon) draait de diff opnieuw als je schema-wijzigingen hebt gemaakt sinds het openen van deze pagina.

Bovenknoppen: Back, Save (slaat de configuratie op als Draft), Deploy (draait de deployment direct). Deploy klik je als laatste.

Valkuilen: deployments worden niet automatisch in een transactie verpakt, een fout halverwege laat de database in een gedeeltelijke staat achter. Voor riskante migraties, verpak je statements in BEGIN; ... COMMIT; in het pre-script. De Force Deploy-toggle slaat veiligheidschecks over; gebruik hem bewust.

Business Entities

Gecureerde views gebouwd op een master-tabel plus joins uit gerelateerde tabellen. Pages binden aan Business Entities, nooit aan ruwe tabellen. Zie Concepten, Business Entities voor het waarom.

Veelvoorkomende workflow: klik op Create. De full-page editor opent met tabs Visual, JSON, Events. Stel Entity Name, Master Table (Autocomplete), en Label Column in (de kolom waarvan de waarde een record vertegenwoordigt in pickers). Sla op, de BE genereert automatisch een lijst van native kolommen uit de master-tabel.

Joins toevoegen: scroll naar de Join Configurator-kaart en klik op Add Join. Elke join opent als een Accordion met: Join Type (INNER / LEFT / RIGHT), From Table, To Table (Autocomplete gegroepeerd op Database Tables / Third Party), From Column, To Column, optionele Type Cast-dropdowns, en een kolompicker voor welke doelkolommen aan de oppervlakte komen.

Aggregaties: schakel op een join Aggregate Mode aan. Voor elke gekozen kolom kies je dan een Aggregate Function: COUNT / SUM / AVG / MIN / MAX / COUNT DISTINCT. "Aantal openstaande contacten op dit Company" is het canonieke voorbeeld.

Run Preview: de editor heeft een Run Preview-knop (met een play-icoon) die de volledige join-configuratie uitvoert en echte rijen in een datagrid toont. Als een joinkolom leeg terugkomt, was de kolom niet aangevinkt in de kolompicker van de join (of is de relatie fout geconfigureerd).

Meerdere BEs per master-tabel: niets weerhoudt je ervan om customer (sales view) en customer (support view) op dezelfde master te hebben. Verschillende pagina's, verschillende doelgroep-passende kolommen, dezelfde onderliggende rij.

Valkuilen: gejoinde en geaggregeerde kolommen zijn read-only. Om het gejoinde label te bewerken, navigeer naar het bronrecord. Geaggregeerde kolommen worden bij elke query herberekend, prima voor honderden rijen, traag op miljoenen.

Page Editor

Configureert de runtime-UI door een Page aan een Business Entity te binden. Het platform genereert secties automatisch op basis van de BE-kolommen; vanaf daar tune je de indeling. Er is geen aparte "template-picker", elke pagina start vanuit dezelfde gegenereerde basislijn en je past hem aan.

Veelvoorkomende workflow: klik op Create. Vul Page Name, Page Route (bijv. /companies), kies de Business Entity (Autocomplete). De pagina opent in de editor met tabs Visual, Overview, Create, Entities, Events, JSON. Pas de automatisch gegenereerde indeling aan, en zet dan de Published-schakelaar in de bovenste header op AAN.

Veld-widgettypes (de Type Select op elk veld): Text, Textarea, Number, Date, Select, Checkbox, Email. Gebruik Select voor foreign-key-velden en stel de Entity-autocomplete van het veld in op de gerefereerde BE zodat gebruikers op label kiezen.

Tabs in het detailformulier: klik op Add Tab in de Visual-tab. Binnen een tab kun je een RelatedGrid-sectie toevoegen die gebonden is aan een andere BE gefilterd op de PK van het huidige record. Klassiek voorbeeld: een Company-pagina met "Contacts"- en "Deals"-tabs, elk gefilterd op company_id = current company's id.

Action-knoppen op de Header-inspector van het detailformulier. Klik op Add in de Actions-sectie. Elke action heeft Label, Icon (Save / Delete / Add / Refresh / Download / Bolt / None), Variant (Contained / Outlined / Text), Color (Primary / Secondary / Error / Success / Warning / Info), en Steps (een geordende lijst van: Save Record, Delete Record, Navigate, Business Events, Custom). Om een Business Event vanuit een knop te draaien, zet je het step-type op Business Events en kies je het event op naam.

Publiceren: de Published-schakelaar in de bovenste header is de enige publicatiebediening. AAN = de pagina verschijnt onder Published Pages in de sidebar en eindgebruikers die naar de route navigeren zien hem. UIT = concept (alleen jij in de editor ziet je wijzigingen).

Valkuilen: de automatisch gegenereerde kolommen op een verse Page spiegelen de BE, als de BE verandert (je voegt een join toe), pikt de Page geen nieuwe kolommen automatisch op. Herlaad de pagina in de editor of voeg de kolom handmatig aan de sectie toe. Er is momenteel geen "Generate PDF"-action-step-type, om een PDF aan een paginaknop te koppelen, expose de PDF via een Script Module die het REST-endpoint aanroept en gebruik een Custom-step (of roep het endpoint direct aan vanuit een Frontend Template).

Business Events

Regels die vuren op data-wijzigingen (of op een schema, of handmatig) en acties draaien wanneer condities zijn voldaan. Het "wanneer X gebeurt, doe Y"-mechanisme van het platform. Zie Concepten, Business Events voor het model.

Veelvoorkomende workflow: klik op Create. Stel Rule Name in, schakel Enabled aan. Kies Business Entity. Vink een of meer Triggers aan: BeforeCreate / BeforeUpdate / AfterCreate / AfterUpdate / BeforeDelete / OnSchedule / Manual / InitialValue. Bouw de conditieboom (AND/OR-groepen). Voeg een of meer acties toe in de FlowCanvas. Sla op.

Actietypes (RuleActionKind):

  • Execute Script - draai een C#-script. De meest flexibele actie; grijp ernaar wanneer je een veld wilt zetten, een berekening wilt doen, een API wilt aanroepen, iets custom. Het script krijgt Entity (muteer op Before*-triggers om de in-flight write te wijzigen), OldEntity, Log, Db, Modules.
  • Validate - een script dat bool teruggeeft. true betekent dat validatie faalt en het opslaan wordt geblokkeerd met het geconfigureerde foutbericht. Markeert optioneel specifieke kolommen via errorColumns.
  • Block Operation - stopt de operatie hard met een geconfigureerd bericht. Geen script.
  • Create Entity - voegt een record in een andere BE in. Veldwaarden ondersteunen template-expressies zoals {{ Entity.column_name }} en {{ now() }}.
  • Update Entity - update records in een andere BE die aan een conditiefilter voldoen. Dezelfde template-expressies.
  • Delete Entity - verwijdert records die aan een conditie voldoen. Weigert te vuren zonder een conditie (veiligheid).
  • Send Email / Send Webhook / Publish Event - in het schema gedefinieerd als toekomstige uitbreidingen; momenteel gelogd en overgeslagen.

"Een veld zetten"-patroon: er is geen aparte Set Field-action. De manier om een veld te zetten is een Execute Script op een Before*-trigger die Entity muteert. Voorbeeld: Entity.title = ((string)Entity.title)?.Trim();. Het platform persisteert de aangepaste Entity als onderdeel van de in-flight write, geen extra query, geen recursie-risico.

Run Simulation: de Simulate-tab van de trigger-editor heeft een record-picker en een Run Simulation-knop. Het platform draait je condities en acties tegen het gekozen record zonder wijzigingen te persisteren, schrijfoperaties worden uitgevoerd in een transactie die wordt teruggedraaid. Het output-paneel toont welke condities matchten en wat elke actie zou hebben gedaan. Gebruik dit om verkeerde configuraties op te vangen voordat live data ze raakt.

Template-expressies in actie-configuratie gebruiken {{ ... }}-haakjes. De daadwerkelijke tokens: {{ Entity.column }}, {{ OldEntity.column }}, {{ now() }} / {{ getdate() }}, {{ today() }}, {{ guid() }} / {{ newid() }}, {{ year() }}, {{ month() }}, {{ day() }}, {{ timestamp() }}, aggregates als {{ SUM(column) }} binnen join-contexten, en post-substitutie- rekenkunde als {{ Entity.quantity * Entity.price }}. Er is geen {{ user.email }}-token.

Conditie-operatoren: Equals, NotEquals, GreaterThan, LessThan, GreaterThanOrEqual, LessThanOrEqual, Like (= ILIKE), Contains (= ILIKE %value%), IsNull, IsNotNull, In (= ANY(...)).

Valkuilen: een trigger die hetzelfde record muteert dat hij bekijkt zal zichzelf hervuren als je Update Entity gebruikt; gebruik in plaats daarvan Before Update + Execute Script + Entity.field = .... Twee triggers op hetzelfde event vuren op prioriteitsvolgorde. Uitgeschakelde events verschijnen toch in de lijst, de Enabled-toggle staat los van de trigger-config.

Script Modules

Herbruikbare C#-scripts die runtime door Roslyn worden gecompileerd. Nemen parameters, bevragen de database via de Db-helper, geven een waarde terug. Aanroepbaar vanuit Business Events, Scheduled Events, en direct vanuit de front-end.

Veelvoorkomende workflow: klik op Create. De editor opent met tabs Edit, Parameters, Test, JSON. Geef de module een naam (PascalCase, bijv. RecalcOpenRevenue). Klik in de Parameters-tab op Add per parameter (Name, Type, Required, Default Value). Type-opties: string, int, decimal, double, bool, DateTime. Terug naar de Edit-tab, schrijf C#. IntelliSense staat aan.

Test-paneel: de Test-tab toont je parameter-invoer links en een Run-knop (PlayArrow-icoon). Klik op Run; de rechterkant toont een succes- of foutindicator, output-log, en de return-waarde (JSON-geformatteerd).

De Db-helper, zie de volledige referentie in Via-script-aanroepbare API's hieronder.

Aanroepen vanuit een Business Event: voeg een Execute Script-action toe waarvan de body de module aanroept:

await Modules.CallAsync("RecalcCompanyOpenDealValue", new Dictionary<string, object?> {
    ["company_id"] = Entity.company_id
});

Aanroepen vanuit een Scheduled Event: maak een event met de On Schedule-trigger, zet de cron, voeg een Execute Script-action toe met dezelfde Modules.CallAsync-body.

Logging: elke invocation schrijft een entry naar Event Logs met uitvoeringstijd, parameters, en resultaat (of fout).

Valkuilen: altijd await op Db-calls, vergeten compileert maar geeft een Task terug. Returns worden als object doorgegeven (niet JSON-geserialiseerd door het framework); voor front-end-consumptie, geef anonieme objecten met primitieve velden terug. Suggestion-on-commit-character is bewust uitgeschakeld in de editor; gebruik Tab om te accepteren.

Frontend Templates

Herbruikbare UI-fragmenten geschreven in TSX die de page editor in een pagina kan droppen. Handig wanneer geconfigureerde templates niet genoeg zijn, op-maat-gemaakte grafieken, ongebruikelijke indelingen, integraties met third-party-widgets.

Veelvoorkomende workflow: klik op Create, geef de template een naam, schrijf een TSX-component in de editor. De component krijgt props: record (de huidige rij wanneer ingebed in een detailformulier), refresh (data opnieuw ophalen), en een paar helpers. Sla op. Verwijs naar de template vanuit een Page Editor-veld.

Packageable: templates stromen door het Package-systeem als elk ander config-object, ze worden mee-gecascadeerd wanneer een pagina die ze gebruikt aan een package wordt toegevoegd.

Valkuilen: de TSX is sandboxed, je kunt geen willekeurige npm-packages importeren. Blijf bij React + de meegeleverde helpers.

PDF Templates

HTML + Scriban-template + een klein C#-datascript dat naar een PDF rendert (headless Chromium). Elke template is op naam aanroepbaar vanuit een script via REST of direct vanuit een knop op een Page (met een kleine adapter, zie hieronder).

Veelvoorkomende workflow: klik op + Create. De editor opent met Name- en Description-tekstvelden bovenaan, vijf tabs aan de linkerkant (HTML Template, Data Script, Settings, Params, JSON), en een altijd-aan-staand PDF Preview-paneel rechts. De Data Script- en HTML Template-tabs openen elk een Monaco-editor in de linkerhelft; de preview rendert opnieuw wanneer je opslaat (groene Update-knop rechtsboven).

Declareer parameters in de Params-tab via de + Add-knop (Name, Type, Required, Default Value). Het tab-label wordt bijgewerkt naar Params (n) met de telling. Paginaformaat / orientatie / marges / schaal / header / footer leven in de Settings-tab.

Datascript-vorm (zie PDF Invoices tutorial voor een echte):

var deal = await Db.GetAsync("deal", deal_id);
var lines = await Db.From("deal_line")
    .Where("deal_id", "=", deal_id).ToListAsync();

return new {
    InvoiceNumber = $"INV-{deal.id:D6}",
    Lines = lines.Select(l => new { l.description, l.quantity })
};

HTML-template-vorm (Scriban, vergelijkbaar met Liquid/Handlebars):

<h1>{{ InvoiceNumber }}</h1>
<table>
  {{ for line in Lines }}
  <tr><td>{{ line.description }}</td><td>{{ line.quantity }}</td></tr>
  {{ end }}
</table>

Preview-paneel: altijd zichtbaar aan de rechterkant van de editor. Rendert opnieuw wanneer je opslaat (groene Update-knop). Bevat een thumbnail-kolom voor PDFs met meerdere pagina's en een ingebouwde viewer-werkbalk (zoom, draaien, downloaden, printen). De icoonknoppen rechtsboven in de editor schakelen de zichtbaarheid van het preview-paneel en full-screen-editing aan/uit.

Aanroepen vanuit buiten de editor:

  • POST /api/v1/pdf-templates/{id}/preview - rendert op ID, geeft application/pdf terug. Gebruikt door het preview-paneel van de editor.
  • POST /api/v1/pdf-templates/generate/{name} - rendert op naam, geeft application/pdf terug.
  • POST /api/v1/pdf-templates/generate/{name}/base64 - hetzelfde maar geeft { "data": "<base64>" } terug.

Geef parameterwaarden mee in de JSON-body. Auth is de standaard Bearer-token.

Trial-beperking: zowel het generate-endpoint als het {id}/preview-endpoint (gebruikt door het preview-paneel van de editor) geven 403 terug in trial-modus, PDF-rendering is volledig afgeschermd. Je kunt nog steeds de template schrijven (data script, HTML, settings, parameters) en opslaan; je ziet alleen geen gerenderde PDF totdat je op een betaalde omgeving zit.

Note over via-script-aanroepbare rendering: de C#-scriptcontext exposeert geen Pdf-global. Om vandaag vanuit een Script Module een PDF te renderen, roep je het generate REST-endpoint aan via HttpClient. (De autocomplete van de scripteditor adverteert Pdf.RenderAsync voor voorwaartse compatibiliteit; de runtime-binding is nog niet bedraad.)

Valkuilen: Scriban escapet HTML standaard. Paginabreuken zijn CSS-gestuurd, page-break-before: always op een sectie. Lettertypes beschikbaar op de rendering-server zijn beperkt tot systeemlettertypes plus de Noto- en Liberation-families, embed je eigen via base64 @font-face als je een merklettertype nodig hebt.

Scheduled Events

Hetzelfde Event Trigger-systeem als Business Events, met de On Schedule-trigger aangevinkt. Gebruik het voor nachtelijke herberekeningen, weekelijkse digests, periodieke opschoning, maandelijkse rapporten.

Veelvoorkomende workflow: maak een Business Event met de On Schedule- trigger (in plaats van, of naast, de data-wijzigings-triggers). Configureer de cron-expressie. Voeg een Execute Script-action toe waarvan de body een Script Module aanroept via Modules.CallAsync(...).

Cron-expressies: Quartz-stijl 6 of 7 velden, zie Concepten, Scheduled Events voor veelvoorkomende patronen. Tijden zijn servertijd (UTC op de productie-stack).

Valkuilen: een langlopende job die zijn cron-interval overschrijdt stapelt niet, Quartz zal geen tweede instantie van dezelfde job tegelijk vuren, de tweede tick wordt overgeslagen. Mislukte runs proberen niet automatisch opnieuw; bouw retry in het script in.

Packages

Exporteerbare bundels van configuratie-objecten (BEs, pages, events, scripts, templates, schema) met cascading-afhankelijkheden. Een Page aan een package toevoegen trekt automatisch alles mee waar die pagina naar verwijst.

Veelvoorkomende workflow (export): klik op Create, geef de package een naam en versie. Voeg de top-level-objecten toe die je belangrijk vindt, meestal een handjevol pagina's. Open het linked-items-paneel om de gecascadeerde lijst te zien (wat de package daadwerkelijk gaat bevatten). Vink uit wat je wilt weglaten. Beslis of je data wilt meenemen (toggle bij export). Klik op Export, je krijgt een ZIP.

Veelvoorkomende workflow (import): open op de bestemmingsomgeving Packages, klik op Import, upload de ZIP. Het platform toont wat zal worden toegevoegd of bijgewerkt. Schema-deltas worden niet automatisch toegepast, als de package verwijst naar een kolom die niet bestaat op de bestemming, faalt de import.

Valkuilen: identifiers zijn op naam, niet op numeriek ID. Een BE genaamd "customer" op de bron bindt aan een BE genaamd "customer" op de bestemming, hernoem een van beide en de link breekt.

Third-Party Data Connections

Verbindingen met externe databases (Postgres, SQL Server, MySQL, andere) die tabellen volgens een schema importeren. Geimporteerde tabellen gedragen zich als native tabellen, ze verschijnen in Schema Designer en kunnen worden gerefereerd door Business Entities, Pages en Scripts.

Veelvoorkomende workflow: maak een verbinding aan (connection string, test, opslaan). Toon beschikbare remote tabellen; kies welke te importeren. Stel voor elke geimporteerde tabel sync-mode (Full / Delta) en sync-trigger (cron / handmatig / vast interval) in.

Gespiegeld, niet gefederalisseerd: de geimporteerde data leeft in je eigen omnicore-db. Reads zijn snel (lokale Postgres). Trade-off: staleness tussen syncs.

App-managed kolommen: markeer sommige kolommen als "managed by Archestack", ze worden niet overschreven door toekomstige syncs. Handig wanneer je vendor-data wilt annoteren met je eigen statusvlaggen.

Valkuilen: de eerste sync van een grote tabel kan even duren. Delta-syncs vereisen een kolom die de connector als watermark kan gebruiken, meestal een modified_at-timestamp.

AI Builder

Een begeleide wizard waarin je een feature in natuurlijke taal beschrijft en de wizard een bouwplan genereert, schema-toevoegingen, BE-wijzigingen, pages, events, dat je regel voor regel reviewt en toepast. Het genereren van het plan wordt gedaan door een externe LLM van je keuze (Claude, ChatGPT, Gemini), de wizard stelt een zelfstandige prompt op om in te plakken en accepteert de JSON-response terug. Er is geen in-app chat-assistent meer.

Veelvoorkomende workflow: beschrijf de feature in 1-3 zinnen ("voeg ondersteuning toe voor service-afspraken, elke heeft een datum, een klant, een voertuig en een status"). Klik op Generate prompt, plak hem in je externe LLM, plak de JSON-response terug in de Import-stap, klik op Review. Vink uit wat je niet wilt. Klik op Apply.

Werkt goed voor: CRUD-vormige features, simpele automatiseringen, rechttoe- rechtaan-uitbreidingen op bestaande entities.

Minder goed voor: niet-vanzelfsprekende businessregels, complexe meerstaps-workflows. Het plan is een startpunt, review het als de PR van een junior dev.

Valkuilen: apply is onomkeerbaar. Voor riskante features, maak eerst een back-up (of pas toe op een trial-omgeving, evalueer, en bouw dan opnieuw op productie vanuit de resulterende Package).

Object Browser

Ruwe view op elke native en geimporteerde tabel, voeg rijen direct toe, bewerk, verwijder. Bevat een CSV-import voor bulk-laden.

Wanneer ernaar grijpen:

  • Bulk-laden van referentiedata voordat er pagina's bestaan (landen, valuta, status-enums).
  • Debugging, zien wat er werkelijk in een tabel zit wanneer een pagina zich vreemd gedraagt.
  • Snelle admin-bewerkingen op data die nog niet via een Page is geexposed.
  • CSV-import: kies een tabel, upload een bestand, koppel kolommen aan velden, preview, commit.

Valkuilen: Object Browser vuurt wel Business Events af (hij gaat door hetzelfde EntityService-schrijfpad als de front-end). De uitzondering is directe SQL via Database Deployments, dat omzeilt alles.

Dependency Graph

Een alleen-lezen kaart van hoe de configuratie-objecten in je omgeving naar elkaar verwijzen. Acht resourcetypes verschijnen als nodes, gekleurd per type: Business Entities, Pages, Event Triggers, Script Modules, PDF Templates, Frontend Templates, Scheduled Events en Packages. Een edge tussen twee nodes betekent dat de ene resource van de andere afhangt. Grijp ernaar om de vragen te beantwoorden "wat breekt er als ik dit verwijder?" en "is hier iets ongebruikt?".

Wat een edge betekent: een Page gekoppeld aan een Business Entity, een Event Trigger geregistreerd op een Business Entity, een Page-actiestap die een Event Trigger afvuurt, een script dat een andere Script Module aanroept via Modules.CallAsync("Name"), een script dat een PDF Template rendert, een Scheduled Event die een Event Trigger afvuurt, of een Package dat een resource bevat. Het is een design-time view, het weerspiegelt wat je configuratie aan elkaar knoopt, niet live runtime-verkeer.

Twee soorten problemen worden visueel uitgelicht:

  • Loose ends (orphans) - nodes waar niets naar verwijst en die zelf nergens naar verwijzen. Ze worden verzameld in een rood omrande "Loose ends"-band onderaan het canvas. Een Script Module die niemand aanroept; een Page die nergens aan gekoppeld is.
  • Dangling references - getekend als rode stippellijn-edges. De verwijzing bestaat in de configuratie maar het doel is niet te vinden, bijvoorbeeld een Page-actiestap die nog naar een verwijderde Event Trigger wijst, of een script dat een Script Module aanroept met een naam die niet meer bestaat.

Veelvoorkomende workflow: open Dependency Graph vanuit de Tools-sectie van de sidebar. Het linkerpaneel heeft een naamzoekveld, een Layout-keuze (Left to right, Top to bottom, By type, Force-directed), de toggles Group by package, Show loose ends en Show edges, en een checklist per type. Klik op een node om focusmodus te activeren: die node en zijn directe buren blijven helder terwijl de rest van de graph vervaagt, zodat je precies kunt traceren wat een resource raakt. Klik op de canvas-achtergrond om de focus te wissen. Elke node heeft een kleine knop die de resource in een nieuw tabblad opent, recht naar de editor ervan. De statsregel bovenaan toont het aantal nodes, edges, orphans en dangling references.

Group by package: omkadert de leden van elk package in een gelabelde stippellijn-box, zodat je een package als geheel ziet en opmerkt welke resources het via cascade heeft binnengehaald.

Valkuilen: de graph wordt op aanvraag opgebouwd uit de huidige staat, gebruik de refresh-knop nadat je elders resources hebt gewijzigd. Script-afgeleide edges worden gevonden door scriptlichamen te scannen op de letterlijke Modules.CallAsync("Name")-aanroepvorm, een module die via een berekende naam wordt aangeroepen toont geen edge. Een dangling reference is altijd het oplossen waard; een orphan vaak niet, een gloednieuwe Script Module geldt als orphan totdat iets hem aanroept.

Event Logs

Het audit-spoor voor alles wat het platform heeft gedraaid, Business Events, Script Modules, Scheduled Events, third-party-syncs.

Veelvoorkomende workflow: open Event Logs, zet Status op Failed, klik op een entry. Het detailpaneel toont de payload (de staat van het record op het moment, parameters meegegeven), de exception met stack trace, en timing.

Logs en Charts: de pagina heeft twee tabbladen die één filterrij delen. Logs is de tabel hierboven. Charts is een operationeel dashboard over hetzelfde filter: volume in de tijd gestapeld op status, een trend van de succesratio, een uitsplitsing per source, de meest falende en de traagste events, de gemiddelde en maximale duur in de tijd, een uitsplitsing per trigger-type, en een heatmap van dag van de week tegen uur van de dag, met de belangrijkste totalen bovenaan. Beide tabbladen delen een Van / Tot datumbereik (met presets Laatste 1u / 24u / 7d); het Charts-tabblad kiest automatisch een passende tijdsbucket voor het bereik en kan met een interval vernieuwen voor live monitoring.

Real-time meldingen: het belicoontje in de bovenste balk van de adminapp laat ongelezen fouten zien via SignalR.

Valkuilen: de log kan groot worden. Oude entries blijven standaard voor altijd bewaard; als schijfruimte een zorg is, zet een Scheduled Event op die entries ouder dan N dagen opruimt.

User Management

Maak, nodig uit en beheer gebruikers; wijs realm-rollen toe. Wraps de Keycloak admin REST API.

Rollen:

  • admin - alles; kan alle Business Units, gebruikers, rollen en system settings beheren.
  • owner - beheert eigen Business Units, kan administratie- en runtime-pagina's bewerken.
  • editor - kan runtime-pagina's bekijken en bewerken, maar geen schema/BE/event-configuratie wijzigen.
  • user - alleen-lezen op runtime-pagina's.

Valkuilen: een gebruiker midden in een sessie degraderen vanaf admin schopt hen er niet uit, de wijziging wordt actief bij de volgende token-refresh (meestal binnen een minuut).

Business Units

Door Keycloak ondersteunde groepen die zichtbaarheid op individuele resources afschermen. Zie Concepten, Business Units voor het model.

Veelvoorkomende workflow: maak een BU aan. Nodig leden uit via e-mail en kies de rol. Wijs resources toe door naar elke BE / Page / Trigger te gaan of via het linked-items-paneel van de BU.

Cascading-toewijzingen: wanneer je een Page aan een BU toewijst, cascadet de toewijzing naar de BE waaraan de pagina bindt.

Valkuilen: de actieve BU van een gebruiker wordt gezet in de BU-switcher in de bovenbalk en blijft in localStorage. Nieuwe gebruikers gaan standaard naar hun eerste BU; als een lijstpagina verdacht leeg is, controleer welke BU actief is.

Database Backups

Nachtelijke pg_dump van alle drie de databases. Handmatige trigger / upload / restore vanuit de UI.

Veelvoorkomende workflow: Trigger now, Download, Upload, Restore. Schema staat standaard op nachtelijks om 03:00 UTC.

Trial-beperking: Backups zijn uitgeschakeld in de trial-omgeving.

Branding

Wijzig de weergavenaam van de app, het logo (licht + donker) en het primaire kleurenschema, runtime toegepast, geen rebuild.

Veelvoorkomende workflow: stel de app-naam in, upload een licht logo en een donker logo (PNG/JPG/SVG, maximaal 10 MB), kies een primaire merkkleur. Sla op. Refresh de browser.

Valkuilen: de favicon wordt niet overschreven door Branding, die zit in de SPA gebundeld.

Translations

Key/value-editor voor de UI-strings van de app. Voeg nieuwe locales toe, overschrijf default labels per klant.

Veelvoorkomende workflow: kies een locale, zoek naar een key, typ een nieuwe waarde, sla op. Refresh de adminapp.

Valkuilen: vertalingen worden eenmaal per sessie geladen; gebruikers op een verouderde tab zien geen wijzigingen totdat ze refreshen. Sommige labels (kolomkoppen van BEs) komen uit de BE-config, niet uit translations.


Via-script-aanroepbare API's

Het exacte oppervlak dat scripts kunnen aanroepen. Geverifieerd tegen de source, elke methode hieronder bestaat daadwerkelijk.

Globals

Elk script krijgt deze top-level-variabelen (geen andere namen bestaan in script-scope):

  • Entity - dynamic ExpandoObject. Huidig record. Toegang tot velden met Entity.column_name. Entity muteren in een Before*-trigger persisteert de wijzigingen als onderdeel van de in-flight write.
  • OldEntity - dynamic ExpandoObject. Vorig record (update- + delete-triggers). Read-only.
  • Log - ILogger. Log.LogInformation("..."), Log.LogWarning(...), Log.LogError(...). Schrijft naar serverlogs en de Event Log-entry.
  • Db - DbHelper. Database-toegang (zie hieronder).
  • Modules - ModulesHelper. Roep andere Script Modules aan: await Modules.CallAsync("ModuleName", new Dictionary<string, object?> { ["param"] = value }). Geeft Task<object?> terug.
  • Pdf - ScriptPdfHelper. Render een opgeslagen PDF Template op naam: await Pdf.GenerateAsync("invoice", new Dictionary<string, string> { ["id"] = Entity.id.ToString() }) geeft byte[] terug; await Pdf.GenerateBase64Async(...) geeft dezelfde payload base64-gecodeerd terug. Parameters worden doorgegeven aan het datascript van de template als string-getypte locals.

Er is geen User, Http, Email, Templates, of enige andere global.

Db - single-row + write-methodes

Alle async, alle op het top-level Db-object:

  • await Db.GetAsync(string table, object id) - haal een rij op via primary key. Geeft dynamic? terug (of null als niet gevonden).
  • await Db.CreateAsync(string table, object values) - insert. values kan een anoniem object zijn of een Dictionary<string, object?>. Vuurt Before/After Create-triggers. Geeft int terug (het nieuwe ID).
  • await Db.UpdateAsync(string table, object id, object values) - update op PK. Vuurt Before/After Update-triggers.
  • await Db.DeleteAsync(string table, object id) - delete op PK. Vuurt Before Delete-trigger.

Db - fluent query builder

Start met Db.From(table). Keten filters, dan een terminal:

  • .Where(string column, string op, object? value = null) - voeg een WHERE-clausule toe. Operatoren: =, != / <>, >, >=, <, <=, LIKE, ILIKE, IN, IS NULL, IS NOT NULL. Keten meerdere .Where(...)-calls voor AND.
  • .OrderBy(string column, bool desc = false) - stel ORDER BY in. Slechts een per query toegestaan.
  • .Limit(int limit) - maximum rijen. Default is 1000.

Terminals (elk draait de query):

  • await ...ToListAsync() - geeft List<dynamic> terug.
  • await ...FirstAsync() - geeft dynamic? terug (eerste match of null). Zet de limit tijdelijk op 1.
  • await ...CountAsync() - geeft int terug.

Er is geen SumAsync, MaxAsync, FirstOrDefaultAsync, of SingleAsync. Voor aggregaties, haal op met ToListAsync() en reduceer in C#.

Uitgewerkt voorbeeld

// Get a row by ID, query a list, calculate a sum, update.
var order = await Db.GetAsync("orders", 42);
if (order == null) return false;

var items = await Db.From("order_items")
    .Where("order_id", "=", order.id)
    .OrderBy("id")
    .ToListAsync();

decimal totalAmount = 0;
foreach (var item in items) {
    totalAmount += (decimal)(item.amount ?? 0);
}

await Db.UpdateAsync("orders", 42, new {
    total = totalAmount,
    updated_at = DateTime.UtcNow
});

return true;

Simulation mode

Tijdens trigger-simulatie (de Run Simulation-knop op een Business Event) zet het platform Db.SimulationMode = true. Alle schrijfoperaties (CreateAsync, UpdateAsync, DeleteAsync) draaien binnen een PostgreSQL-transactie die aan het einde altijd wordt teruggedraaid. Leesoperaties werken normaal. Dit is wat Run Simulation veilig maakt om tegen echte data te gebruiken.

Modules

  • await Modules.CallAsync(string moduleName, Dictionary<string, object?>? parameters = null) - roep een andere Script Module aan op naam. Parameters worden getypte variabelen in het script van de aangeroepen module. Geeft Task<object?> terug (wat de module ook teruggaf).

Template-expressies (Business Event-actions)

Actie-configuratie gebruikt {{ ... }}-haakjes. De volledige lijst geldige tokens:

  • {{ Entity.column_name }} / {{ Entity.id }}
  • {{ OldEntity.column_name }}
  • {{ now() }} / {{ getdate() }} - ISO 8601 UTC-datetime
  • {{ today() }} - datum-string
  • {{ guid() }} / {{ newid() }} - verse GUID
  • {{ year() }}, {{ month() }}, {{ day() }}, {{ timestamp() }} - Unix-seconden
  • {{ empty() }}, {{ null() }}
  • Aggregates binnen een join-context: {{ SUM(column) }}, {{ AVG() }}, {{ COUNT() }}, {{ MIN() }}, {{ MAX() }}
  • Rekenkunde: {{ Entity.quantity * Entity.price }} - geevalueerd na substitutie via DataTable.Compute()

Er is geen {{ user.email }} of andere user-scoped token.