Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Catalog · How the catalog works
Anything · Lazarus or Delphi
Random projectRandom project

horse-crud

Middleware de Auto-CRUD de alta performance para o framework Horse. Gere automaticamente rotas CRUD completas (GET, POST, PUT, DELETE) com injeção de persistência genérica de forma thread-safe e multiplataforma (Delphi & Lazarus/FPC).

View on GitHub

Member rating

No ratings yet.

Sign in to rate this project.

README

horse-crud

Middleware para o framework Horse voltado à geração automática e dinâmica de rotas CRUD (Create, Read, Update, Delete) a partir de entidades decoradas, compatível com Delphi XE7+ e Lazarus/FPC (Windows/Linux).

O horse-crud adota o padrão Repository/Store Decoupled Auto-CRUD, separando completamente o ciclo de vida HTTP do mecanismo de persistência de banco de dados. A persistência real é delegada ao desenvolvedor através de uma fábrica de repositórios, garantindo que as conexões de banco sejam seguras e isoladas por requisição (Thread-Safety).


🏛️ Padrão Repository/Store Decoupled

Ao registrar o middleware CRUD automático para uma classe de negócio (ex: TCliente), o horse-crud gerencia o ciclo HTTP e delega as operações de persistência à interface genérica IHorseRepository<T>.

A fábrica de conexões (THorseCrudRepositoryFactory<T>) permite retornar instâncias novas dos repositórios a cada requisição (thread), prevenindo deadlocks e compartilhamento de conexões (essencial ao usar drivers como FireDAC ou SQLdb do FPC).

mermaid
sequenceDiagram
    Client->>Horse: GET /clientes
    Horse->>THorseCrud: DoGet
    THorseCrud->>Factory: Solicita Repositório
    Factory-->>THorseCrud: Retorna IHorseRepository<T>
    THorseCrud->>Repository: FindAll()
    Repository-->>THorseCrud: TObjectList<T>
    THorseCrud->>THorseCrud: Serializa e libera a lista
    THorseCrud-->>Client: 200 OK (JSON Array)

⚙️ Instalação

A instalação deve ser feita utilizando o gerenciador de pacotes boss:

bash
boss4d package install horse-crud@1.0.0

📖 Exemplos Práticos

1. Declaração do Model e Interface de Repositório

Defina seu model decorado com atributos e crie a classe repositório que implementa IHorseRepository<T>:

pascal
unit Model.Cliente;

interface

uses
  {$IFNDEF FPC} Horse.CRUD {$ENDIF};

type
  {$M+}
  {$IFNDEF FPC}
  [Entity('/clientes')]
  {$ENDIF}
  TCliente = class
  private
    FId: Integer;
    FNome: string;
  published
    {$IFNDEF FPC} [Key] {$ENDIF}
    property Id: Integer read FId write FId;
    property Nome: string read FNome write FNome;
  end;
pascal
unit Repository.Cliente;

interface

uses
  SysUtils, Generics.Collections, Horse.CRUD.Interfaces, Model.Cliente;

type
  TClienteRepository = class(TInterfacedObject, IHorseRepository<TCliente>)
  public
    function FindAll: TObjectList<TCliente>;
    function Find(const AId: string): TCliente;
    procedure Insert(const AEntity: TCliente);
    procedure Update(const AEntity: TCliente);
    procedure Delete(const AId: string);
  end;

function ClienteRepositoryFactory: IHorseRepository<TCliente>;

implementation

function ClienteRepositoryFactory: IHorseRepository<TCliente>;
begin
  Result := TClienteRepository.Create;
end;

// Implementações do Repositório (FindAll, Find, Insert, Update, Delete)...

2. Registro do Auto-CRUD no Servidor Horse

No arquivo principal do servidor, configure o middleware de JSON (como o Jhonson) e registre as entidades que deseja expor automaticamente:

pascal
uses
  SysUtils,
  Horse,
  Horse.Jhonson,
  Horse.CRUD,
  Model.Cliente,
  Repository.Cliente;

begin
  // O Jhonson fará a serialização de objetos e arrays automaticamente
  THorse.Use(Jhonson());

  // Registro automático de rotas CRUD da entidade TCliente usando a fábrica portátil
  THorseCrud<TCliente>.Register(ClienteRepositoryFactory);

  THorse.Listen(9000);
end.

O horse-crud irá mapear automaticamente os seguintes endpoints:

  • GET /clientes -> Retorna todos os registros (FindAll).
  • GET /clientes/:id -> Retorna um registro por ID (Find).
  • POST /clientes -> Insere uma entidade (Insert).
  • PUT /clientes/:id -> Atualiza uma entidade (Update).
  • DELETE /clientes/:id -> Exclui um registro por ID (Delete).

⚡ Segurança de Memória e Thread-Safety

  • Thread-Safety: O repositório é instanciado na thread ativa que atende à requisição HTTP por meio da fábrica passada no Register. Após a requisição terminar, o repositório é desalocado (por ser gerenciado como interface IHorseRepository<T>).
  • Memory Leaks: O controller assume a propriedade das listas e entidades retornadas pelo repositório e as libera imediatamente depois de serializar a resposta. O repositório deve retornar instâncias independentes.

🛠️ Portabilidade e Lazarus/FPC

O horse-crud foi projetado para portabilidade total. No Lazarus/FPC:

  1. Como o FPC não oferece suporte nativo a closures/métodos anônimos, a fábrica THorseCrudRepositoryFactory<T> é mapeada como um ponteiro de função padrão (function). Você deve declarar uma função global tradicional (ex: ClienteRepositoryFactory) e passá-la como parâmetro.
  2. Como o compilador Lazarus/FPC não suporta atributos de RTTI moderna ([Entity], [Key]), você deve passar a rota e a propriedade de ID de forma explícita no momento do registro:
pascal
// No Lazarus/FPC o registro explícito das rotas e chaves é obrigatório
THorseCrud<TCliente>.Register(
  ClienteRepositoryFactory, 
  '/clientes', // Caminho explícito
  'Id'         // Nome da chave primária explícito
);

📄 Licença

Este projeto está licenciado sob a Apache License 2.0.