### Complete Hummingbird Fluent Configuration Example Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/configuration.md A comprehensive example showing the full setup for Hummingbird Fluent, including logger configuration, database setup with SQLite, adding migrations, creating a persist driver, running migrations, defining routes for database operations, and running the application. ```swift import HummingbirdFluent import FluentSQLiteDriver import Logging // 1. Configure logger var logger = Logger(label: "MyApp") logger.logLevel = .info // 2. Initialize Fluent let fluent = Fluent(logger: logger) // 3. Configure database fluent.databases.use(.sqlite(.file("app.db")), as: .sqlite) // 4. Add migrations await fluent.migrations.add( CreateUsersTable(), CreateTodosTable(), CreateSessionsTable() ) // 5. Create persist driver let persist = await FluentPersistDriver( fluent: fluent, tidyUpFrequency: .minutes(15) ) // 6. Run migrations try await fluent.migrate() // 7. Create router with database operations let router = Router() router.post("todos") { request, context in let todo = try await request.decode(as: Todo.self, context: context) try await todo.create(on: fluent.db()) return todo } router.get("cache/:key") { _, context in let key = try context.parameters.require("key") return try await persist.get(key: key, as: String.self) } // 8. Create and configure application var app = Application(router: router) app.addServices(fluent, persist) // 9. Run application try await app.runService() ``` -------------------------------- ### Run Application Service Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/INDEX.md Starts the application and its associated services. This is typically the final step in application setup. ```swift try await app.runService() ``` -------------------------------- ### Basic Hummingbird Fluent Usage Example Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/README.md Demonstrates initializing Fluent, configuring a SQLite database, adding and running migrations, and integrating with application routes. This example requires FluentSQLiteDriver and Logging. ```swift import HummingbirdFluent import FluentSQLiteDriver import Logging // 1. Initialize Fluent let logger = Logger(label: "MyApp") let fluent = Fluent(logger: logger) // 2. Configure database fluent.databases.use(.sqlite(.file("db.sqlite")), as: .sqlite) // 3. Add migrations await fluent.migrations.add(CreateTodo()) // 4. Run migrations try await fluent.migrate() // 5. Use in routes let router = Router() router.get("todos/:id") { _, context in let id = try context.parameters.require("id", as: UUID.self) return try await Todo.find(id, on: fluent.db()) } // 6. Run application var app = Application(router: router) app.addServices(fluent) try await app.runService() ``` -------------------------------- ### SQLite Database Examples Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/configuration.md Demonstrates setting up file-based, in-memory, and specific path SQLite databases. File-based is common for production. ```swift // File-based SQLite (production typical) fluent.databases.use(.sqlite(.file("db.sqlite")), as: .sqlite) // In-memory SQLite (testing typical) fluent.databases.use(.sqlite(.memory), as: .sqlite) // Specific path fluent.databases.use(.sqlite(.file("/var/lib/myapp/db.sqlite")), as: .sqlite) ``` -------------------------------- ### Fluent Persist Driver Basic Setup Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent-persist-driver.md Integrates the Fluent Persist Driver into a Hummingbird application. Requires Fluent and a database driver. Sets up basic PUT and GET endpoints for caching. ```swift import HummingbirdFluent import FluentSQLiteDriver import Logging let logger = Logger(label: "MyApp") let fluent = Fluent(logger: logger) fluent.databases.use(.sqlite(.memory), as: .sqlite) // Create persist driver let persist = await FluentPersistDriver(fluent: fluent) // Run migrations to create _hb_persist_ table try await fluent.migrate() // Create router with persist endpoints let router = Router() router.put("cache/:key") { request, context in let key = try context.parameters.require("key") let buffer = try await request.body.collect(upTo: .max) try await persist.set(key: key, value: String(buffer: buffer)) return HTTPResponse.Status.ok } router.get("cache/:key") { _, context in let key = try context.parameters.require("key") return try await persist.get(key: key, as: String.self) } // Add to services var app = Application(router: router) app.addServices(fluent, persist) try await app.runService() ``` -------------------------------- ### Basic Hummingbird Application Setup with Fluent Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent.md Sets up a basic Hummingbird application with Fluent ORM, configures a SQLite database, adds and runs migrations, and defines a simple route for creating todos. ```swift import HummingbirdFluent import FluentSQLiteDriver import Logging let logger = Logger(label: "MyApp") let fluent = Fluent(logger: logger) // Configure database fluent.databases.use(.sqlite(.file("db.sqlite")), as: .sqlite) // Add migrations await fluent.migrations.add(CreateTodo(), CreateUser()) // Run migrations try await fluent.migrate() // Create router let router = Router() router.put("todos") { request, context in let todo = try await request.decode(as: Todo.self, context: context) try await todo.create(on: fluent.db()) return HTTPResponse.Status.created } // Create and run app var app = Application(router: router) app.addServices(fluent) try await app.runService() ``` -------------------------------- ### Configure Database Connection Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/INDEX.md Configures the database connection for Fluent. This example uses an SQLite database file. ```swift fluent.databases.use(.sqlite(.file("db.sqlite")), as: .sqlite) ``` -------------------------------- ### Initialize Hummingbird Fluent and Configure Database Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/START_HERE.md Initialize Hummingbird Fluent, configure a SQLite database, add migrations, and run them. This setup is essential before running the application service. ```swift import HummingbirdFluent import FluentSQLiteDriver import Logging // 1. Initialize let logger = Logger(label: "MyApp") let fluent = Fluent(logger: logger) // 2. Configure database fluent.databases.use(.sqlite(.file("db.sqlite")), as: .sqlite) // 3. Add migrations await fluent.migrations.add(CreateTodo()) // 4. Run migrations try await fluent.migrate() // 5. Create app and add service var app = Application(router: router) app.addServices(fluent) try await app.runService() ``` -------------------------------- ### get() Options Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/configuration.md Retrieves a value associated with a given key, attempting to decode it into a specified type. ```APIDOC ## get() Options ### Description Retrieves a value associated with a given key, attempting to decode it into a specified type. Returns `nil` if the key does not exist or if decoding fails. ### Method Asynchronous function call (Swift SDK) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **key** (String) - Required - Key to retrieve - **object** (Type) - Required - Type to decode value as ### Request Example ```swift // String let value = try await persist.get(key: "str", as: String.self) // Custom Codable type let value = try await persist.get(key: "data", as: MyData.self) // Array let values = try await persist.get(key: "list", as: [String].self) // Dictionary let dict = try await persist.get(key: "config", as: [String: Any].self) ``` ### Response #### Success Response - **Object?** - The decoded value, or `nil` if the key is not found or decoding fails. #### Response Example ```swift // Assuming MyData is a Codable struct struct MyData: Codable { let id: Int let name: String } // Example retrieval if let data = try await persist.get(key: "user_profile", as: MyData.self) { print("User name: \(data.name)") } else { print("User profile not found or invalid format.") } ``` ``` -------------------------------- ### run Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent-persist-driver.md Starts the persist driver's service lifecycle, including a background task for cleaning up expired entries. This method should be added to the application's services. ```APIDOC ## Service Lifecycle: run ### Description Service protocol implementation for lifecycle management. ### Signature ```swift public func run() async throws ``` ### Returns Void (runs until graceful shutdown) ### Throws None ### Example ```swift var app = Application(router: router) app.addServices(fluent, persist) try await app.runService() // Automatically calls persist.run() in background ``` ``` -------------------------------- ### Initialize FluentPersistDriver with Specific Database Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/configuration.md Configure `FluentPersistDriver` to use a specific database for persistence by providing a `databaseID`. Examples include using `.sqlite` or `.postgres`. ```swift let persist = await FluentPersistDriver( fluent: fluent, databaseID: .sqlite ) ``` ```swift let persist = await FluentPersistDriver( fluent: fluent, databaseID: .postgres ) ``` -------------------------------- ### Initialize Fluent with Custom NIOThreadPool Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/configuration.md Pass a manually created `NIOThreadPool` instance for blocking operations. Ensure the thread pool is started before passing it to Fluent. ```swift let threadPool = NIOThreadPool(numberOfThreads: 4) threadPool.start() let fluent = Fluent( threadPool: threadPool, logger: logger ) ``` -------------------------------- ### get Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent-persist-driver.md Retrieves a value from the store by its key and decodes it into the specified type. Returns nil if the key does not exist or has expired. ```APIDOC ## Method: get ### Description Retrieve and decode a value for a key. ### Signature ```swift public func get( key: String, as object: Object.Type ) async throws -> Object? ``` ### Parameters #### Path Parameters - **key** (String) - Required - Key to retrieve - **object** (Object.Type) - Required - Type to decode the value as ### Returns `Object?` - The decoded value, or nil if key doesn't exist or has expired. ### Throws - **PersistError.invalidConversion** - If stored value cannot be decoded as the requested type. ### Example ```swift struct UserSession: Codable { let userId: String let roles: [String] } // Retrieve existing session if let session = try await persist.get(key: "session:123", as: UserSession.self) { print("User: \(session.userId), Roles: \(session.roles)") } else { print("Session not found or expired") } // Type mismatch throws error do { let stringValue = try await persist.get(key: "cache:data", as: String.self) } catch let error as PersistError where error == .invalidConversion { print("Value stored as different type") } ``` ``` -------------------------------- ### Get Database Connection Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/INDEX.md Retrieves a database connection from Fluent for executing queries. ```swift let db = fluent.db() ``` -------------------------------- ### Duration Formats for Cleanup Frequency Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/configuration.md Examples of `Duration` formats available for configuring `tidyUpFrequency`, including seconds, milliseconds, microseconds, nanoseconds, minutes, hours, and days. ```swift .seconds(Int) .milliseconds(Int) .microseconds(Int) .nanoseconds(Int) .minutes(Int) .hours(Int) .days(Int) ``` -------------------------------- ### Get Database Connection Instance Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent.md Obtain a configured database connection instance. This instance is safe for concurrent use and can be stored in request contexts or used directly in route handlers. Optional parameters allow specifying a database ID, custom logger, query history, or page size limit. ```swift public func db( _ id: DatabaseID? = nil, logger: Logger? = nil, history: QueryHistory? = nil, pageSizeLimit: Int? = nil ) -> Database ``` ```swift router.get("todos/:id") { request, context in guard let id = context.parameters.get("id", as: UUID.self) else { return request.failure(HTTPError(.badRequest)) } return try await Todo.find(id, on: fluent.db()) } ``` -------------------------------- ### Initialize FluentPersistDriver Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent-persist-driver.md Initializes a new persist driver backed by a Fluent database. It automatically creates the internal `_hb_persist_` table if it doesn't exist and starts a background task to clean expired entries. ```swift import HummingbirdFluent import FluentSQLiteDriver import Logging let logger = Logger(label: "MyApp") let fluent = Fluent(logger: logger) fluent.databases.use(.sqlite(.memory), as: .sqlite) let persist = await FluentPersistDriver(fluent: fluent) try await fluent.migrate() var app = Application(router: router) app.addServices(fluent, persist) try await app.runService() ``` -------------------------------- ### Get Database Connection Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent.md Retrieves a configured database connection instance. This instance is safe for concurrent use and can be stored in request contexts or used directly. ```APIDOC ## db ### Description Get a database connection instance. ### Method `db` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **id** (DatabaseID? = nil) - ID of the database to use. If nil, uses default database - **logger** (Logger? = nil) - Custom logger for this connection. If nil, uses Fluent's logger - **history** (QueryHistory? = nil) - Query history storage for debugging - **pageSizeLimit** (Int? = nil) - Maximum page size limit to prevent server overload ### Returns `Database` - Database connection instance ### Throws Fatal error if specified database ID does not exist ### Example ```swift router.get("todos/:id") { request, context in guard let id = context.parameters.get("id", as: UUID.self) else { return request.failure(HTTPError(.badRequest)) } return try await Todo.find(id, on: fluent.db()) } ``` ``` -------------------------------- ### Run Persist Driver Service Lifecycle Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent-persist-driver.md Runs the persist driver's service lifecycle, starting a background cleanup task for expired entries. This should be added to the application's services list and exits gracefully on shutdown. ```swift public func run() async throws ``` ```swift var app = Application(router: router) app.addServices(fluent, persist) try await app.runService() // Automatically calls persist.run() in background ``` -------------------------------- ### Handle General Errors During Fluent Migrations Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/errors.md Catch any error that occurs during Fluent's migration process. Log the error and re-throw it, as the application cannot start without successful migrations. ```swift do { try await fluent.migrate() } catch { logger.error("Migration failed: \(error)") // Application cannot start without successful migrations throw error } ``` -------------------------------- ### Initialize Fluent with Logger Configuration Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/configuration.md The logger is the only required parameter. Configure its label and log level before passing it to Fluent. Supported levels range from .trace to .critical. ```swift import Logging var logger = Logger(label: "HummingbirdFluent") logger.logLevel = .info let fluent = Fluent(logger: logger) ``` -------------------------------- ### Initialize SQLite Database and Migrations Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/README.md Initializes an SQLite database connection and adds a migration. Ensure FluentSQLiteDriver and HummingbirdFluent are imported. ```swift import FluentSQLiteDriver import HummingbirdFluent let logger = Logger(label: "MyApp") let fluent = Fluent(logger: logger) // add sqlite database fluent.databases.use(.sqlite(.file("db.sqlite")), as: .sqlite) // add migration await fluent.migrations.add(CreateTodo()) // migrate if arguments.migrate { try fluent.migrate().wait() } ``` -------------------------------- ### Initialize Fluent Service Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/START_HERE.md Instantiate the main Fluent struct and add it to your application's services. Requires a logger. ```swift let fluent = Fluent(logger: logger) app.addServices(fluent) ``` -------------------------------- ### run() Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent.md Runs the Fluent service lifecycle, handling graceful shutdown and database connection closure. ```APIDOC ## run ### Description Run the Fluent service lifecycle. ### Parameters None ### Returns Void ### Throws | Error | |-----------| | Any | Database shutdown errors | ### Description Waits for graceful shutdown signal and then cleanly shuts down all database connections. This method should be called when adding Fluent as a service to your application. ### Example ```swift var app = Application(router: router, services: [fluent]) try await app.runService() ``` ``` -------------------------------- ### FluentPersistDriver Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/INDEX.md A persistent key-value store implementation conforming to PersistDriver and Service. It handles creating, setting, getting, and removing key-value pairs with optional expiration. ```APIDOC ## FluentPersistDriver ### Description Persistent key-value store implementation. Handles creating, setting, getting, and removing key-value pairs with optional expiration. ### Initializers - `init(fluent:databaseID:tidyUpFrequency:) async` — Initialize driver ### Methods - `create(key:value:expires:) async throws` — Create key (fails if exists) - `set(key:value:expires:) async throws` — Set key (creates or updates) - `get(key:as:) async throws → T?` — Get and decode value - `remove(key:) async throws` — Delete key - `run() async throws` — Service lifecycle ``` -------------------------------- ### Initialize Fluent with Custom EventLoopGroupProvider Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/configuration.md Use this when you need to manage the EventLoopGroup lifecycle separately. The `.singleton` provider is recommended for most use cases. ```swift let fluent = Fluent( eventLoopGroupProvider: .singleton, logger: logger ) ``` -------------------------------- ### Fluent Constructor Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent.md Initializes a new Fluent instance with configurable event loop group, thread pool, and logger. ```APIDOC ## init ### Description Initialize a new Fluent instance. ### Parameters #### Parameters - **eventLoopGroupProvider** (EventLoopGroupProvider) - Optional - EventLoopGroup provider for handling async operations - **threadPool** (NIOThreadPool) - Optional - NIOThreadPool for blocking database operations - **logger** (Logger) - Required - Logger instance used by databases ### Returns New Fluent instance ### Throws None ### Example ```swift import HummingbirdFluent import Logging let logger = Logger(label: "MyApp") let fluent = Fluent(logger: logger) ``` ``` -------------------------------- ### create() Options Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/configuration.md Stores a key-value pair that can optionally expire. If the key already exists, this operation will fail. ```APIDOC ## create() Options ### Description Stores a key-value pair that can optionally expire. If the key already exists, this operation will fail. ### Method Asynchronous function call (Swift SDK) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **key** (String) - Required - Unique key identifier - **value** (Codable) - Required - Value to store (will be JSON encoded) - **expires** (Duration?) - Optional - Time until expiration (nil = never expires) ### Request Example ```swift // No expiration try await persist.create(key: "permanent", value: data) // Expire in 1 hour try await persist.create(key: "temp", value: data, expires: .hours(1)) // Expire in 30 seconds try await persist.create(key: "shortlived", value: data, expires: .seconds(30)) // Expire in 7 days try await persist.create(key: "weekly", value: data, expires: .days(7)) ``` ### Response #### Success Response This operation does not return a value upon success. #### Response Example None ``` -------------------------------- ### Fluent Database Configuration Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent.md Shows how to configure SQLite database connections for Fluent ORM, including a file-based database and an in-memory database for testing. ```swift // SQLite fluent.databases.use(.sqlite(.file("db.sqlite")), as: .sqlite) ``` ```swift // SQLite in-memory (for testing) fluent.databases.use(.sqlite(.memory), as: .sqlite) ``` -------------------------------- ### Initialize FluentPersistDriver Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/START_HERE.md Set up a persistent key-value store for cross-request data like sessions or cache. This driver also acts as a service. ```swift let persist = await FluentPersistDriver(fluent: fluent) try await persist.set(key: "session:123", value: sessionData) app.addServices(fluent, persist) ``` -------------------------------- ### Get Operation with Type Specification Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/configuration.md Retrieve a value associated with a key, specifying the expected type for decoding. Handles various types including custom Codable objects, arrays, and dictionaries. ```swift // String let value = try await persist.get(key: "str", as: String.self) // Custom Codable type let value = try await persist.get(key: "data", as: MyData.self) // Array let values = try await persist.get(key: "list", as: [String].self) // Dictionary let dict = try await persist.get(key: "config", as: [String: Any].self) ``` -------------------------------- ### Initialize Fluent Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/INDEX.md Initializes the Fluent ORM with a logger. This is the first step before configuring databases or migrations. ```swift let fluent = Fluent(logger: logger) ``` -------------------------------- ### Run Fluent Migrations Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/INDEX.md Executes all pending database migrations. Ensure all migrations are added before running this. ```swift try await fluent.migrate() ``` -------------------------------- ### Initialize Fluent Instance Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent.md Initialize a new Fluent instance with a logger. Event loop group and thread pool providers can be customized if needed. ```swift import HummingbirdFluent import Logging let logger = Logger(label: "MyApp") let fluent = Fluent(logger: logger) ``` -------------------------------- ### migrate() Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent.md Executes all pending database migrations, creating the migration history table if necessary. ```APIDOC ## migrate ### Description Execute all pending database migrations. ### Parameters None ### Returns Void (all pending migrations are executed) ### Throws | Error | |-----------| | Database error | If migration preparation or execution fails | ### Description Runs all registered migrations that have not yet been applied to the database. Creates migration history table if needed. Must be called before using the database in most applications. ### Example ```swift fluent.databases.use(.sqlite(.file("db.sqlite")), as: .sqlite) await fluent.migrations.add(CreateTodo()) try await fluent.migrate() ``` ``` -------------------------------- ### Get Decoded Value with Fluent Persist Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent-persist-driver.md Retrieves a value from the store and decodes it to the requested type. Returns nil if the key doesn't exist or has expired. Use this when you need to fetch and use stored data as a specific Codable type. ```swift public func get( key: String, as object: Object.Type ) async throws -> Object? ``` ```swift struct UserSession: Codable { let userId: String let roles: [String] } // Retrieve existing session if let session = try await persist.get(key: "session:123", as: UserSession.self) { print("User: \(session.userId), Roles: \(session.roles)") } else { print("Session not found or expired") } // Type mismatch throws error do { let stringValue = try await persist.get(key: "cache:data", as: String.self) } catch let error as PersistError where error == .invalidConversion { print("Value stored as different type") } ``` -------------------------------- ### Add and Run Migrations Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/START_HERE.md Add your database schema migrations to the FluentMigrations actor and then execute them. Ensure migrations are added before calling migrate(). ```swift await fluent.migrations.add(CreateTodo()) try await fluent.migrate() ``` -------------------------------- ### Migration from HBFluent to Fluent Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/types.md Illustrates how to migrate from using the deprecated `HBFluent` type alias to the recommended `Fluent` type. ```swift // Old let fluent = HBFluent(logger: logger) // New let fluent = Fluent(logger: logger) ``` -------------------------------- ### Configuring Multiple Databases in Fluent Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/README.md Set up and use multiple database connections within a single Fluent application. Allows querying specific databases by their alias. ```swift fluent.databases.use(.sqlite(.memory), as: .sqlite) fluent.databases.use(.postgres(configuration: postgresConfig), as: .postgres) // Query primary database let result1 = try await Model.query(on: fluent.db()).all() // Query specific database let result2 = try await Model.query(on: fluent.db(.postgres)).all() ``` -------------------------------- ### File Organization Structure Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/STRUCTURE.md Illustrates the directory structure and file names for the HummingbirdFluent documentation. ```text output/ ├── README.md # Main entry point and overview ├── INDEX.md # Comprehensive symbol index ├── STRUCTURE.md # This file ├── types.md # Type definitions and type aliases ├── configuration.md # Configuration parameters and options ├── errors.md # Error types and error handling └── api-reference/ ├── fluent.md # Fluent struct and FluentMigrations actor └── fluent-persist-driver.md # FluentPersistDriver class ``` -------------------------------- ### Execute Fluent Migrations Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/configuration.md Run pending migrations, revert all migrations, or revert only the last batch. Ensure the `databases` and `logger` are provided when reverting the last batch. ```swift try await fluent.migrate() ``` ```swift try await fluent.revert() ``` ```swift try await fluent.migrations.revertLast( databases: fluent.databases, logger: fluent.logger ) ``` -------------------------------- ### Add Fluent Services to Application Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/configuration.md Demonstrates how to add the Fluent service, and optionally the Persist service, to your Hummingbird application. ```swift var app = Application(router: router) // Add Fluent service app.addServices(fluent) // Add Fluent and Persist services app.addServices(fluent, persist) ``` -------------------------------- ### Register Database-Specific Migrations Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/configuration.md Specify the target database for a migration using the `to:` parameter. Migrations can be registered for specific databases like PostgreSQL or SQLite, or for the default database if `nil` is provided. ```swift await fluent.migrations.add(CreateTodo(), to: nil) ``` ```swift await fluent.migrations.add(CreateTodo(), to: .postgres) ``` ```swift await fluent.migrations.add(CreateTodo(), to: .sqlite) await fluent.migrations.add(CreateTodo(), to: .postgres) ``` -------------------------------- ### Fluent Persist Driver with Codable Types Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent-persist-driver.md Demonstrates storing and retrieving Codable types using the Fluent Persist Driver. Ensure the Codable type is defined and conforms to Codable. ```swift struct CacheEntry: Codable { let timestamp: Date let version: Int let content: String } // Store let entry = CacheEntry( timestamp: Date(), version: 1, content: "cached content" ) try await persist.set(key: "page:home", value: entry, expires: .hours(1)) // Retrieve if let cached = try await persist.get(key: "page:home", as: CacheEntry.self) { print("Cache hit: v\(cached.version)") } ``` -------------------------------- ### Fluent Persist Driver Handling Expiration Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent-persist-driver.md Shows how to set an expiration time for stored data using the `expires` parameter. Retrieved data will be nil if it has expired. ```swift // Create a session that expires in 30 minutes try await persist.create( key: "session:\(sessionId)", value: sessionData, expires: .minutes(30) ) // Later, retrieve it if let session = try await persist.get(key: "session:\(sessionId)", as: SessionData.self) { // Session exists and hasn't expired } else { // Session doesn't exist or has expired } ``` -------------------------------- ### Configure Cleanup Frequency for FluentPersistDriver in Swift Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/errors.md Configure the `tidyUpFrequency` for `FluentPersistDriver` to manage database cleanup. The default of 10 minutes is often sufficient, but can be adjusted as needed. ```swift // Default 10 minutes is usually fine let persist = await FluentPersistDriver(fluent: fluent) // But adjust if needed let persist = await FluentPersistDriver( fluent: fluent, tidyUpFrequency: .minutes(5) // More frequent cleanup ) ``` -------------------------------- ### Add Migrations (Variadic) Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent.md Adds one or more migration instances to be executed during the next call to `migrate()`. Migrations are executed in the order they were added. ```APIDOC ## add (variadic) ### Description Add one or more migrations. ### Method `add(_ migrations: Migration..., to id: DatabaseID? = nil)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **migrations** (Migration...) - Variable number of migration instances to add - **id** (DatabaseID? = nil) - Database ID to add migrations to. If nil, adds to default database ### Returns Void ### Throws None ### Example ```swift await fluent.migrations.add(CreateTodo(), CreateUser()) ``` ``` -------------------------------- ### Set Page Size Limit Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/configuration.md Configure a `pageSizeLimit` for paginated queries to prevent server overload. This limit is respected by the `paginate` method. ```swift // No limit (default, use with caution) let db = fluent.db() // Limit to 100 items per page let db = fluent.db(pageSizeLimit: 100) // Limit to 1000 items per page let db = fluent.db(pageSizeLimit: 1000) // Use in query let items = try await Item.query(on: fluent.db(pageSizeLimit: 50)) .paginate(for: request) // Respects pageSizeLimit .all() ``` -------------------------------- ### Check Existence Before Creating in Swift Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/errors.md Before creating a new entry, check if a key already exists to prevent duplicate errors. Use `persist.get()` to check and `persist.create()` if it doesn't. ```swift if let existing = try await persist.get(key: id, as: MyType.self) { // Key already exists } else { try await persist.create(key: id, value: data) } ``` -------------------------------- ### SQLite Database Options Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/configuration.md Choose between file-based or in-memory SQLite databases based on your needs. In-memory is typically used for testing. ```swift .sqlite(.file(path: String)) // File-based database ``` ```swift .sqlite(.memory) // In-memory database ``` -------------------------------- ### Catching PersistError.duplicate Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/errors.md Demonstrates how to catch a `PersistError.duplicate` when attempting to create a key that already exists. This is useful for handling race conditions or preventing overwrites. ```swift do { try await model.save(on: db) } catch let error as DatabaseError where error.isConstraintFailure { throw PersistError.duplicate // Line 44 } ``` ```swift do { try await persist.create(key: sessionKey, value: sessionData) } catch let error as PersistError where error == .duplicate { // Handle duplicate key print("Key already exists") } ``` -------------------------------- ### Lifecycle Management Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/INDEX.md Methods for managing the lifecycle of Fluent and its components. ```APIDOC ## Lifecycle Management ### `run()` (Fluent) Starts the Fluent service. This is an asynchronous operation and can throw errors. ### `run()` (FluentPersistDriver) Starts the FluentPersistDriver service. This is an asynchronous operation and can throw errors. ### `shutdown()` Shuts down the Fluent service. This is an asynchronous operation and can throw errors. ``` -------------------------------- ### set Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent-persist-driver.md Sets a value for a key, creating it if it doesn't exist or updating it if it does. This method never fails with a duplicate key error. ```APIDOC ## set ### Description Set a value for a key, creating or updating as needed. ### Method ```swift public func set(key: String, value: some Codable, expires: Duration?) async throws ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | key | String | — | Unique identifier for the value | | value | some Codable | — | Codable value to store | | expires | Duration? | nil | Optional duration until expiration. If nil, value never expires | ### Returns Void ### Throws | Error | Condition | |-------|-----------| | PersistError | If encoding fails | ### Example ```swift struct Cache: Codable { let data: String let version: Int } let cache = Cache(data: "important data", version: 1) try await persist.set( key: "cache:data", value: cache, expires: .minutes(30) ) // Later, update the same key let updatedCache = Cache(data: "new data", version: 2) try await persist.set( key: "cache:data", value: updatedCache, expires: .minutes(30) ) ``` ``` -------------------------------- ### Run Fluent Service Lifecycle Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent.md Run the Fluent service lifecycle, which includes waiting for a graceful shutdown signal and then cleanly shutting down all database connections. This method should be called when adding Fluent as a service to your application. ```swift var app = Application(router: router, services: [fluent]) try await app.runService() ``` -------------------------------- ### Migration from HBFluentPersistDriver to FluentPersistDriver Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/types.md Illustrates how to migrate from using the deprecated `HBFluentPersistDriver` type alias to the recommended `FluentPersistDriver` type. ```swift // Old let persist = await HBFluentPersistDriver(fluent: fluent) // New let persist = await FluentPersistDriver(fluent: fluent) ``` -------------------------------- ### db() Method Parameters Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/configuration.md The `db()` method allows specifying the database ID, a custom logger, query history tracking, and a page size limit. ```swift public func db( _ id: DatabaseID? = nil, logger: Logger? = nil, history: QueryHistory? = nil, pageSizeLimit: Int? = nil ) -> Database ``` -------------------------------- ### Specify Database in Queries Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/configuration.md Select which database to use for a query. You can use the default, a specific ID, or a database with a custom logger. ```swift // Uses default database let db = fluent.db() // Uses specific database let db = fluent.db(.postgres) // Uses database with custom logger let db = fluent.db(logger: customLogger) ``` -------------------------------- ### Fluent Persist Driver Using Multiple Databases Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent-persist-driver.md Specifies which database to use for persistence when multiple databases are configured in the application. Defaults to the first configured database. ```swift fluent.databases.use(.sqlite(.memory), as: .sqlite) fluent.databases.use(.postgres(...), as: .postgres) // Use PostgreSQL for persistence instead of default SQLite let persist = await FluentPersistDriver( fluent: fluent, databaseID: .postgres ) ``` -------------------------------- ### create Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent-persist-driver.md Creates a new key-value pair in the persist store. This method will fail if the key already exists. ```APIDOC ## create ### Description Create a new key with a value. ### Method ```swift public func create(key: String, value: some Codable, expires: Duration?) async throws ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | key | String | — | Unique identifier for the value | | value | some Codable | — | Codable value to store | | expires | Duration? | nil | Optional duration until expiration. If nil, value never expires | ### Returns Void ### Throws | Error | Condition | |-------|-----------| | PersistError.duplicate | If a key with this name already exists | | PersistError | If encoding fails | ### Example ```swift struct UserSession: Codable { let userId: String let loginTime: Date } let session = UserSession(userId: "user123", loginTime: Date()) do { try await persist.create( key: "session:user123", value: session, expires: .hours(24) ) } catch let error as PersistError where error == .duplicate { print("Session already exists") } ``` ``` -------------------------------- ### Fetch Todo by ID in Route Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/README.md Defines a route to fetch a Todo item by its UUID from the request URI. Requires the `fluent` instance to access the database. ```swift let router = Router() router .group("todos") .get(":id") { request, context in guard let id = context.parameters.get("id", as: UUID.self) else { return request.failure(HTTPError(.badRequest)) } return Todo.find(id, on: fluent.db()) } ``` -------------------------------- ### Migration Management Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/INDEX.md Methods for managing database migrations. ```APIDOC ## Migration Management ### `add()` Adds a new migration. ### `migrate()` Applies all pending migrations. This is an asynchronous operation and can throw errors. ### `revert()` Reverts all applied migrations. This is an asynchronous operation and can throw errors. ### `revertLast()` Reverts the last applied migration. ``` -------------------------------- ### Database Management Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/INDEX.md Methods for accessing and configuring database connections. ```APIDOC ## Database Management ### `db()` Retrieves the default database connection. ### `db(id:)` Retrieves a database connection by its ID. ### `db(logger:)` Retrieves a database connection with a custom logger. ### `db(history:)` Retrieves a database connection with history tracking enabled. ### `db(pageSizeLimit:)` Retrieves a database connection with a specified page size limit. ``` -------------------------------- ### Execute Database Migrations Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent.md Execute all pending database migrations. This method ensures that all registered migrations that have not yet been applied are run. It also creates the migration history table if it doesn't exist. This must be called before using the database in most applications. ```swift fluent.databases.use(.sqlite(.file("db.sqlite")), as: .sqlite) await fluent.migrations.add(CreateTodo()) try await fluent.migrate() ``` -------------------------------- ### Log Errors Appropriately in Swift Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/errors.md Implement robust error handling using `do-catch` blocks and log errors using `fluent.logger.error()` with relevant metadata to aid in debugging database operations. ```swift do { try await persist.set(key: key, value: value) } catch { fluent.logger.error("Persist operation failed", metadata: [ "key": "\(key)", "error": "\(error)" ]) throw error } ``` -------------------------------- ### set() Options Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/configuration.md Stores or overwrites a key-value pair that can optionally expire. ```APIDOC ## set() Options ### Description Stores or overwrites a key-value pair that can optionally expire. This operation is similar to `create()` but will overwrite existing keys. ### Method Asynchronous function call (Swift SDK) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **key** (String) - Required - Unique key identifier - **value** (Codable) - Required - Value to store (will be JSON encoded) - **expires** (Duration?) - Optional - Time until expiration (nil = never expires) ### Request Example ```swift // Overwrite existing key or create new try await persist.set(key: "mykey", value: newData) // Overwrite with expiration try await persist.set(key: "session", value: sessionData, expires: .minutes(15)) ``` ### Response #### Success Response This operation does not return a value upon success. #### Response Example None ``` -------------------------------- ### FluentPersistDriver Constructor Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent-persist-driver.md Initializes a new FluentPersistDriver instance, configuring it to use a Fluent database for storing key-value pairs with optional expiration. ```APIDOC ## init ### Description Initialize a new FluentPersistDriver. ### Constructor ```swift public init( fluent: Fluent, databaseID: DatabaseID? = nil, tidyUpFrequency: Duration = .seconds(600) ) async ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | fluent | Fluent | — | Fluent instance with configured databases | | databaseID | DatabaseID? | nil | ID of database to use for persistence. If nil, uses default database | | tidyUpFrequency | Duration | .seconds(600) | How frequently to run cleanup of expired entries (10 minutes default) | ### Returns New FluentPersistDriver instance ### Throws None (database errors during migration setup are logged) ### Example ```swift import HummingbirdFluent import FluentSQLiteDriver import Logging let logger = Logger(label: "MyApp") let fluent = Fluent(logger: logger) fluent.databases.use(.sqlite(.memory), as: .sqlite) let persist = await FluentPersistDriver(fluent: fluent) try await fluent.migrate() var app = Application(router: router) app.addServices(fluent, persist) try await app.runService() ``` ``` -------------------------------- ### Document Key Types in Swift Code Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/errors.md Add comments to your code to document the expected data types for different key patterns, aiding in maintaining type consistency and preventing conversion errors. ```swift // Cache keys store CacheEntry, not String // Session keys store SessionData // Config keys store ConfigDict ``` -------------------------------- ### Persistent Storage with Fluent Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/README.md Utilize Fluent's persistent storage for session management and data caching. Supports setting expiration times for stored data. ```swift // Store session let session = SessionData(userId: "user123", roles: ["admin"]) try await persist.set( key: "session:\(sessionId)", value: session, expires: .hours(24) ) // Retrieve session if let session = try await persist.get(key: "session:\(sessionId)", as: SessionData.self) { // Session exists } // Cache data try await persist.set(key: "cache:homepage", value: htmlContent, expires: .hours(1)) ``` -------------------------------- ### Fluent Persist Driver Custom Cleanup Interval Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent-persist-driver.md Configures the automatic cleanup interval for expired entries. Defaults to 10 minutes if not specified. ```swift // Custom cleanup interval (every 5 minutes) let persist = await FluentPersistDriver( fluent: fluent, tidyUpFrequency: .minutes(5) ) // Less frequent cleanup (every hour) let persist = await FluentPersistDriver( fluent: fluent, tidyUpFrequency: .hours(1) ) ``` -------------------------------- ### Ensure Migrations Run Before Operations in Swift Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/errors.md Always run database migrations using `fluent.migrate()` and ensure they complete successfully before performing other operations to maintain database reliability. ```swift try await fluent.migrate() // Now safe to use persist ``` -------------------------------- ### Create Fluent Persist Driver Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/INDEX.md Creates an instance of the FluentPersistDriver, which is used for key-value storage. ```swift let persist = await FluentPersistDriver(fluent: fluent) ``` -------------------------------- ### Add Fluent Services to Application Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/INDEX.md Adds Fluent and its associated services, like the persist driver, to the application's service container. ```swift app.addServices(fluent, persist) ``` -------------------------------- ### revert() Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/api-reference/fluent.md Reverts all applied database migrations in reverse order, useful for development and testing. ```APIDOC ## revert ### Description Revert all database migrations. ### Parameters None ### Returns Void ### Throws | Error | |-----------| | Database error | If migration reversion fails | ### Description Reverts all applied migrations in reverse order. Typically used in development or testing. This is a destructive operation. ### Source Lines 62-65 ``` -------------------------------- ### Add Fluent Service to Application Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/README.md Integrates the initialized Fluent instance into the Hummingbird application's services for proper lifecycle management and shutdown. ```swift var app = Application(router: router) // add the fluent service to the application so it can manage shutdown correctly app.addServices(fluent) try await app.runService() ``` -------------------------------- ### Add Migrations to Fluent Source: https://github.com/hummingbird-project/hummingbird-fluent/blob/main/_autodocs/configuration.md Register single, multiple, or an array of migrations with the Fluent instance. Ensure migrations are added before calling `migrate()`. ```swift await fluent.migrations.add(CreateTodo()) ``` ```swift await fluent.migrations.add( CreateTodo(), CreateUser(), CreateProject() ) ``` ```swift let migrations: [Migration] = [ CreateTodo(), CreateUser() ] await fluent.migrations.add(migrations) ```