1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
//! Server-less - Composable derive macros for Rust
//!
//! Server-less takes an **impl-first** approach: write your Rust methods,
//! and derive macros project them into various protocols (HTTP, CLI, MCP, WebSocket).
//!
//! # Quick Start
//!
//! ```no_run
//! use server_less::prelude::*;
//! use serde::{Deserialize, Serialize};
//!
//! #[derive(Serialize, Deserialize)]
//! struct User { name: String, email: String }
//!
//! #[derive(Debug, ServerlessError)]
//! enum UserError { NotFound }
//!
//! struct UserService;
//!
//! #[mcp]
//! impl UserService {
//! /// Create a new user
//! async fn create_user(&self, name: String, email: String) -> Result<User, UserError> {
//! Ok(User { name, email })
//! }
//!
//! /// List all users
//! async fn list_users(&self, limit: Option<u32>) -> Vec<User> {
//! let _ = limit;
//! vec![]
//! }
//! }
//! ```
//!
//! This generates:
//! - **MCP**: Tools `create_user`, `list_users` (Model Context Protocol)
//!
//! # Available Macros
//!
//! **Blessed presets** (batteries-included, use these to get started):
//!
//! | Macro | Combines | Feature |
//! |-------|----------|---------|
//! | `#[server]` | `#[http]` (with OpenAPI) + `#[serve(http)]` | `http` |
//! | `#[program]` | `#[cli]` + `#[markdown]` | `cli` |
//! | `#[tool]` | `#[mcp]` + `#[jsonschema]` | `mcp` |
//! | `#[rpc]` | `#[jsonrpc]` + `#[openrpc]` + `#[serve(jsonrpc)]` | `jsonrpc` |
//!
//! **À la carte macros** (explicit composition):
//!
//! | Macro | Protocol | Generated Methods |
//! |-------|----------|-------------------|
//! | `#[http]` | HTTP/REST | `http_router()`, `http_openapi_spec()`, `http_openapi_paths()` |
//! | `#[cli]` | Command Line | `cli_command()`, `cli_run()`, `cli_run_with()`, `cli_run_async()`, `cli_run_with_async()` |
//! | `#[mcp]` | MCP | `mcp_tools()`, `mcp_call()`, `mcp_call_async()`, `mcp_method_names()` |
//! | `#[ws]` | WebSocket | `ws_router()`, `ws_handle_message()`, `ws_handle_message_async()`, `ws_methods()` |
//! | `#[jsonrpc]` | JSON-RPC 2.0 | `jsonrpc_router()`, `jsonrpc_methods()`, `jsonrpc_handle_async()` |
//! | `#[graphql]` | GraphQL | async-graphql integration |
//! | `#[grpc]` | gRPC | `.proto` schema generation |
//!
//! **Cross-cutting attributes:**
//!
//! | Macro | Purpose |
//! |-------|---------|
//! | `#[app(...)]` | Attach protocol-neutral metadata (name, description, version, homepage) |
//! | `#[derive(Config)]` | Generate config loading from env vars, TOML files, and defaults |
//! | `#[derive(ServerlessError)]` | Derive `IntoErrorCode` + `Display` + `Error` for error enums |
//! | `#[route(...)]` | Per-method HTTP overrides (method, path, skip, hidden) |
//! | `#[response(...)]` | Per-method response customization |
//! | `#[param(...)]` | Per-parameter metadata (name, default, location, env, help) |
//!
//! # Naming Conventions
//!
//! Method names infer HTTP methods and CLI subcommand structure:
//!
//! | Prefix | HTTP | CLI |
//! |--------|------|-----|
//! | `create_*`, `add_*` | POST | `<cmd> create-*` |
//! | `get_*`, `fetch_*` | GET (single) | `<cmd> get-*` |
//! | `list_*`, `find_*` | GET (collection) | `<cmd> list-*` |
//! | `update_*`, `set_*` | PUT | `<cmd> update-*` |
//! | `delete_*`, `remove_*` | DELETE | `<cmd> delete-*` |
//!
//! # Return Types
//!
//! | Type | HTTP | CLI | MCP/WS |
//! |------|------|-----|--------|
//! | `T` | 200 + JSON | stdout JSON | JSON result |
//! | `Option<T>` | 200 or 404 | stdout or exit 1 | result or null |
//! | `Result<T, E>` | 200 or error | stdout or stderr | result or error |
//! | `()` | 204 | silent | `{"success": true}` |
//! | `impl Stream<Item=T>` | SSE | N/A | N/A |
//!
//! # Async Methods
//!
//! All macros support async methods:
//!
//! ```no_run
//! use server_less::prelude::*;
//!
//! struct MyService;
//!
//! #[mcp]
//! impl MyService {
//! /// Sync method - works with mcp_call() and mcp_call_async()
//! pub fn sync_method(&self) -> String {
//! String::from("hello")
//! }
//!
//! /// Async method - use mcp_call_async() for proper await
//! pub async fn async_method(&self) -> String {
//! String::from("hello async")
//! }
//! }
//!
//! #[tokio::main]
//! async fn main() {
//! let service = MyService;
//! // Sync call (errors on async methods)
//! service.mcp_call("sync_method", serde_json::json!({}));
//! // Async call (awaits async methods properly)
//! service.mcp_call_async("async_method", serde_json::json!({})).await;
//! }
//! ```
//!
//! # SSE Streaming (HTTP)
//!
//! Return `impl Stream<Item=T>` for Server-Sent Events:
//!
//! ```no_run
//! use server_less::prelude::*;
//! use serde::{Deserialize, Serialize};
//!
//! #[derive(Clone, Serialize, Deserialize)]
//! struct Event { message: String }
//!
//! #[derive(Clone)]
//! struct StreamService;
//!
//! #[http]
//! impl StreamService {
//! // Note: Rust 2024 requires `+ use<>` to avoid lifetime capture
//! pub fn stream_events(&self) -> impl futures::Stream<Item = Event> + use<> {
//! futures::stream::iter(vec![Event { message: String::from("hello") }])
//! }
//! }
//! ```
//!
//! # Application Metadata
//!
//! `#[app]` attaches protocol-neutral metadata consumed by all protocol macros on the same impl:
//!
//! ```no_run
//! use server_less::prelude::*;
//! use server_less::{app, __app_meta};
//!
//! #[derive(Clone)]
//! struct MyApi;
//!
//! #[app(name = "myapi", description = "My API", version = "1.0.0")]
//! #[server]
//! impl MyApi {
//! pub fn hello(&self) -> String { String::from("hi") }
//! }
//! ```
//!
//! Preset macros also accept metadata inline:
//!
//! ```no_run
//! use server_less::prelude::*;
//!
//! #[derive(Clone)]
//! struct MyApi;
//!
//! #[server(name = "myapi", description = "My API")]
//! impl MyApi {
//! pub fn hello(&self) -> String { String::from("hi") }
//! }
//! ```
//!
//! # Config Management
//!
//! `#[derive(Config)]` generates config loading from env vars, TOML files, and defaults:
//!
//! ```no_run
//! use server_less::prelude::*;
//! # #[cfg(feature = "config")]
//! use server_less::{ConfigLoad, ConfigSource};
//!
//! # #[cfg(feature = "config")]
//! #[derive(server_less::Config)]
//! struct AppConfig {
//! #[param(default = "localhost")]
//! host: String,
//! #[param(default = 8080)]
//! port: u16,
//! #[param(env = "DATABASE_URL")]
//! database_url: String,
//! }
//! ```
//!
//! Pass the config type to `#[server]` to add a `config` subcommand and wire it into serve:
//!
//! ```no_run
//! use server_less::prelude::*;
//!
//! #[derive(Clone)]
//! struct MyService;
//!
//! // #[server(config = AppConfig)]
//! #[server]
//! impl MyService {
//! pub fn hello(&self) -> String { String::from("hi") }
//! }
//! ```
//!
//! # Feature Flags
//!
//! Enable only what you need:
//!
//! ```toml
//! [dependencies]
//! server-less = { version = "0.4", default-features = false, features = ["http", "cli"] }
//! ```
//!
//! Available features:
//! - `mcp` - MCP macro (no extra deps)
//! - `http` - HTTP macro (requires axum)
//! - `cli` - CLI macro (requires clap)
//! - `ws` - WebSocket macro (requires axum, futures)
//! - `jsonrpc` - JSON-RPC 2.0 macro
//! - `graphql` - GraphQL macro (requires async-graphql)
//! - `grpc` - gRPC `.proto` schema generation (no runtime deps)
//! - `capnp` - Cap'n Proto `.capnp` schema generation (no runtime deps)
//! - `thrift` - Apache Thrift `.thrift` IDL generation (no runtime deps)
//! - `connect` - Connect RPC schema generation (no runtime deps)
//! - `smithy` - AWS Smithy `.smithy` model generation (no runtime deps)
//! - `openapi` - Standalone OpenAPI spec generation (no axum required)
//! - `openrpc` - OpenRPC spec generation (no runtime deps)
//! - `asyncapi` - AsyncAPI spec generation (no runtime deps)
//! - `jsonschema` - JSON Schema generation (no runtime deps)
//! - `markdown` - Markdown API docs generation (no runtime deps)
//! - `config` - `#[derive(Config)]` for config loading (requires toml)
//! - `full` - All features (default)
// Re-export macros (feature-gated)
pub use mcp;
pub use http;
pub use openapi;
pub use route;
pub use response;
pub use param;
pub use serve;
pub use cli;
pub use CliSubcommand;
pub use CliGlobals;
pub use cli_format_output;
pub use ;
pub use McpNamespace;
pub use JsonRpcMount;
pub use WsMount;
pub use HttpMount;
pub use ws;
pub use jsonrpc;
pub use openrpc;
pub use graphql;
pub use graphql_enum;
pub use graphql_input;
pub use grpc;
pub use capnp;
pub use thrift;
pub use connect;
pub use smithy;
pub use markdown;
pub use jsonschema;
pub use asyncapi;
// Blessed presets
pub use server;
pub use rpc;
pub use tool;
pub use program;
// Error derive macro (always available - no deps, commonly needed)
pub use ServerlessError;
// Application metadata attribute (always available)
pub use app;
pub use __app_meta;
// Standalone health-check derive
pub use HealthCheck;
// Config derive macro
pub use Config;
pub use ;
// Re-export deps for generated code — users shouldn't need to add these directly
pub use clap;
// Shell completions / man page generators for the #[cli] projection
pub use clap_complete;
pub use clap_mangen;
pub use tokio;
pub use axum;
// Re-export futures for generated WebSocket code
pub use futures;
// Re-export async-graphql for generated GraphQL code
pub use async_graphql;
pub use async_graphql_axum;
// Re-export core types
pub use *;
// Re-export OpenAPI composition utilities (available when any protocol that generates OpenAPI is enabled)
pub use ;
// Re-export serde for generated code
pub use serde;
pub use serde_json;
/// Prelude for convenient imports