Services and APIs#
Services and APIs define explicit integration boundaries. Keep business policy in tables and resolver functions; services should orchestrate configured behavior.
Services#
public service InvoiceService implements Approver, Notifier {
inject repo: InvoiceRepository;
config {
retries: 3;
timeout_ms: 5000;
}
on startup {
repo.connect();
}
function approve(invoice_id: InvoiceId): bool {
return true;
}
}Service members include injected dependencies, config or configuration blocks, lifecycle hooks, and functions. Inject declarations and config properties may end with semicolons. Lifecycle hooks use on <identifier> { ... }.
Service functions#
Service functions may include an access modifier and function modifiers before function. They use typed parameters with optional default expressions. Return types may use : or ->, and may be prefixed with async. Bodies can be blocks or abstract semicolon declarations.
public service InvoiceService {
public async function refresh_invoice(invoice_id: InvoiceId): Invoice;
private inline function normalize_invoice(invoice: Invoice): Invoice {
return invoice;
}
}HTTP APIs#
API declarations group HTTP endpoints. Endpoint parameters are optional: an endpoint may omit parentheses entirely when it has no parameters. Endpoint return types use : Type; route-local functions may use : or ->.
API declarations do not take annotations or access modifiers in the current grammar. Endpoint return types use only : Type; route-local functions may use : or ->, but route-local functions do not take access modifiers.
api VendorApi {
get "/vendors" list_vendors(): Json {
return {};
}
post "/vendors" create_vendor(payload: Json): Json {
return payload;
}
head "/vendors" ping;
}Supported methods are get, post, put, delete, patch, head, and options.
Route blocks#
Route blocks group a method/path with route-local functions.
api InvoiceApi {
route post "/invoices" {
function create(input: Json) -> async Json {
return input;
}
}
}Route-local functions support function modifiers, typed parameters with defaults, : or -> return types, and block or semicolon bodies.
api InvoiceApi {
route get "/invoices" {
async function list(company_code: CompanyCode = current_company()) -> Json;
}
}Subscriptions#
Subscriptions bind code to table events.
@audited
subscribe InvoiceChanged on table Invoice after update async (
old_row: Invoice,
new_row: Invoice
) {
handle_invoice_change(old_row, new_row);
}The grammar supports after insert, after update, and after delete. Dispatch mode is currently async.