diff --git a/docs/book/art/openers/ch04b.svg b/docs/book/art/openers/ch04b.svg new file mode 100644 index 00000000..92d7179c --- /dev/null +++ b/docs/book/art/openers/ch04b.svg @@ -0,0 +1 @@ +CHAPTER 6BOOTSTRAPnew().run()web + CQRSscan beansadmin + docs diff --git a/docs/book/art/openers/ch06.svg b/docs/book/art/openers/ch06.svg index 37243295..286de8d0 100644 --- a/docs/book/art/openers/ch06.svg +++ b/docs/book/art/openers/ch06.svg @@ -1 +1 @@ -CHAPTER 6MONO & FLUXMono<T>Flux<T> +CHAPTER 7MONO & FLUXMono<T>Flux<T> diff --git a/docs/book/art/openers/ch06a.svg b/docs/book/art/openers/ch06a.svg new file mode 100644 index 00000000..f9a0daa5 --- /dev/null +++ b/docs/book/art/openers/ch06a.svg @@ -0,0 +1 @@ +CHAPTER 9OPENAPI#[rest_controller]#[derive(Schema)]openapi.jsonSwagger · ReDoc diff --git a/docs/book/art/openers/ch07.svg b/docs/book/art/openers/ch07.svg index 79e3d346..6c9002b9 100644 --- a/docs/book/art/openers/ch07.svg +++ b/docs/book/art/openers/ch07.svg @@ -1 +1 @@ -CHAPTER 7HTTP APIGET /walletsPOST /walletsRouter200 OK +CHAPTER 8HTTP APIGET /walletsPOST /walletsRouter200 OK diff --git a/docs/book/art/openers/ch08.svg b/docs/book/art/openers/ch08.svg index a90477f1..c85da559 100644 --- a/docs/book/art/openers/ch08.svg +++ b/docs/book/art/openers/ch08.svg @@ -1 +1 @@ -CHAPTER 8PERSISTENCERepositoryfind · save · delete +CHAPTER 10PERSISTENCERepositoryfind · save · delete diff --git a/docs/book/art/openers/ch09.svg b/docs/book/art/openers/ch09.svg index 05aefda8..169b4e78 100644 --- a/docs/book/art/openers/ch09.svg +++ b/docs/book/art/openers/ch09.svg @@ -1 +1 @@ -CHAPTER 9DOMAIN MODELMoneyWalletIdinvariantdomain eventWallet aggregate +CHAPTER 11DOMAIN MODELMoneyWalletIdinvariantdomain eventWallet aggregate diff --git a/docs/book/art/openers/ch10.svg b/docs/book/art/openers/ch10.svg index 8d865c44..2eb69202 100644 --- a/docs/book/art/openers/ch10.svg +++ b/docs/book/art/openers/ch10.svg @@ -1 +1 @@ -CHAPTER 10CQRSDepositCommandBalanceQueryBus +CHAPTER 12CQRSDepositCommandBalanceQueryBus diff --git a/docs/book/art/openers/ch11.svg b/docs/book/art/openers/ch11.svg index 263b9c59..257a4d70 100644 --- a/docs/book/art/openers/ch11.svg +++ b/docs/book/art/openers/ch11.svg @@ -1 +1 @@ -CHAPTER 11EVENTS & MESSAGINGKafkaRabbitMQlistenerprojectionEventBus +CHAPTER 13EVENTS & MESSAGINGKafkaRabbitMQlistenerprojectionEventBus diff --git a/docs/book/art/openers/ch12.svg b/docs/book/art/openers/ch12.svg index 94c4d713..50971fc9 100644 --- a/docs/book/art/openers/ch12.svg +++ b/docs/book/art/openers/ch12.svg @@ -1 +1 @@ -CHAPTER 12EVENT SOURCING+10-3+5= balance 12replay the stream +CHAPTER 14EVENT SOURCING+10-3+5= balance 12replay the stream diff --git a/docs/book/art/openers/ch13.svg b/docs/book/art/openers/ch13.svg index eae8adf0..ea12185f 100644 --- a/docs/book/art/openers/ch13.svg +++ b/docs/book/art/openers/ch13.svg @@ -1 +1 @@ -CHAPTER 13HTTP CLIENTSLumenPayments APIWebClient · retry · breaker +CHAPTER 15HTTP CLIENTSLumenPayments APIWebClient · retry · breaker diff --git a/docs/book/art/openers/ch14.svg b/docs/book/art/openers/ch14.svg index 31ed3183..810718ff 100644 --- a/docs/book/art/openers/ch14.svg +++ b/docs/book/art/openers/ch14.svg @@ -1 +1 @@ -CHAPTER 14EXPERIENCE TIERmobileBFFwalletsledgerfx +CHAPTER 16EXPERIENCE TIERmobileBFFwalletsledgerfx diff --git a/docs/book/art/openers/ch15.svg b/docs/book/art/openers/ch15.svg index fecf1837..bd160ef1 100644 --- a/docs/book/art/openers/ch15.svg +++ b/docs/book/art/openers/ch15.svg @@ -1 +1 @@ -CHAPTER 15SAGASdebitcreditnotifycompensate +CHAPTER 17SAGASdebitcreditnotifycompensate diff --git a/docs/book/art/openers/ch16.svg b/docs/book/art/openers/ch16.svg index 09ffe404..ab6c30a6 100644 --- a/docs/book/art/openers/ch16.svg +++ b/docs/book/art/openers/ch16.svg @@ -1 +1 @@ -CHAPTER 16SECURITYJWT#[secure]roles +CHAPTER 19SECURITYJWT#[secure]roles diff --git a/docs/book/art/openers/ch17.svg b/docs/book/art/openers/ch17.svg index 0e69d557..dc4c15a7 100644 --- a/docs/book/art/openers/ch17.svg +++ b/docs/book/art/openers/ch17.svg @@ -1 +1 @@ -CHAPTER 17OBSERVABILITY/health/metricstraces +CHAPTER 20OBSERVABILITY/health/metricstraces diff --git a/docs/book/art/openers/ch18.svg b/docs/book/art/openers/ch18.svg index 8894968d..5207fd8a 100644 --- a/docs/book/art/openers/ch18.svg +++ b/docs/book/art/openers/ch18.svg @@ -1 +1 @@ -CHAPTER 18CACHINGrequestCacheResiliencecache hitretry · breaker +CHAPTER 21CACHINGrequestCacheResiliencecache hitretry · breaker diff --git a/docs/book/art/openers/ch19.svg b/docs/book/art/openers/ch19.svg index 5a521703..7850e316 100644 --- a/docs/book/art/openers/ch19.svg +++ b/docs/book/art/openers/ch19.svg @@ -1 +1 @@ -CHAPTER 19SCHEDULING@schedulednotifywebhook +CHAPTER 22SCHEDULING@schedulednotifywebhook diff --git a/docs/book/art/openers/ch20.svg b/docs/book/art/openers/ch20.svg index 5c5d11fc..3b9ec410 100644 --- a/docs/book/art/openers/ch20.svg +++ b/docs/book/art/openers/ch20.svg @@ -1 +1 @@ -CHAPTER 20MACROS#[..]#[handler]#[route]#[saga_step] +CHAPTER 23MACROS#[..]#[handler]#[route]#[saga_step] diff --git a/docs/book/art/openers/ch21.svg b/docs/book/art/openers/ch21.svg index 7d937107..7718249a 100644 --- a/docs/book/art/openers/ch21.svg +++ b/docs/book/art/openers/ch21.svg @@ -1 +1 @@ -CHAPTER 21TESTINGStepVerifierTestcontainersall greenreal infra +CHAPTER 24TESTINGStepVerifierTestcontainersall greenreal infra diff --git a/docs/book/art/openers/ch22.svg b/docs/book/art/openers/ch22.svg index 1546a3cb..1490829a 100644 --- a/docs/book/art/openers/ch22.svg +++ b/docs/book/art/openers/ch22.svg @@ -1 +1 @@ -CHAPTER 22THE CLI$ firefly new$ firefly run$ firefly migrate ▮ +CHAPTER 25THE CLI$ firefly new$ firefly run$ firefly migrate ▮ diff --git a/docs/book/art/openers/ch22b.svg b/docs/book/art/openers/ch22b.svg new file mode 100644 index 00000000..d389d7f7 --- /dev/null +++ b/docs/book/art/openers/ch22b.svg @@ -0,0 +1 @@ +CHAPTER 18LAYERED SERVICES…-interfaces…-models…-core…-web…-sdk diff --git a/docs/book/art/openers/ch23.svg b/docs/book/art/openers/ch23.svg index f79ab6d4..45dec7c1 100644 --- a/docs/book/art/openers/ch23.svg +++ b/docs/book/art/openers/ch23.svg @@ -1 +1 @@ -CHAPTER 23PRODUCTIONbuildimageship12-factork8s · health · graceful +CHAPTER 26PRODUCTIONbuildimageship12-factork8s · health · graceful diff --git a/docs/book/book.yaml b/docs/book/book.yaml index 5e6bb155..5577d700 100644 --- a/docs/book/book.yaml +++ b/docs/book/book.yaml @@ -31,32 +31,35 @@ parts: - {id: ch03, file: 03-configuration.md, num: 3, title: "Configuration, Profiles & Secrets", opener: art/openers/ch03.svg} - {id: ch04, file: 04a-dependency-injection.md, num: 4, title: "Dependency Injection & the Application Context", opener: art/openers/ch04.svg} - {id: ch05, file: 04-dependency-wiring.md, num: 5, title: "Dependency Wiring & Composition", opener: art/openers/ch05.svg} - - {id: ch06, file: 05-reactive-model.md, num: 6, title: "The Reactive Model — Mono & Flux", opener: art/openers/ch06.svg} + - {id: ch04b, file: 04b-bootstrap.md, num: 6, title: "Application Bootstrap", opener: art/openers/ch04b.svg} + - {id: ch06, file: 05-reactive-model.md, num: 7, title: "The Reactive Model — Mono & Flux", opener: art/openers/ch06.svg} - title: "Part II — Modeling & Persisting the Domain" chapters: - - {id: ch07, file: 06-first-http-api.md, num: 7, title: "Your First HTTP API", opener: art/openers/ch07.svg} - - {id: ch08, file: 07-persistence.md, num: 8, title: "Persistence & Reactive Repositories", opener: art/openers/ch08.svg} - - {id: ch09, file: 08-domain-driven-design.md, num: 9, title: "Domain-Driven Design", opener: art/openers/ch09.svg} - - {id: ch10, file: 09-cqrs.md, num: 10, title: "CQRS: Commands & Queries", opener: art/openers/ch10.svg} + - {id: ch07, file: 06-first-http-api.md, num: 8, title: "Your First HTTP API", opener: art/openers/ch07.svg} + - {id: ch06a, file: 06a-openapi.md, num: 9, title: "OpenAPI & API Documentation", opener: art/openers/ch06a.svg} + - {id: ch08, file: 07-persistence.md, num: 10, title: "Persistence & Reactive Repositories", opener: art/openers/ch08.svg} + - {id: ch09, file: 08-domain-driven-design.md, num: 11, title: "Domain-Driven Design", opener: art/openers/ch09.svg} + - {id: ch10, file: 09-cqrs.md, num: 12, title: "CQRS: Commands & Queries", opener: art/openers/ch10.svg} - title: "Part III — Event-Driven Architecture" chapters: - - {id: ch11, file: 10-eda-messaging.md, num: 11, title: "Event-Driven Architecture & Messaging", opener: art/openers/ch11.svg} - - {id: ch12, file: 11-event-sourcing.md, num: 12, title: "Event Sourcing the Ledger", opener: art/openers/ch12.svg} + - {id: ch11, file: 10-eda-messaging.md, num: 13, title: "Event-Driven Architecture & Messaging", opener: art/openers/ch11.svg} + - {id: ch12, file: 11-event-sourcing.md, num: 14, title: "Event Sourcing the Ledger", opener: art/openers/ch12.svg} - title: "Part IV — Into Microservices" chapters: - - {id: ch13, file: 13-http-clients.md, num: 13, title: "HTTP Clients & Calling Other Services", opener: art/openers/ch13.svg} - - {id: ch14, file: 20a-experience-tier.md, num: 14, title: "The Experience Tier: Composing a BFF", opener: art/openers/ch14.svg} - - {id: ch15, file: 12-sagas.md, num: 15, title: "Distributed Transactions: Sagas, Workflows & TCC", opener: art/openers/ch15.svg} + - {id: ch13, file: 13-http-clients.md, num: 15, title: "HTTP Clients & Calling Other Services", opener: art/openers/ch13.svg} + - {id: ch14, file: 20a-experience-tier.md, num: 16, title: "The Experience Tier: Composing a BFF", opener: art/openers/ch14.svg} + - {id: ch15, file: 12-sagas.md, num: 17, title: "Distributed Transactions: Sagas, Workflows & TCC", opener: art/openers/ch15.svg} + - {id: ch22b, file: 22-layered-microservices.md, num: 18, title: "Layered Microservices", opener: art/openers/ch22b.svg} - title: "Part V — Secure, Observe & Ship" chapters: - - {id: ch16, file: 14-security.md, num: 16, title: "Security, Sessions & Identity", opener: art/openers/ch16.svg} - - {id: ch17, file: 15-observability.md, num: 17, title: "Observability & Health", opener: art/openers/ch17.svg} - - {id: ch18, file: 17-caching.md, num: 18, title: "Caching & Resilience", opener: art/openers/ch18.svg} - - {id: ch19, file: 16-scheduling-notifications.md, num: 19, title: "Scheduling, Notifications & Webhooks", opener: art/openers/ch19.svg} - - {id: ch20, file: 21-declarative-macros.md, num: 20, title: "Declarative Services with Macros", opener: art/openers/ch20.svg} - - {id: ch21, file: 18-testing.md, num: 21, title: "Testing Firefly Applications", opener: art/openers/ch21.svg} - - {id: ch22, file: 19-cli.md, num: 22, title: "The firefly CLI", opener: art/openers/ch22.svg} - - {id: ch23, file: 20-production.md, num: 23, title: "Extending Firefly & Going to Production", opener: art/openers/ch23.svg} + - {id: ch16, file: 14-security.md, num: 19, title: "Security, Sessions & Identity", opener: art/openers/ch16.svg} + - {id: ch17, file: 15-observability.md, num: 20, title: "Observability & Health", opener: art/openers/ch17.svg} + - {id: ch18, file: 17-caching.md, num: 21, title: "Caching & Resilience", opener: art/openers/ch18.svg} + - {id: ch19, file: 16-scheduling-notifications.md, num: 22, title: "Scheduling, Notifications & Webhooks", opener: art/openers/ch19.svg} + - {id: ch20, file: 21-declarative-macros.md, num: 23, title: "Declarative Services with Macros", opener: art/openers/ch20.svg} + - {id: ch21, file: 18-testing.md, num: 24, title: "Testing Firefly Applications", opener: art/openers/ch21.svg} + - {id: ch22, file: 19-cli.md, num: 25, title: "The firefly CLI", opener: art/openers/ch22.svg} + - {id: ch23, file: 20-production.md, num: 26, title: "Extending Firefly & Going to Production", opener: art/openers/ch23.svg} - title: "Appendices" chapters: - {id: appb, file: 91-appendix-modules.md, num: "A", title: "Crate & Module Index", opener: art/openers/appb.svg} diff --git a/docs/book/build/gen_openers.py b/docs/book/build/gen_openers.py index 832fda39..b9cfe471 100644 --- a/docs/book/build/gen_openers.py +++ b/docs/book/build/gen_openers.py @@ -420,14 +420,59 @@ def s_appb(): return rows +def s_bootstrap(): + # FireflyApplication::new("lumen").run() ignites the whole stack: one call + # on the left fans out into the services the framework discovers & wires. + call = (card(48, 132, 150, "new().run()", "url(#grh)", RUST_D, "#16110c", 14) + + spark(60, 90, 5, AMBER, 0.85) + spark(178, 102, 4, AMBER_B, 0.8)) + fans = (arrow(202, 142, 270, 78) + arrow(202, 150, 274, 150) + arrow(202, 158, 270, 222)) + pieces = (chip(280, 64, "web + CQRS") + chip(284, 136, "scan beans") + + chip(280, 208, "admin + docs")) + return call + fans + pieces + + +def s_openapi(): + # routes + DTOs are harvested into one generated spec, served as Swagger/ReDoc. + sources = (chip(40, 70, "#[rest_controller]") + chip(40, 196, "#[derive(Schema)]")) + funnel = (arrow(196, 92, 256, 132) + arrow(196, 210, 256, 156)) + doc = (f'' + f'' + f'' + # a little "spec" sheet: title bar + lines + f'' + + "".join(f'' for r in range(4)) + + f'') + out = (f'openapi.json') + return sources + funnel + doc + out + chip(290, 70, "Swagger · ReDoc", AMBER) + + +def s_layered(): + # five separately-compiled crates stacked like a multi-module project. + crates = ["…-interfaces", "…-models", "…-core", "…-web", "…-sdk"] + rows = [] + for i, c in enumerate(crates): + y = 60 + i * 38 + fill = "url(#grh)" if i == 4 else NODE + stroke = RUST_D if i == 4 else RUST + tcol = "#16110c" if i == 4 else INK + # slight left inset per layer to read as a stack + rows.append(card(44 + i * 6, y, 300 - i * 12, c, fill, stroke, tcol, 13)) + return "".join(rows) + spark(420, 96, 5, AMBER, 0.8) + spark(404, 196, 4, AMBER_B, 0.7) + + SCENES = { "ch01": ("Why Firefly — infinite choice becomes cohesion", "WHY FIREFLY", s_choice), "ch02": ("Quickstart — cargo new to a running service", "QUICKSTART", s_quickstart), "ch03": ("Configuration — layered defaults, profiles, secrets", "CONFIGURATION", s_config), "ch04": ("Dependency Injection — the application context", "DEPENDENCY INJECTION", s_di), "ch05": ("Dependency Wiring — composing the core", "WIRING", s_wiring), + "ch04b": ("Application Bootstrap — one call ignites the stack", "BOOTSTRAP", s_bootstrap), "ch06": ("The Reactive Model — Mono and Flux", "MONO & FLUX", s_reactive), "ch07": ("Your first HTTP API — routes and handlers", "HTTP API", s_http), + "ch06a": ("OpenAPI — routes and DTOs become a served spec", "OPENAPI", s_openapi), "ch08": ("Persistence — reactive repositories", "PERSISTENCE", s_persist), "ch09": ("Domain-Driven Design — aggregates and value objects", "DOMAIN MODEL", s_ddd), "ch10": ("CQRS — commands and queries on a bus", "CQRS", s_cqrs), @@ -436,6 +481,7 @@ def s_appb(): "ch13": ("HTTP clients — calling other services", "HTTP CLIENTS", s_clients), "ch14": ("The experience tier — composing a BFF", "EXPERIENCE TIER", s_bff), "ch15": ("Sagas, workflows and TCC — and compensation", "SAGAS", s_saga), + "ch22b": ("Layered microservices — separately-compiled crates", "LAYERED SERVICES", s_layered), "ch16": ("Security, sessions and identity", "SECURITY", s_security), "ch17": ("Observability and health", "OBSERVABILITY", s_observe), "ch18": ("Caching and resilience", "CACHING", s_cache), @@ -448,8 +494,18 @@ def s_appb(): "appb": ("Crate and module index", "MODULE INDEX", s_appb), } -# kicker numbers shown top-left, keyed by opener id -NUMS = {f"ch{i:02d}": f"CHAPTER {i}" for i in range(1, 24)} +# kicker numbers shown top-left, keyed by opener id. The order below is the +# book's reading order and the display number must match book.yaml's `num:`. +# Inserting 04b-bootstrap, 06a-openapi and 22-layered renumbers everything that +# follows, so this is an EXPLICIT ordered list rather than a range() formula. +_CH_ORDER = [ + "ch01", "ch02", "ch03", "ch04", "ch05", "ch04b", "ch06", # Part I (1..7) + "ch07", "ch06a", "ch08", "ch09", "ch10", # Part II (8..12) + "ch11", "ch12", # Part III (13..14) + "ch13", "ch14", "ch15", "ch22b", # Part IV (15..18) + "ch16", "ch17", "ch18", "ch19", "ch20", "ch21", "ch22", "ch23", # Part V (19..26) +] +NUMS = {oid: f"CHAPTER {i}" for i, oid in enumerate(_CH_ORDER, start=1)} NUMS["appa"] = "APPENDIX A" # book.yaml maps the module-index appendix (opener id appb) to "Appendix A". NUMS["appb"] = "APPENDIX A" diff --git a/docs/book/dist/firefly-rust-by-example.epub b/docs/book/dist/firefly-rust-by-example.epub index 320a8a24..68305668 100644 Binary files a/docs/book/dist/firefly-rust-by-example.epub and b/docs/book/dist/firefly-rust-by-example.epub differ diff --git a/docs/book/dist/firefly-rust-by-example.pdf b/docs/book/dist/firefly-rust-by-example.pdf index 7f5ead7c..a11e89ac 100644 Binary files a/docs/book/dist/firefly-rust-by-example.pdf and b/docs/book/dist/firefly-rust-by-example.pdf differ