Skip to content

Commit 2971ac0

Browse files
committed
refactor: pre-generate protobuf modules to remove protoc build-time dep
Downstream consumers no longer need protoc installed to compile the SDK. lib/longbridge/_protos.ex now ships the pre-compiled output of mix protox.generate (run via the new mix gen_protos alias). - pre-generate Longbridge.{Control,Quote,Trade}.V1.* into _protos.ex - drop protos/ from the Hex package files list (not needed by users) - exclude _protos.ex from mix format and ex_dna (generated code) - add mix gen_protos alias for regenerating after a .proto change - remove protoc build-time requirement from README install docs - document the new workflow in AGENTS.md
1 parent 62ddf3c commit 2971ac0

7 files changed

Lines changed: 27608 additions & 22 deletions

File tree

.ex_dna.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
%{
22
min_mass: 55,
33
min_occurrences: 2,
4-
ignore: ["deps/**", "_build/**", "node_modules/**"],
4+
ignore: ["deps/**", "_build/**", "node_modules/**", "lib/longbridge/_protos.ex"],
55
excluded_macros: [:schema, :pipe_through, :plug],
66
normalize_pipes: true
77
}

.formatter.exs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
# Used by "mix format"
22
[
3-
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
3+
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"],
4+
# Pre-generated by `mix protox.generate` from protos/*.proto.
5+
# Regenerate with `mix longbridge.gen_protos` (see mix.exs aliases).
6+
ignore_files: ["lib/longbridge/_protos.ex"]
47
]

AGENTS.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Operating instructions for AI coding agents working on the **longbridge** Elixir
2626
| `Longbridge.PortfolioContext` | Exchange rates and portfolio P&L analysis. HTTP-only. |
2727
| `Longbridge.Protocol` | Wire-format constants + `pack/2` / `unpack/1` for whole packets. |
2828
| `Longbridge.Protocol.Header` | Per-packet header encode/decode (request / response / push layouts). |
29-
| `Longbridge.Protos` | `use Protox, files: protos/*.proto` — generates `Longbridge.{Control,Quote,Trade}.V1.*` structs. |
29+
| `Longbridge.Protos` | Pre-generated protobuf modules (`lib/longbridge/_protos.ex`) for `Longbridge.{Control,Quote,Trade}.V1.*` structs. Regenerate with `mix gen_protos` (requires `protoc`, dev-only). |
3030
| `Longbridge.QuoteContext` | Public API for the quote endpoint — 20+ typed methods. |
3131
| `Longbridge.SharelistContext` | Community sharelist management. HTTP-only. |
3232
| `Longbridge.ScreenerContext` | Stock-screener strategies, indicator search, AI recommendations. HTTP-only. Mirrors `ScreenerContext` in `longbridge/openapi-go` and `longbridge/openapi`. |
@@ -61,7 +61,7 @@ mix format # auto-format
6161
mix docs # generate ExDoc HTML
6262
```
6363

64-
`protoc` must be on `$PATH` (Elixir `protox` shells out to it). On macOS: `brew install protobuf`.
64+
`protoc` is **only** required when regenerating protobuf modules (`mix gen_protos`), not for normal `mix compile`/`mix test`. On macOS: `brew install protobuf`. The generated modules ship pre-compiled in `lib/longbridge/_protos.ex`; downstream consumers never need `protoc`.
6565

6666
## Architecture invariants
6767

@@ -83,7 +83,7 @@ mix docs # generate ExDoc HTML
8383
- **No `IO.puts` / `IO.inspect` in library code.** Use `Logger` (the connection module already requires it). This includes temporary debugging — use `Logger.debug` and remove before committing.
8484
- **Specs for public functions.** `@spec` for every public function. Prefer concrete types (`non_neg_integer()`, `:atom | binary()`) over generic ones (`term()`, `any()`).
8585
- **Match on the struct shape, not just the variable.** When a function expects a `Header.t()`, pattern-match `def f(%Header{} = h, ...)` so Dialyzer can prove the type and you get a clear error if a caller passes the wrong shape.
86-
- **One `use Protox` only.** The `use Protox, files: [...], paths: [...]` macro call lives **exclusively** in `lib/longbridge/_protos.ex`. The macro generates `Longbridge.{Control,Quote,Trade}.V1.*` modules and the file's name (and `defmodule Longbridge.Protos`) are load-bearing for the generated module names — renaming either one will require updating the `Q.`, `T.`, and `Ctrl.` aliases in `quote_context.ex`, `trade_context.ex`, and `connection.ex`.
86+
- **Protobuf modules are pre-generated.** `lib/longbridge/_protos.ex` contains the pre-compiled output of `mix protox.generate` (run via the `mix gen_protos` alias). It generates `Longbridge.{Control,Quote,Trade}.V1.*` modules. Do **not** switch back to `use Protox, files: [...]` — that would reintroduce the `protoc` build-time dependency for downstream consumers. The file's name and `defmodule Longbridge.Protos` are load-bearing for the generated module names — renaming either one will require updating the `Q.`, `T.`, and `Ctrl.` aliases in `quote_context.ex`, `trade_context.ex`, and `connection.ex`. To regenerate after a `.proto` change: `mix gen_protos` (requires `protoc`).
8787

8888
## Tests
8989

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Changed
1111

12+
- **Pre-generated protobuf modules**`lib/longbridge/_protos.ex` now ships
13+
the compiled output of `mix protox.generate` instead of using `use Protox,
14+
files: [...]`. **Downstream consumers no longer need `protoc` installed** to
15+
compile the SDK. `protoc` is only required for maintainers regenerating the
16+
modules after a `.proto` change (run `mix gen_protos`). The `protos/` source
17+
files are no longer included in the Hex package.
1218
- **Dropped the `jason` dependency** in favor of the built-in `JSON` module
1319
(Elixir 1.20+). All encode/decode call sites in `lib/` and `test/` now use
1420
`JSON.encode!/1` / `JSON.decode/1`. `jason` remains only as a transitive
1521
dependency of `req` and `ex_doc`.
1622
- **Removed the redundant License section** from the README; the MIT LICENSE
1723
file now ships with the package and is linked via the badge.
24+
- **Removed the `protoc` build-time requirement** from the README installation
25+
instructions (no longer needed thanks to pre-generated modules).
1826

1927
## [0.1.0] — Initial beta release
2028

README.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,6 @@ def deps do
2424
end
2525
```
2626

27-
`protoc` is a build-time dependency of `protox` (one of the transitive deps). On macOS:
28-
29-
```sh
30-
brew install protobuf
31-
```
32-
3327
## Quick start
3428

3529
```elixir
@@ -636,7 +630,11 @@ The four `.proto` files under `protos/` are vendored from [`longbridge/openapi-p
636630
cp deps/openapi_protobuf_specs/control/*.proto protos/
637631
cp deps/openapi_protobuf_specs/quote/*.proto protos/
638632
cp deps/openapi_protobuf_specs/trade/*.proto protos/
639-
# 4. mix compile && mix test
633+
# 4. regenerate the pre-compiled modules (requires protoc)
634+
mix gen_protos
635+
# 5. mix compile && mix test
640636
```
641637

638+
The protobuf Elixir modules are **pre-generated** into `lib/longbridge/_protos.ex` (via `mix protox.generate`), so downstream consumers do **not** need `protoc` installed. `protoc` is only required for maintainers regenerating the modules after a proto change. Run `mix gen_protos` to regenerate.
639+
642640
Don't hand-edit files under `protos/` — the next sync will clobber your changes.

0 commit comments

Comments
 (0)