# dream_ets
**Type-safe ETS (Erlang Term Storage) for Gleam.**
A standalone module providing a type-safe interface to Erlang's ETS in-memory storage. Features a builder pattern for table configuration, type-safe operations, and comprehensive error handling. Built with the same quality standards as [Dream](https://github.com/TrustBound/dream), but completely independent—use it in any Gleam project.
## Features
- ✅ Type-safe key-value storage
- ✅ Builder pattern for table configuration
- ✅ CRUD operations (get, set, delete, etc.)
- ✅ Atomic operations (insert_new, take)
- ✅ Pattern matching and advanced queries
- ✅ Table persistence (save/load to disk)
- ✅ Zero dependencies on Dream or other frameworks
## Installation
```bash
gleam add dream_ets
```
## Quick Start
### Creating Tables
```gleam
import dream_ets as ets
// Using the builder pattern
let assert Ok(table) = ets.new("my_table")
|> ets.key_string()
|> ets.value_string()
|> ets.create()
// Or use convenience functions
let assert Ok(counter) = ets.new_counter("user_counts")
let assert Ok(cache) = ets.new_string_table("cache")
```
### Basic Operations
```gleam
import dream_ets/operations
// Set a value
operations.set(table, "user:123", "Alice")
// Get a value
case operations.get(table, "user:123") {
Ok(option.Some(name)) -> io.println("Found: " <> name)
Ok(option.None) -> io.println("Not found")
Error(err) -> handle_error(err)
}
// Delete a key
operations.delete(table, "user:123")
// Check existence
if operations.member(table, "user:123") {
io.println("Key exists")
}
```
### Counter Tables
```gleam
import dream_ets/helpers
let assert Ok(counter) = ets.new_counter("page_views")
// Increment
case helpers.increment(counter, "homepage") {
Ok(new_value) -> io.println("Views: " <> int.to_string(new_value))
Error(err) -> handle_error(err)
}
// Increment by amount
helpers.increment_by(counter, "homepage", 5)
// Decrement
helpers.decrement(counter, "homepage")
```
## Usage
### Table Configuration
Use the builder pattern to configure tables:
```gleam
import dream_ets as ets
let assert Ok(table) = ets.new("users")
|> ets.table_type(ets.table_type_set()) // or ordered_set, bag, duplicate_bag
|> ets.access(ets.access_public()) // or protected, private
|> ets.read_concurrency(True)
|> ets.write_concurrency(False)
|> ets.compressed(False)
|> ets.key_string()
|> ets.value_string()
|> ets.create()
```
### Type-Safe Operations
Tables are parameterized over key and value types:
```gleam
import dream_ets/operations
// String-to-String table
let assert Ok(table) = ets.new_string_table("cache")
// Type-safe operations
operations.set(table, "key", "value") // ✅ Compiles
// operations.set(table, 123, "value") // ❌ Type error
case operations.get(table, "key") {
Ok(option.Some(value)) -> {
// value is String type
io.println(value)
}
Ok(option.None) -> {}
Error(err) -> handle_error(err)
}
```
### Advanced Operations
```gleam
import dream_ets/operations
// Insert only if key doesn't exist
case operations.insert_new(table, "key", "value") {
Ok(True) -> io.println("Inserted")
Ok(False) -> io.println("Already exists")
Error(err) -> handle_error(err)
}
// Get and delete atomically
case operations.take(table, "key") {
Ok(option.Some(value)) -> {
// Key is now deleted
process_value(value)
}
Ok(option.None) -> {}
Error(err) -> handle_error(err)
}
// Get all keys/values
let all_keys = operations.keys(table)
let all_values = operations.values(table)
let all_pairs = operations.to_list(table)
```
### Table Persistence
```gleam
import dream_ets/operations
// Save table to disk
case operations.save_to_file(table, "/tmp/my_table.ets") {
Ok(_) -> io.println("Saved")
Error(err) -> handle_error(err)
}
// Load table from disk (advanced - returns raw reference)
case operations.load_from_file("/tmp/my_table.ets") {
Ok(table_ref) -> {
// Use table_ref with internal APIs
}
Error(err) -> handle_error(err)
}
```
## API Reference
### Table Creation
- `ets.new(name)` - Create table config
- `ets.key_string(config)` - Configure string keys
- `ets.value_string(config)` - Configure string values
- `ets.counter(config)` - Configure counter table (String keys, Int values)
- `ets.create(config)` - Create table from config
- `ets.new_counter(name)` - Convenience: create counter table
- `ets.new_string_table(name)` - Convenience: create string-to-string table
### Operations
- `operations.set(table, key, value)` - Insert or update
- `operations.get(table, key)` - Lookup value
- `operations.delete(table, key)` - Delete key
- `operations.member(table, key)` - Check if key exists
- `operations.insert_new(table, key, value)` - Insert only if new
- `operations.take(table, key)` - Get and delete atomically
- `operations.keys(table)` - Get all keys
- `operations.values(table)` - Get all values
- `operations.to_list(table)` - Get all key-value pairs
- `operations.size(table)` - Get table size
- `operations.delete_table(table)` - Delete entire table
### Counter Helpers
- `helpers.increment(table, key)` - Increment by 1
- `helpers.increment_by(table, key, amount)` - Increment by amount
- `helpers.decrement(table, key)` - Decrement by 1
- `helpers.decrement_by(table, key, amount)` - Decrement by amount
## Design Principles
This module follows the same quality standards as [Dream](https://github.com/TrustBound/dream):
- **No nested cases** - Clear, flat control flow
- **No anonymous functions** - Named functions for clarity
- **Builder pattern** - Consistent, composable APIs
- **Type safety** - `Result` types force error handling
- **Quality testing** - Comprehensive test coverage
## About Dream
This module was originally built for the [Dream](https://github.com/TrustBound/dream) web toolkit, but it's completely standalone and can be used in any Gleam project. It follows Dream's design principles and will be maintained as part of the Dream ecosystem.
## License
MIT License - see LICENSE file for details.