# cjp2600/protoc-gen-structify architecture

> Architecture diagram of the GitHub repository cjp2600/protoc-gen-structify, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-27). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/cjp2600/protoc-gen-structify
- Repository: https://github.com/cjp2600/protoc-gen-structify

## Overview

1. **What this repo is**
   `protoc-gen-structify` is a Go Protocol Buffers plugin. Its job is to read `.proto` definitions annotated with `structify` options and generate typed database-access code, rather than an application runtime or server.

2. **Overall flow**
   The architecture is a one-way code-generation pipeline:
   protobuf schema + custom structify options → plugin parses descriptors and model state → provider-specific code generation → Go source files for DB clients, storage/query helpers, constants, and relation handling.

3. **Plugin entrypoint**
   The top-level `main.go` and `plugin/plugin.go` form the protoc plugin boundary. This is the executable that protoc invokes, and it delegates into the internal generator logic rather than talking to any database directly.

4. **Schema/options layer**
   `plugin/options/structify.proto` and the generated `structify.pb.go` define the custom protobuf annotations used to describe tables, primary keys, foreign keys, relations, and provider selection. These options are the main input contract for generation.

5. **Generation core**
   `plugin/generator` is the central orchestration layer. It turns protobuf descriptors and parsed metadata into output files, and its tests indicate this is where the main generation semantics are validated.

6. **Provider abstraction**
   `plugin/provider/provider.go` defines the abstraction for database backends, with concrete implementations for:
   - `plugin/provider/postgres`
   - `plugin/provider/sqlite`
   - `plugin/provider/clickhouse`
   
   This is the main architectural boundary in the repo: database-specific SQL dialect and behavior are isolated behind provider packages.

7. **Provider-specific templating**
   Each provider has its own `templater` and `tmpl` directories. The templater packages assemble generation inputs, while the `tmpl` packages hold the actual code templates for init logic, table code, and condition helpers. This keeps SQL-generation differences localized per database engine.

8. **Import/state plumbing**
   `plugin/import` manages generated import sets, avoiding duplication and keeping output files consistent. `plugin/state` stores generation-time context across files/messages, likely tracking resolved tables, relations, and naming decisions while the plugin traverses the schema.

9. **Utility and versioning**
   `plugin/pkg/helper` contains shared helper logic used across generation, and `plugin/pkg/version` exposes version metadata. These are supporting packages rather than architectural pillars, but they help stabilize output and tooling behavior.

10. **Repository examples as architecture samples**
   The `example/` tree is important because it shows the generated-code boundary in practice. The `case_one`, `case_two`, and `case_click` examples include generated `*.db.go` files alongside `.proto` inputs and small Go programs that exercise CRUD, pagination, and relation queries. They demonstrate the expected contract between schema, generator, and application code.

11. **Database feature coverage**
   The README and example layout show that the generated layer supports CRUD, filtering, pagination, transactions, joins, and relation navigation. ClickHouse is treated differently from the row-oriented providers because it supports query settings and PREWHERE, which is reflected in the separate ClickHouse provider implementation.

12. **Tests as architecture guardrails**
   The repo has focused tests around the generator, imports, helper utilities, state management, and each provider. That suggests the system is designed around deterministic code generation, with tests protecting both cross-provider behavior and backend-specific output.

13. **What is not in scope**
   This repo does not appear to include a live database service, HTTP server, or ORM runtime. The generated code is the output artifact; the only runtime dependency is the consumer application that imports the generated package and passes in a database connection.

14. **Diagram-friendly boundary summary**
   For an architecture diagram, the main boxes are: protobuf schema + structify options, protoc plugin entrypoint, generator/state/import orchestration, provider implementations per database, template/rendering layer, and generated Go DB-access code consumed by example apps.

Main entry points: [`plugin/generator/generator.go`](https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/generator/generator.go) (Generator), [`plugin/provider/provider.go`](https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/provider/provider.go) (Provider API), [`plugin/options/structify.proto`](https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/options/structify.proto) (Options proto), [`plugin/plugin.go`](https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/plugin.go) (Plugin)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_entry["Plugin entrypoint"]
  node_main["main.go<br/>executable entry<br/>[main.go]"]
  node_plugin_entry["Plugin<br/>[plugin.go]"]
end

subgraph group_core["Generation core"]
  node_generator["Generator<br/>orchestrator<br/>[generator.go]"]
  node_imports["Imports<br/>import planner<br/>[imports.go]"]
  node_state["State<br/>[state.go]"]
  node_helper["Helper<br/>shared utils<br/>[helper.go]"]
  node_version["Version<br/>metadata<br/>[version.go]"]
end

subgraph group_providers["Database providers"]
  node_provider_api["Provider API<br/>backend interface<br/>[provider.go]"]
  node_postgres["Postgres<br/>sql provider<br/>[postgres.go]"]
  node_sqlite["SQLite<br/>sql provider<br/>[sqlite.go]"]
  node_clickhouse["ClickHouse<br/>analytic provider<br/>[clickhouse.go]"]
  node_pg_templater["PG templater<br/>template assembler<br/>[init.go]"]
  node_sqlite_templater["SQLite templater<br/>template assembler<br/>[init.go]"]
  node_ch_templater["CH templater<br/>template assembler<br/>[init.go]"]
end

subgraph group_contracts["Schema contract"]
  node_structify_proto["Options proto<br/>schema options<br/>[structify.proto]"]
  node_structify_pb["Options pb<br/>generated schema<br/>[structify.pb.go]"]
end

subgraph group_examples["Examples"]
  node_case_one["Case one<br/>example app"]
  node_case_two["Case two<br/>example app"]
  node_case_click["Case click<br/>example app"]
end

node_main -->|"invokes"| node_plugin_entry
node_plugin_entry -->|"delegates"| node_generator
node_structify_proto -->|"compiles to"| node_structify_pb
node_structify_pb -->|"drives"| node_generator
node_generator -->|"tracks"| node_state
node_generator -->|"collects"| node_imports
node_generator -->|"selects"| node_provider_api
node_provider_api -->|"implements"| node_postgres
node_provider_api -->|"implements"| node_sqlite
node_provider_api -->|"implements"| node_clickhouse
node_postgres -->|"uses"| node_pg_templater
node_sqlite -->|"uses"| node_sqlite_templater
node_clickhouse -->|"uses"| node_ch_templater
node_generator -->|"uses"| node_helper
node_generator -->|"reads"| node_version
node_generator -->|"produces"| node_case_one
node_generator -->|"produces"| node_case_two
node_generator -->|"produces"| node_case_click
node_case_one -.->|"consumes"| node_structify_proto
node_case_two -.->|"consumes"| node_structify_proto
node_case_click -.->|"consumes"| node_structify_proto

click node_main "https://github.com/cjp2600/protoc-gen-structify/blob/main/main.go"
click node_plugin_entry "https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/plugin.go"
click node_structify_proto "https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/options/structify.proto"
click node_structify_pb "https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/options/structify.pb.go"
click node_generator "https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/generator/generator.go"
click node_imports "https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/import/imports.go"
click node_state "https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/state/state.go"
click node_provider_api "https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/provider/provider.go"
click node_postgres "https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/provider/postgres/postgres.go"
click node_sqlite "https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/provider/sqlite/sqlite.go"
click node_clickhouse "https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/provider/clickhouse/clickhouse.go"
click node_pg_templater "https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/provider/postgres/templater/init.go"
click node_sqlite_templater "https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/provider/sqlite/templater/init.go"
click node_ch_templater "https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/provider/clickhouse/templater/init.go"
click node_helper "https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/pkg/helper/helper.go"
click node_version "https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/pkg/version/version.go"
click node_case_one "https://github.com/cjp2600/protoc-gen-structify/tree/main/example/case_one"
click node_case_two "https://github.com/cjp2600/protoc-gen-structify/tree/main/example/case_two"
click node_case_click "https://github.com/cjp2600/protoc-gen-structify/tree/main/example/case_click"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_main,node_plugin_entry toneBlue
class node_generator,node_imports,node_state,node_helper,node_version toneAmber
class node_provider_api,node_postgres,node_sqlite,node_clickhouse,node_pg_templater,node_sqlite_templater,node_ch_templater toneMint
class node_structify_proto,node_structify_pb toneRose
class node_case_one,node_case_two,node_case_click toneIndigo
```

## Components

### Plugin entrypoint

Protoc plugin boundary and executable entry path.

- [main.go](https://github.com/cjp2600/protoc-gen-structify/blob/main/main.go): executable entry · CLI entry that protoc invokes. · `main.go`
- [Plugin](https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/plugin.go): protoc plugin · Bridges protoc input to generator logic. · `plugin/plugin.go`

### Generation core

Descriptor parsing, state, imports, and orchestration.

- [Generator](https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/generator/generator.go): orchestrator · Coordinates descriptor analysis and file generation. · `plugin/generator/generator.go`
- [Imports](https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/import/imports.go): import planner · Builds and deduplicates generated import sets. · `plugin/import/imports.go`
- [State](https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/state/state.go): generation state · Holds cross-file and cross-message generation context. · `plugin/state/state.go`
- [Helper](https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/pkg/helper/helper.go): shared utils · Common helper routines used across generation. · `plugin/pkg/helper/helper.go`
- [Version](https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/pkg/version/version.go): metadata · Build and version metadata surfaced by the plugin. · `plugin/pkg/version/version.go`

### Database providers

Backend-specific generation and SQL behavior.

- [Provider API](https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/provider/provider.go): backend interface · Abstracts database-specific capabilities behind one contract. · `plugin/provider/provider.go`
- [Postgres](https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/provider/postgres/postgres.go): sql provider · PostgreSQL-specific generation and SQL behavior. · `plugin/provider/postgres/postgres.go`
- [SQLite](https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/provider/sqlite/sqlite.go): sql provider · SQLite-specific generation and SQL behavior. · `plugin/provider/sqlite/sqlite.go`
- [ClickHouse](https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/provider/clickhouse/clickhouse.go): analytic provider · ClickHouse-specific generation, including its query constraints. · `plugin/provider/clickhouse/clickhouse.go`
- [PG templater](https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/provider/postgres/templater/init.go): template assembler · Assembles Postgres generation inputs for templates. · `plugin/provider/postgres/templater/init.go`
- [SQLite templater](https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/provider/sqlite/templater/init.go): template assembler · Assembles SQLite generation inputs for templates. · `plugin/provider/sqlite/templater/init.go`
- [CH templater](https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/provider/clickhouse/templater/init.go): template assembler · Assembles ClickHouse generation inputs for templates. · `plugin/provider/clickhouse/templater/init.go`

### Schema contract

Custom protobuf options that drive generation.

- [Options proto](https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/options/structify.proto): schema options · Custom annotations for tables, keys, relations, and provider selection. · `plugin/options/structify.proto`
- [Options pb](https://github.com/cjp2600/protoc-gen-structify/blob/main/plugin/options/structify.pb.go): generated schema · Compiled protobuf bindings for structify options. · `plugin/options/structify.pb.go`

### Examples

Sample generated outputs and consumer apps.

- [Case one](https://github.com/cjp2600/protoc-gen-structify/tree/main/example/case_one): example app · End-to-end sample with generated DB code and consumer flows. · `example/case_one`
- [Case two](https://github.com/cjp2600/protoc-gen-structify/tree/main/example/case_two): example app · Smaller sample showing generated DB access usage. · `example/case_two`
- [Case click](https://github.com/cjp2600/protoc-gen-structify/tree/main/example/case_click): example app · ClickHouse-oriented sample output and usage. · `example/case_click`

## Connections

- main.go → Plugin: invokes · Executable entry hands off to the protoc plugin boundary.
- Plugin → Generator: delegates · Plugin forwards parsed protoc input into generation orchestration.
- Options proto → Options pb: compiles to · Schema definitions are compiled into Go bindings.
- Options pb → Generator: drives · Generated annotations inform generator behavior.
- Generator → State: tracks · Generator stores schema-derived context during traversal.
- Generator → Imports: collects · Generator builds file imports as outputs are assembled.
- Generator → Provider API: selects · Generator chooses a backend through the provider abstraction.
- Provider API → Postgres: implements · Postgres is one backend implementation.
- Provider API → SQLite: implements · SQLite is one backend implementation.
- Provider API → ClickHouse: implements · ClickHouse is one backend implementation.
- Postgres → PG templater: uses · Provider-specific logic feeds templating.
- SQLite → SQLite templater: uses · Provider-specific logic feeds templating.
- ClickHouse → CH templater: uses · Provider-specific logic feeds templating.
- Generator → Helper: uses · Shared helpers support generation and naming.
- Generator → Version: reads · Version metadata is surfaced during generation/tooling.
- Generator → Case one: produces · Example package shows generated DB code as output.
- Generator → Case two: produces · Example package shows generated DB code as output.
- Generator → Case click: produces · ClickHouse example shows generated DB code as output.
- Case one → Options proto: consumes · Example schema uses the structify annotations.
- Case two → Options proto: consumes · Example schema uses the structify annotations.
- Case click → Options proto: consumes · Example schema uses the structify annotations.
