pub fn blank_schema() -> &'static str {
r#"// ForgeDB Schema
// Define your models below
User {
id: +uuid
email: ^&string @email
created_at: +timestamp
}
"#
}
pub fn blog_schema() -> &'static str {
r#"// Blog Schema
User {
id: +uuid
username: ^&string
email: ^&string @email
password_hash: string
created_at: +timestamp
posts: [Post]
}
Post {
id: +uuid
title: string
slug: ^&string
content: string
published: bool
published_at: timestamp?
created_at: +timestamp
updated_at: +timestamp
author: *User
tags: [Tag]
}
Tag {
id: +uuid
name: ^&string
posts: [Post]
}
"#
}
pub fn ecommerce_schema() -> &'static str {
r#"// E-commerce Schema
User {
id: +uuid
email: ^&string @email
name: string
created_at: +timestamp
orders: [Order]
}
Product {
id: +uuid
sku: ^&string
name: string
description: string
price: f64 @min(0)
stock: u32
created_at: +timestamp
}
Order {
id: +uuid
customer: *User
status: string
total: f64
created_at: +timestamp
items: [OrderItem]
}
OrderItem {
id: +uuid
order: *Order
product: *Product
quantity: u32 @min(1)
price: f64
}
"#
}
pub fn todo_schema() -> &'static str {
r#"// Todo App Schema
User {
id: +uuid
email: ^&string @email
name: string
created_at: +timestamp
todos: [Todo]
}
Todo {
id: +uuid
title: string
description: string?
completed: bool
due_date: timestamp?
created_at: +timestamp
updated_at: +timestamp
owner: *User
}
"#
}
pub fn default_config(project_name: &str) -> String {
format!(
r#"[project]
name = "{}"
version = "0.1.0"
# Generator configuration — consumed by the forgedb CLI.
# Precedence: explicit CLI flag > values below > built-in defaults.
[generate]
schema = "schema.forge"
output = "./generated"
# Uncomment to restrict which targets are generated:
# targets = ["rust", "typescript", "api", "stubs"]
# Generate-time RUNTIME BEHAVIOR (epic #126). These schema-blind knobs are baked
# into the generated database.rs when you run `forgedb generate` / `forgedb build`
# — the Rust compiler optimizes around them (there is no runtime settings engine).
# Every value below is the DEFAULT; the commented lines document what you can
# change. Changing one requires regenerating.
[runtime]
# Attach the durable replication broker so `/replicate` and browser read-replica
# followers work (#130). OFF by default: an unused broker fsyncs a SECOND time per
# write (pure waste when nothing is subscribed). Turn on only if you consume it.
replication = false
# In-process change-feed / durable-broker buffer capacity (#135).
# changefeed_capacity = 1024
# Max @on_delete(cascade) recursion depth — a structural safety bound (#150).
# max_cascade_depth = 64
# Durable replication-log retention (#137): when replication is on, maintain()
# prunes _replication.log to the last N broker offsets. 0 = keep the full log
# (default). A follower resuming from an offset older than the retained window
# must re-seed from a fresh backup.
# replication_log_retention = 0
# Generate-time STORAGE / DURABILITY knobs (epic #126). Also baked at generate
# time. Defaults are crash-safe and byte-identical to prior releases.
[storage]
# WAL fsync policy (#129): "always" (default — every acked write is crash-safe)
# or "never" (OS flushes on its own schedule; FASTER but a real data-loss window
# on power loss — an explicit, deliberate durability trade-off).
# fsync = "always"
# Mutations per collection between WAL checkpoints (#131) — bounds WAL growth.
# wal_checkpoint_interval = 1000
# In-process auto-compaction of dead row versions (#134). true = reclaim
# automatically; false = omit the auto-trigger (reclaim only via an explicit
# Database::compact() call).
# compaction = true
# Dead row versions per model before auto-compaction fires (#133).
# compaction_threshold = 1000
# Generate-time TRANSACTION knobs (epic #126). Baked at generate time.
[transaction]
# Default retry count for `transaction_optimistic` (#146) — a conflict-losing
# optimistic transaction is re-run up to max_retries + 1 times. Per-call control
# stays available via `transaction_retrying(retries, f)`.
# max_retries = 3
# Generate-time SERVER / transport knobs (epic #126). Baked at generate time.
# (Host/port, log level/format, and shutdown drain are separate DEPLOY-env knobs
# read from the environment at process start — see the note below.)
[server]
# List-endpoint page size when the client omits ?limit (#141).
# page_default_limit = 50
# Maximum list-endpoint page size; a larger ?limit is clamped (#141).
# page_max_limit = 1000
# Emit the unauthenticated /metrics endpoint (#151). false omits the handler +
# route entirely (/health, /ready, /snapshot are unaffected).
# metrics = true
# Generate-time WASM read-replica knobs (epic #126). Substituted into the static,
# schema-agnostic Worker bootstrap at generate time.
[wasm]
# Browser read-replica auto-commit debounce, ms (#148) — trades persist-write
# frequency vs the tab-close loss window.
# commit_debounce_ms = 250
# Commit immediately once this many replication frames are buffered (#148).
# commit_max_frames = 100
# Note: the generated server's host/port, log level/format, and graceful-shutdown
# drain timeout are DEPLOY-environment config, read from the environment at
# process start (FORGEDB_HOST / FORGEDB_PORT / RUST_LOG / FORGEDB_LOG_FORMAT /
# FORGEDB_SHUTDOWN_TIMEOUT) — 12-factor, not baked into the binary. See the
# generated main.rs and docs/DEPLOYMENT.md.
# Multi-tenancy (#59): physical, dir-per-tenant isolation. Each tenant's data
# lives under <root>/<tenant>/, and ONE `forgedb serve` process serves ONE
# tenant (process-per-tenant). Manage tenant dirs with `forgedb tenant`.
[tenant]
root = "./data"
# Verify-only JWT tenant guard for the generated server (#59). ForgeDB verifies
# tokens signed by YOUR identity provider (Auth0/Clerk/Cognito/…) — it never
# issues tokens. The generated process reads these at runtime via env
# (FORGEDB_TENANT selects which tenant this process serves); this table is the
# declarative source. Off by default.
[auth]
enabled = false
# issuer = "https://your-idp.example/"
# audience = "your-api"
# tenant_claim = "tenant" # claim carrying the tenant id (default)
# jwks_url = "https://your-idp.example/.well-known/jwks.json"
# jwks_refresh_secs = 300 # JWKS re-fetch interval for key rotation (#81)
# public_key_path = "./idp_pub.pem" # alternative to jwks_url (static key)
# algorithms = ["RS256"] # asymmetric-only allowlist; multiple allowed,
# # e.g. ["RS256", "ES256"] (default ["RS256"])
# leeway_secs = 60 # clock-skew leeway seconds (default)
"#,
project_name
)
}
pub fn default_gitignore() -> &'static str {
r#"# ForgeDB Generated Files
/generated/
# Database Files
/data/
# Rust
/target/
**/*.rs.bk
Cargo.lock
# TypeScript / Node
node_modules/
dist/
*.js
*.d.ts
!vite.config.js
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# OS
.DS_Store
Thumbs.db
"#
}
pub fn readme_template(project_name: &str) -> String {
format!(
r#"# {}
A ForgeDB project.
## Getting Started
### Development
```bash
# Generate code from schema
cargo run
# Run the application
cargo run --example basic
```
### Schema
Edit `schema.forge` to define your data models. The code will be automatically generated.
### Generated Code
- `generated/database.rs` - Rust database implementation
## Learn More
- [ForgeDB Documentation](https://github.com/yourusername/forgedb)
- [Schema Language Guide](https://github.com/yourusername/forgedb/blob/main/docs/schema.md)
"#,
project_name
)
}