Files
jogos_matheus/endpoints/CLAUDE.md
T
2026-09-23 12:29:08 -03:00

7.3 KiB

Endpoints

Endpoints are REST WebServices written in ES5 JavaScript, executed on the Rhino engine. Each file must export a single WebService instance. Vitruvio maps incoming HTTP requests to the corresponding handler method.


vitruvio.json Registration

{
  "key": "my-endpoint",
  "name": "My Endpoint",
  "description": "What this endpoint does.",
  "language": "javascript",
  "authMode": "PUBLIC",
  "active": true,
  "source": "endpoints/my-endpoint.js"
}
  • key — kebab-case, stable. Changing it breaks any external integrations pointing to the URL.
  • authMode — one of "PUBLIC", "STATIC_TOKEN", "VITRUVIO_WS_USER_AUTH", "HTTP_BASIC_AUTH". Default to "PUBLIC".
  • active — must be true for the endpoint to be reachable. Set to false to disable without removing.

URL structure

The authMode determines the URL segment used to reach the endpoint:

authMode URL
PUBLIC /api/integration/public/{key}
STATIC_TOKEN /api/integration/tokenauth/{key}
VITRUVIO_WS_USER_AUTH /api/integration/bearerauth/{key}
HTTP_BASIC_AUTH /api/integration/bauth/{key}

STATIC_TOKEN authentication

The token can be sent in either of two ways:

  • Query parameter: _x_token_auth=<token>
  • Request header: X-WS-TOKEN-AUTH: <token>

File Structure

function WebService() {

    this.onGet = function(params) { ... }
    this.onPost = function(params) { ... }
    this.onPut = function(params) { ... }
    this.onPatch = function(params) { ... }
    this.onDelete = function(params) { ... }
}

module.exports = new WebService();
  • All methods are optional. Only implement the verbs your endpoint actually handles.
  • Remove unused verb stubs entirely — don't leave placeholder return JSON.stringify({ prop: value }) bodies in production code.
  • module.exports must be new WebService() — Vitruvio instantiates and reads from this exported object.
  • If a caller sends a verb that is not implemented in the script, Vitruvio throws EndpointMethodNotImplementedException — it is not a silent 404.

The params Object

Each handler receives a single params argument:

// GET / DELETE
params = {
    headers: {},   // request headers as key/value
    query: {}      // query string params as key/value  e.g. params.query["hub.mode"]
}

// POST / PUT / PATCH
params = {
    requestBody: '',  // raw request body string — always JSON.parse() before use
    headers: {},
    query: {}
}

Always parse the body explicitly:

this.onPost = function(params) {
    var body = JSON.parse(params.requestBody);
    // use body.*
}

Return Values

Return value HTTP response
A non-empty string 200 OK with that string as body
null, no return, or empty string "" 204 No Content
JSON.stringify(obj) 200 OK with JSON body — set Content-Type accordingly

Always return strings. Returning a raw object will not serialize correctly.

// Correct
return JSON.stringify({ status: 'ok', data: result });

// Wrong — object will not be serialized properly
return { status: 'ok' };

Error Handling

Wrap handler logic in try/catch and return a JSON error body. Don't let uncaught exceptions bubble up.

this.onPost = function(params) {
    try {
        var body = JSON.parse(params.requestBody);
        if (!body.id) throw "Missing required field: id";
        // ...
        return JSON.stringify({ success: true });
    } catch (e) {
        return JSON.stringify({ error: e.toString() });
    }
};
  • Use e.toString() when serializing caught exceptions — raw exception objects may not stringify correctly under Rhino.
  • Validate required fields early and throw descriptive messages.

DELETE Convention

By convention, DELETE requests should not receive a body and should not return data. If nothing is returned, Vitruvio responds with 204 No Content.

this.onDelete = function(params) {
    // perform deletion
    // no return needed — 204 is implied
}

Loading Scripts and Libraries

Use libService.loadScript(key) to load scripts registered in vitruvio.json. The key is the script's key field in the manifest.

// Load inside the handler — safe, always fresh
this.onPost = function(params) {
    var lib = libService.loadScript('my-lib');
    lib.doSomething();
}

// Load in the constructor — shared across all calls to this endpoint instance
function WebService() {
    var lib = libService.loadScript('my-lib');

    this.onPost = function(params) {
        lib.doSomething();
    }
}

Prefer constructor-level loading when the same library is used in multiple handlers — avoids redundant loads. Use handler-level loading when the script key is dynamic or determined at runtime.


Database Access

Load the db library and instantiate with a datasource name:

var db = libService.loadScript('db');
var banco = new db(db.VITRUVIO_DATASOURCE);  // default Vitruvio datasource
// or
var banco = new db('named-datasource');

Common operations:

// Single row
var row = banco.queryRow("SELECT NAME FROM TB_CONFIG WHERE ID = :id", { id: 1 });

// Multiple rows
var rows = banco.query("SELECT * FROM TB_ITEMS WHERE ACTIVE = 1");

// Update / Insert
banco.update("UPDATE TB_ITEMS SET STATUS = :status WHERE ID = :id", {
    status: 'DONE',
    id: itemId
});
  • Prefer named queries from queries/*.sql for reusable or complex SQL. Use inline SQL only for simple, endpoint-specific queries.
  • Use named bind parameters (:paramName) — never concatenate user input into SQL strings.

Logged User (Authenticated Modes)

For VITRUVIO_WS_USER_AUTH and HTTP_BASIC_AUTH, Vitruvio resolves the caller's identity and injects a loggedUser object into the script context. This gives the endpoint access to who is making the call.

HTTP_BASIC_AUTH additionally validates that the authenticated user belongs to the roles configured for that endpoint in Vitruvio's admin.


Common Patterns

Webhook with verification (e.g. Meta/WhatsApp)

this.onGet = function(params) {
    var mode = params.query["hub.mode"];
    var token = params.query["hub.verify_token"];
    var challenge = params.query["hub.challenge"];

    if (mode === "subscribe" && token === EXPECTED_TOKEN) {
        return challenge;
    }
    return JSON.stringify({ error: "Forbidden" });
};

Delegating to a script

this.onPost = function(params) {
    try {
        var body = JSON.parse(params.requestBody);
        var lib = libService.loadScript('my-processing-script');
        var result = lib.run(body);
        return JSON.stringify(result);
    } catch (e) {
        return JSON.stringify({ error: e.toString() });
    }
};

What NOT to do

  • Don't leave placeholder bodies (return JSON.stringify({ prop: value })) in unused verb stubs — remove the whole method instead.
  • Don't return raw exception objects — always call .toString() or wrap in a message.
  • Don't hardcode datasource names or tokens in the script — read them from vConfigService or from a DB config table.
  • Don't put heavy business logic directly in the endpoint file — delegate to a script via libService.loadScript.