with one click
horse-integration
// Horse/ExpxHorse integration patterns for SimpleORM — server auto-routing, client REST driver, serialization examples.
// Horse/ExpxHorse integration patterns for SimpleORM — server auto-routing, client REST driver, serialization examples.
Validates all SimpleORM Delphi source files for Delphi 10.2 Tokyo+ compatibility. Checks inline vars, unit scoping, generics E2506, uses completeness, memory safety, .dpr structure, and conditional compilation. Run anytime to "lint" the project.
Delphi project file structure reference — .dpr vs .pas, .dproj, .res, .dfm. Templates for console and VCL projects.
CHANGELOG.md format reference and examples for the SimpleORM project.
Coding conventions and patterns for the SimpleORM Delphi project. Automatically loaded when writing or modifying Delphi code.
SimpleORM entity-to-database mapping via RTTI attributes. Complete reference for all attributes, property types, and relationship setup.
The exact iSimpleQuery interface contract that all query drivers must implement. Reference for creating or reviewing drivers.
| name | horse-integration |
| description | Horse/ExpxHorse integration patterns for SimpleORM — server auto-routing, client REST driver, serialization examples. |
| user-invocable | false |
Rules are in
.claude/rules/horse-integration.md— this skill provides architecture reference and examples.
Server Side:
Entity + iSimpleQuery → TSimpleHorseRouter.RegisterEntity<T> → 5 CRUD routes
Client Side:
TSimpleQueryHorse.New(URL) → iSimpleQuery → TSimpleDAO<T> (identical to DB code)
Shared:
TSimpleSerializer — Entity ↔ JSON via RTTI [Campo] attributes
TSimpleHorseRouter.RegisterEntity<T>(THorse, aQuery);
// Generates: GET /tablename, GET /tablename/:id, POST /tablename,
// PUT /tablename/:id, DELETE /tablename/:id
| Method | Route | Status | Response |
|---|---|---|---|
| GET | /path?skip=N&take=N | 200 | {"data": [...], "count": N} |
| GET | /path/:id | 200/404 | JSON object or {"error": "Not found"} |
| POST | /path | 201 | Created entity JSON |
| PUT | /path/:id | 200 | Updated entity JSON |
| DELETE | /path/:id | 204 | No body |
TSimpleHorseRouter.RegisterEntity<T>(THorse, LQuery)
.OnBeforeInsert(procedure(aEntity: TObject; var aContinue: Boolean) begin ... end)
.OnAfterInsert(procedure(aEntity: TObject) begin ... end)
.OnBeforeUpdate(procedure(aEntity: TObject; var aContinue: Boolean) begin ... end)
.OnBeforeDelete(procedure(aId: string; var aContinue: Boolean) begin ... end);
// Basic
LDAO := TSimpleDAO<T>.New(TSimpleQueryHorse.New('http://server:9000'));
// With Bearer token
LDAO := TSimpleDAO<T>.New(TSimpleQueryHorse.New('http://server:9000', 'my-token'));
// With custom headers
TSimpleQueryHorse(LQuery).OnBeforeRequest(
procedure(aHeaders: TStrings) begin
aHeaders.Values['X-Custom'] := 'value';
end
);
INSERT INTO ... → POST /tablenameUPDATE tablename ... → PUT /tablename/:pkDELETE FROM tablename ... → DELETE /tablename/:pkSELECT ... FROM tablename ... → GET /tablename (or /tablename/:pk)InTransaction always returns FalseTSimpleSerializer.EntityToJSON<T>(entity): TJSONObject;
TSimpleSerializer.JSONToEntity<T>(json): T;
TSimpleSerializer.EntityListToJSONArray<T>(list): TJSONArray;
TSimpleSerializer.JSONArrayToEntityList<T>(array): TObjectList<T>;
program MyServer;
{$APPTYPE CONSOLE}
uses Horse, SimpleInterface, SimpleQueryFiredac, SimpleHorseRouter,
FireDAC.Comp.Client, Entidade.MinhaEntidade;
var LConn: TFDConnection;
begin
LConn := TFDConnection.Create(nil);
// Configure connection...
TSimpleHorseRouter.RegisterEntity<TMinhaEntidade>(THorse, TSimpleQueryFiredac.New(LConn));
THorse.Listen(9000);
end.