tlpp-rest-endpoint-generator · v4.2.0 · 2026-06-28 · sha256 feae17447de8c34d
tlpp-rest-endpoint-generator v4.2.0A
Immutable. This exact content never changes and is served at /api/v1/blob/feae17447de8c34d.
---
name: tlpp-rest-endpoint-generator
description: "Generate TLPP REST endpoints using annotation-based routing (@Get, @Post, @Put, @Patch, @Delete) with the oRest object. Follows TOTVS API standards (TTALK) including pagination, error model, standard headers, and Swagger documentation. Use when user says 'create REST endpoint', 'TLPP REST', '@Get annotation', 'oRest endpoint'."
license: MIT
metadata:
domain: Protheus
maintainer: Customizações ADVPL/TLPP
author: Thalion Starforge
version: '4.2.0'
category: Code Generation
---
# TLPP REST Endpoint Generator
## Overview
Generate production-ready TLPP REST endpoints using the native annotation-based REST framework. TLPP REST replaces the legacy WsRESTful pattern with a simpler, annotation-driven approach. Each endpoint is a function decorated with an HTTP verb annotation and uses the global `oRest` object to handle requests and responses.
## When to Use
Use this skill when:
- Creating new REST API endpoints in TLPP
- Implementing TOTVS TTALK-compliant APIs
- Generating CRUD endpoints for Protheus entities
- Building integration APIs for external systems
- Migrating WsRESTful services to TLPP REST
---
## TLPP REST Architecture
### How It Works
1. A function is annotated with an HTTP verb annotation (e.g., `@Get("/path")`)
2. The TLPP REST Server automatically registers the route at startup via annotation scanning
3. When a request matches the route, the annotated function is invoked
4. The function uses the global `oRest` object to read the request and write the response
5. Swagger/OpenAPI documentation is generated automatically from the annotations
### Available Annotations
| Annotation | HTTP Verb | Typical Use |
| --------------------- | --------- | ---------------------------- |
| `@Get("endpoint")` | GET | Retrieve resource(s) |
| `@Post("endpoint")` | POST | Create a new resource |
| `@Put("endpoint")` | PUT | Full update of a resource |
| `@Patch("endpoint")` | PATCH | Partial update of a resource |
| `@Delete("endpoint")` | DELETE | Remove a resource |
**Annotation properties:**
- `endpoint` (required): The URI path for the route
- `description` (optional): Description shown in Swagger docs
```tlpp
// Minimal form (endpoint only)
@Get("/api/v1/customers")
// Full form (named properties)
@Get(endpoint="/api/v1/customers", description="List all customers")
```
---
## The oRest Object
The `oRest` object is a global object available inside any annotated REST function. It provides all methods for reading requests and writing responses.
### Request Methods
| Method | Returns | Description |
| ------------------------------ | --------- | -------------------------------------- |
| `oRest:getQueryRequest()` | Json | Query string parameters (`?key=value`) |
| `oRest:getBodyRequest()` | Character | Raw request body as string |
| `oRest:getPathParamsRequest()` | Json | Path parameters (e.g., `:id`) |
| `oRest:getHeaderRequest()` | Json | All request headers |
| `oRest:getClientIP()` | Character | Client IP address |
### Response Methods
| Method | Parameters | Description |
| --------------------------------------------- | -------------------- | --------------------------------------------------------- |
| `oRest:setResponse(cBody)` | Character | Set response body (concatenates if called multiple times) |
| `oRest:setStatusResponse(nCode, cBody)` | Numeric, Character | Set HTTP status code and body; returns Logical |
| `oRest:setKeyHeaderResponse(cKey, cValue)` | Character, Character | Set a response header |
| `oRest:updateKeyHeaderResponse(cKey, cValue)` | Character, Character | Update an existing response header |
| `oRest:resetResponse()` | — | Clear the response body |
| `oRest:getBodyResponse()` | — | Get current response body |
### Path Parameters
Use `:paramName` syntax in the endpoint path to define path parameters:
```tlpp
@Get("/api/v1/customers/:id")
User Function getCustomer() as Logical
Local jPathParams := oRest:getPathParamsRequest() as Json
Local cId := jPathParams["id"] as Character
// ...
Return oRest:setStatusResponse(200, cResponse)
```
---
## Bundled Reference Files
This skill uses progressive disclosure. The SKILL.md body covers the architecture, decision logic, and the generation checklist. Detailed endpoint templates, TTALK standards, and troubleshooting are in the `references/` directory — read them on demand based on the scenario:
| Reference File | When to Read | Content |
| --- | --- | --- |
| [references/tlpp-rest-endpoint-templates.md](references/tlpp-rest-endpoint-templates.md) | Generating **any CRUD endpoint** — GET list (paginated), GET by ID, POST, PUT, or DELETE | Full code templates for all 5 HTTP verbs, shared helper functions (`BuildErrorResponse`, `BuildValidationErrorResponse`) |
| [references/ttalk-standards-and-configuration.md](references/ttalk-standards-and-configuration.md) | Checking **TTALK response formats**, **HTTP status codes**, **REST server `appserver.ini` configuration**, or **debugging endpoint issues** | TTALK collection/error JSON formats, pagination query parameters, status code table, `appserver.ini` REST section, troubleshooting guide |
> Also refer to [references/sonarqube-rules-reference.md](../references/sonarqube-rules-reference.md) for the complete SonarQube rules reference shared across skills.
---
## Endpoint Generation Workflow
### Step 1: Gather Requirements
Determine from the user's request:
- Which HTTP verb(s) to generate (GET, POST, PUT, PATCH, DELETE, or full CRUD)
- The target Protheus entity/table (e.g., SA1 = Customers, SA2 = Suppliers)
- The endpoint base path (e.g., `/api/v1/customers`)
- Whether TTALK-compliant pagination is needed (collection endpoints)
### Step 2: Load Templates
Read [references/tlpp-rest-endpoint-templates.md](references/tlpp-rest-endpoint-templates.md) for the code templates matching the required verb(s). Adapt the templates to the target entity by replacing table aliases, field names, and namespace.
### Step 3: Apply TTALK Standards
For TOTVS-ecosystem APIs, read [references/ttalk-standards-and-configuration.md](references/ttalk-standards-and-configuration.md) to ensure responses follow the standard collection format, error model, and HTTP status codes.
### Step 4: Validate Against Checklist
Use the checklist below to verify the generated code covers all requirements.
---
## Endpoint Generation Checklist
### Structure
- [ ] `#include "tlpp-core.th"` is the first include
- [ ] `Namespace` declaration matches project convention
- [ ] User Function name is descriptive and uses camelCase
- [ ] HTTP verb annotation matches the operation semantics
- [ ] Endpoint path follows RESTful conventions (`/api/v1/{resource}`)
- [ ] Path parameters use `:paramName` syntax
### Request Handling
- [ ] Body parsed and validated for POST/PUT/PATCH
- [ ] Path parameters extracted via `oRest:getPathParamsRequest()`
- [ ] Query parameters extracted via `oRest:getQueryRequest()`
- [ ] Input sanitized before use in SQL queries (`FWExecStatement`)
### Response
- [ ] `Content-Type` header set to `application/json`
- [ ] Correct HTTP status code used
- [ ] Success response follows TTALK format
- [ ] Error response follows TTALK error model
- [ ] Collection endpoints include pagination (`hasNext`, `items`, `remainingRecords`)
### Data Access
- [ ] Workarea positioned correctly before read/write
- [ ] Database locks acquired with `RecLock()` and released with `MsUnlock()`
- [ ] `D_E_L_E_T_` filter always included in queries
- [ ] Branch filter (`FWxFilial`) always included
- [ ] Temporary aliases closed with `DBCloseArea()`
- [ ] SQL injection prevented (`FWExecStatement`)
### Error Handling
- [ ] `Try-Catch` wraps database operations
- [ ] Errors logged with `FWLogMsg()` including function context
- [ ] Error responses use TTALK error format
- [ ] Lock failures handled gracefully
### Security
- [ ] Authentication verified (if applicable)
- [ ] Authorization checked for the operation
- [ ] Input validated against expected types and ranges
- [ ] No sensitive data in error messages
### SonarQube Compliance
- [ ] No `RpcSetEnv` / `RpcSetType` calls in REST endpoint functions — use REST Server `PrepareIn` configuration instead
- [ ] No assignment to `__cUserID` or `cEmpAnt` — these are protected system variables
- [ ] No `StaticCall()` — use `FWLoadModel()`, `FWLoadMenuDef()`, or namespace-based calls
- [ ] No hardcoded passwords or credentials in source code
- [ ] `FWExecStatement` used for all queries with dynamic parameters
- [ ] Logging via `FWLogMsg()`, not `ConOut()`
- [ ] No `IIF()` — use `If/Else/EndIf` blocks
- [ ] `GetMV()` / `ExistBlock()` calls moved outside of loops
- [ ] No UI functions (`MsgAlert`, `MsgYesNo`, `Aviso`, `Help`) inside transaction-scoped handlers
- [ ] Includes in lowercase (e.g., `#include "totvs.ch"`)
> Refer to [references/sonarqube-rules-reference.md](../references/sonarqube-rules-reference.md) for the complete SonarQube rules reference.