{"id":19594499,"url":"https://github.com/salpreh/crudhex","last_synced_at":"2026-02-14T11:36:42.938Z","repository":{"id":54422587,"uuid":"520529306","full_name":"salpreh/crudhex","owner":"salpreh","description":"Java/Spring CRUD generation","archived":false,"fork":false,"pushed_at":"2023-02-12T20:27:42.000Z","size":340,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-07T07:26:19.420Z","etag":null,"topics":["codegeneration","crud","java","spring"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/salpreh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-08-02T14:22:32.000Z","updated_at":"2023-08-29T19:38:26.000Z","dependencies_parsed_at":"2024-11-11T08:44:01.128Z","dependency_job_id":"1559fd6c-7e39-4bf3-8e72-c2c79928f8e9","html_url":"https://github.com/salpreh/crudhex","commit_stats":{"total_commits":199,"total_committers":1,"mean_commits":199.0,"dds":0.0,"last_synced_commit":"9340a2d23bccba74606eb8a294c864816e39d280"},"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"purl":"pkg:github/salpreh/crudhex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salpreh%2Fcrudhex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salpreh%2Fcrudhex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salpreh%2Fcrudhex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salpreh%2Fcrudhex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/salpreh","download_url":"https://codeload.github.com/salpreh/crudhex/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salpreh%2Fcrudhex/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29443452,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-14T10:51:12.367Z","status":"ssl_error","status_checked_at":"2026-02-14T10:50:52.088Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["codegeneration","crud","java","spring"],"created_at":"2024-11-11T08:43:45.146Z","updated_at":"2026-02-14T11:36:42.920Z","avatar_url":"https://github.com/salpreh.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Crudhex\n\n[![PyPI version](https://badge.fury.io/py/crudhex.svg)](https://badge.fury.io/py/crudhex)\n\n⚠️ **Warn: Beta development stage**\n\n---\n\nCLI tool to generate Java CRUD classes from a spec file. The target for this code generation is a Hexagonal architecture.\n\n\n## Motivation\nAdding CRUD operation in a hexagonal project is quite a pain. You can take shortcuts that can be totally legit in cases of just CRUD operations, but most cases if there is already a rich domain/application layer for other use cases CRUD shortcuts can break the consistency of the project.\n\nThe target of this CLI is to ease ~~my life~~ and try to give a general solution to CRUD generations in Hexagonal architecture. There are some customizations you can make, but some aspects for now are closed to customization for now.\n\n## Getting started\n\n### Project config file\nProject config file is used to know where things should go in the project. Usually contains a path to the sources folder (`src/main/java` in regular maven projects) and packages where things are located within that source folder.\nHere is a basic example:\n```yaml\nsrc: src/main/java # General sources for single module apps, default to src/main/java (maven project)\n\ndomain-models-pkg: com.salpreh.baseapi.domain.models # domain models package\ndomain-commands-pkg: com.salpreh.baseapi.domain.models.commands # domain commands package\ndomain-in-ports-pkg: com.salpreh.baseapi.domain.ports.application # domain ports (in/driving/application)\ndomain-out-ports-pkg: com.salpreh.baseapi.domain.ports.infrastructure # domain ports (out/driven/infrastructure)\ndomain-use-cases-pkg: com.salpreh.baseapi.domain.services # domain use cases implementation\ndomain-exceptions-pkg: com.salpreh.baseapi.domain.exceptions # domain exceptions\n\ndb-adapters-pkg: com.salpreh.baseapi.adapters.infrastructure.db.adapters # db adapters (port implementations)\ndb-models-pkg: com.salpreh.baseapi.adapters.infrastructure.db.models # db entities package\ndb-repositories-pkg: com.salpreh.baseapi.adapters.infrastructure.db.repositories # db repositories package\n\ndb-mapper-class: com.salpreh.baseapi.adapters.infrastructure.db.mappers.DbMapper # mapper class to map db adapter entities to domain models. Needed if no mapper option specified when running command (optional)\ndb-mapper-pkg: com.salpreh.baseapi.adapters.infrastructure.db.mappers # db mapper package.Needed when mapper option specified when running command (optional)\n\nrest-models-pkg: com.salpreh.baseapi.application.api.models # rest models package\nrest-controllers-pkg: com.salpreh.baseapi.application.api.controllers # rest controllers package\nrest-exception-handler-pkg: com.salpreh.baseapi.application.api.config # rest exception handler package\n\nrest-mapper-class: com.salpreh.baseapi.application.api.controllers.mappers.ApiMapper # mapper class to map domain models to api models. Needed if no mapper option specified when running command (optional)\nrest-mapper-pkg: com.salpreh.baseapi.application.api.controllers.mappers # api mapper package. Needed when mapper option specified when running command (optional)\n```\n\nIn case of multimodule project you will have to specify `src` path to each module (domain, rest adapter and db adapter). \n```yaml\n# Source folder for each module\ndomain-src: domain/src/main/java # Domain java sources\ndb-adapter-src: infrastructure/datasource-adapter/src/main/java # DB adapter java sources\nrest-adapter-src: application/web/src/main/java # Rest adapter java sources\n\n# Packages config as previous example\n```\nMore examples of config can be found in (`doc/examples/config`).\n\nThe default name for this config file is `.crudhex-conf.yaml`, located in the root of the project (you can provide the path to config file by cli options, so you can place it anywhere you want)\n\n### Spec file\nThis is the file where you specify the crud model. Class name, attributes and some metadata about DB structure (relations, PK field, column name alias, etc).\n\nAn example of spec file:\n```yaml\nPerson: # Model name\n  .meta:\n    table-name: persons # OPTIONAL: Table name for entity\n  id: # Field name\n    type: Long\n    id: sequence # PK marker. This field will be the primary key for the entity. \n                 # As value, you specify generation strategy available in JPA with lower case.\n  name: String # Field name and type\n  birthPlanet: # Field name\n    type: Planet\n    column: birth_planet # OPTIONAL: Column name alias\n    relation: # DB relation meta data in case of FK\n      type: many-to-one # Relation type\n      join-column: birth_planet_id # Join column for relation\n  affiliations:\n    type: Faction\n    relation:\n      type: many-to-many # In case of many-to-many we have a couple of more meta about DB setup\n      join-table: person_affiliation \n      join-column: person_id\n      inverse-join-column: faction_id\n  backup:\n    type: Person\n    relation:\n      type: one-to-one\n      join-column: backup_id\n  backing:\n    type: Person\n    relation:\n      type: one-to-one\n      mapped-by: backup # Mapping attribute for non-owning side of relation\n\n# Here another model\nPlanet:\n  .meta:\n    table-name: planets\n  id:\n    type: Long\n    id: # You can specify the generation strategy as map to use additional options. In this case we are giving a sequence name\n      type: sequence \n      sequence: planet_pk_gen\n  name: # Field name and type also can be specified as map to add column name metadata\n    type: String \n    column: original_name\n  affiliation:\n    type: Faction\n    relation:\n      type: many-to-one\n      join-column: affiliation_id\n  relevantPersons:\n    type: Person\n    relation:\n      type: one-to-many\n      mapped-by: birthPlanet\n\n```\n\nSnippet config comments provide an overview of each relevant section in config. I'll dig further in config details in a dedicated section.\nFor now, you can find some additional examples in `doc/examples/spec`.\n\n### Installation\n\nPackage is published in Pypi public repositories. You can use [pip]() (or another convenient python dependency manager) to install the package:\n```shell\npip install crudhex\n```\n\nOnce installed you should be able to use it as CLI tool:\n```shell\ncrudhex --help\n```\n\n### Usage\nYou can use the `--help` option to see all available options:\n```shell\ncrudhex --help\n```\n\nTo generate the code you need to locate the shell in the root of the project and run the command:\n```shell\ncrudhex -m mapstruct spec/crudhex.yaml\n```\nHere we are specifying mapstruct as mapper library and the path to the spec file. By default, will use the config file `.crudhex-conf.yaml` located in the root of the project.\n\nIf you want to use a different config file, you can specify it with the `-c` option:\n```shell\ncrudhex -c .doc/config/cruhex-config.yaml spec/crudhex.yaml\n```\n\n## Details\n### Spec file options\n#### Model\nFirst level keys in spec file are the **model names**. Each model name is followed by a map with the model fields/attributes. \n```yaml\nPerson: # Model name\n  id: Long # Field name\n  name: String # Field name\n  surname:  # Field name\n    type: String\n    column: last_name\n  birthPlanet: # Field name with relation data\n    type: Planet\n    column: birth_planet\n    relation:\n      type: many-to-one\n      join-column: birth_planet_id\n```\nThere is a special key inside the model map called `.meta` that contains metadata about the model.\n\n```yaml\nPerson: # Model name\n  .meta:\n    table-name: persons # Table name for entity\n  id: Long # Field name\n  name: String # Field name\n# More fields\n```\nCurrent supported options in meta are:\n- `table-name`: Table name for the entity. If not specified, will use the model name as table name.\n\n#### Field\nFields in the model have many options depending on the type of field. The most basic field spec is just the field name and the type:\n```yaml\nPerson: # Model name\n  id: Long # Field name\n  name: String # Field name\n```\n\nThis structure can be expanded to specify additional options for the field. \n```yaml\nPerson: # Model name\n  name: # Field name\n    type: String # Field type\n    column: original_name # Column name alias\n    \n  id:  # Field name\n    type: Long # Field type\n    id:\n      type: sequence # PK generation strategy\n      sequence: person_pk_gen # Sequence name\n    \n  birthPlanet: # Field name\n    type: Planet # Field type\n    column: birth_planet # Column name alias\n    relation: # DB relation metadata\n      type: many-to-one\n      join-column: birth_planet_id\n```\n\nOptions available are:\n- `type`: Field type. Can contain a primitive, java type, custom class or another model.\n- `column`: Column name alias. If not specified, will use the field name as column name.\n- `id`: Marks the field as Primary key in DB. Also contains metadata for PK generation strategy. \n- `relation`: Contains metadata for DB relations.\n\nExpanding on `type` options available here is an example with each one of the mentioned options:\n```yaml\nPerson:\n  id: \n    type: UUID # Java type\n    id: auto\n  age: int # Primitive type\n  birthPlanet: \n    type: Planet # Model class\n    relation:\n      type: many-to-one\n      join-column: birth_planet_id\n  race: com.salpreh.baseapi.domain.models.RaceType # Custom class\n```\nFor custom classes full package name is required (`race` field in example). For java types all jdk 11 classes are supported, in case you need a not supported type you can use full package name to refer to it. There is a list of supported types in [crudhex/domain/services/data/class_type_data.py](https://github.com/salpreh/crudhex/tree/master/crudhex/domain/services/data/class_type_data.py).\n\nFor regular fields most common option is to use type directly as value (first example), or a map with type and column name alias (second example). We will dig into `id` and `relation` options in the next sections.\n\n#### Id fields\nId fields are marked with the `id` key. This key also contains metadata about the PK generation strategy.\n```yaml\nPerson: # Model name\n  id:  # Field name\n    type: Long # Field type\n    id: \n      type: sequence # PK generation strategy\n      sequence: person_pk_gen # Sequence name\n      \nSpaceship: # Model name\n  code: # Field name\n    type: UUID # Field type\n    column: ship_code # Column name alias\n    id: auto # PK generation strategy\n```\n\nPK generation strategies are mapped to JPA generation strategies with lower case. Current supported strategies are:\n- `none`: No generation strategy.\n- `auto`: Auto generation strategy.\n- `sequence`: Sequence generation strategy. Sequence name can be provided.\n- `identity`: Identity generation strategy.\n\n#### Relation fields\nRelation fields are marked with the `relation` key. This key also contains metadata about the relation.\n```yaml\nPerson:\n  birthPlanet: # Field name\n    type: Planet # Field type\n    column: birth_planet\n    relation: # DB relation metadata\n      type: many-to-one # Relation type\n      join-column: birth_planet_id # Join column for relation\n  affiliations:\n    type: Faction # Field type\n    relation: # DB relation metadata\n      type: many-to-many # Relation type\n      join-table: person_affiliation # Join table for relation\n      join-column: person_id # Join column for relation\n      inverse-join-column: faction_id # Inverse join column for relation\n  backup: # Field name\n    type: Person # Field type\n    relation: # DB relation metadata\n      type: one-to-one # Relation type\n      join-column: backup_id # Join column for relation\n```\nOptions available are:\n- `type`: Relation type. Supported options are:\n  - `one-to-one`\n  - `one-to-many`\n  - `many-to-one`\n  - `many-to-many`\n- `join-column`: Join column for relation (owning side).\n- `mapped-by`: Mapped by field for relation (inverse side).\n- `inverse-join-column`: Inverse join column for relation (many-to-many relations).\n- `join-table`: Join table for relation (many-to-many relations).\n\nAll of these options are mapped to JPA annotations and configurations. Explaining when to use each option and what it does is out of the scope of this document.\n\n## Annexes\n### References\n- [JPA Bidirectional relations](https://vladmihalcea.com/jpa-hibernate-synchronize-bidirectional-entity-associations/)\n- [JPA many-to-many relations](https://www.jpa-buddy.com/blog/synchronization-methods-for-many-to-many-associations/)\n- [JPA equals/hashCode](https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/)\n- [JPA many-to-many collections](https://vladmihalcea.com/the-best-way-to-use-the-manytomany-annotation-with-jpa-and-hibernate/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalpreh%2Fcrudhex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsalpreh%2Fcrudhex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalpreh%2Fcrudhex/lists"}