### PostgreSQL Database Setup Example Source: https://github.com/simolus3/drift/blob/develop/docs/content/platforms/postgres.md An example demonstrating how to set up a PostgreSQL database connection with drift. ```APIDOC ## PostgreSQL Database Setup Example ### Description This snippet shows a basic setup for a drift database with PostgreSQL, including connection details. ### Method Dart code snippet ### Endpoint N/A ### Parameters N/A ### Request Example ```dart // Assuming 'setup' is a defined snippet from /lib/src/snippets/platforms/postgres.dart // This is a placeholder for the actual code. // Example structure: // PgDatabase setup() => PgDatabase.open(Endpoint.parse('postgres://user:password@host:port/database')); ``` ### Response N/A ``` -------------------------------- ### Run Drift build runner Source: https://github.com/simolus3/drift/blob/develop/examples/web_worker_example/README.md Execute this command to start the development server for the shared web worker example. ```bash dart run build_runner serve ``` -------------------------------- ### CMake Project Setup and Configuration Source: https://github.com/simolus3/drift/blob/develop/examples/encryption/linux/CMakeLists.txt Initializes the CMake project, sets the minimum required version, defines the project name and languages, and configures modern CMake behaviors. It also sets the installation path for bundled libraries. ```cmake cmake_minimum_required(VERSION 3.13) project(runner LANGUAGES CXX) set(BINARY_NAME "drift_encryption_sample") set(APPLICATION_ID "com.example.drift_encryption_sample") cmake_policy(SET CMP0063 NEW) set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") ``` -------------------------------- ### Run PostgreSQL Database with Docker Source: https://github.com/simolus3/drift/blob/develop/examples/multi_package/README.md Starts a PostgreSQL database server using a Docker container. This is a prerequisite for running the server component of the example. ```bash docker run -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres postgres ``` -------------------------------- ### CMake: Define Installation Rules Source: https://github.com/simolus3/drift/blob/develop/extras/integration_tests/ffi_on_flutter/windows/CMakeLists.txt Configures the installation process for the application, setting the installation prefix to be adjacent to the executable for in-place execution. It defines destinations for data and library files and installs the main executable, ICU data, Flutter library, and any bundled plugin libraries. ```cmake set(BUILD_BUNDLE_DIR "$") set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) endif() set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) if(PLUGIN_BUNDLED_LIBRARIES) install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endif() ``` -------------------------------- ### Serve Drift Documentation Source: https://github.com/simolus3/drift/blob/develop/docs/README.md Run this command to start the website for preview purposes. The development server will be available on http://localhost:8080. ```shell dart run jaspr_cli:jaspr serve --no-managed-build-options ``` -------------------------------- ### CMake Installation Rules for Application Bundle Source: https://github.com/simolus3/drift/blob/develop/examples/encryption/windows/CMakeLists.txt Sets up installation rules for the application bundle, ensuring that the executable, libraries, and assets are correctly placed relative to the executable for in-place execution. This includes handling multi-configuration generators and defining installation directories. ```cmake set(BUILD_BUNDLE_DIR "$") set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) endif() set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) if(PLUGIN_BUNDLED_LIBRARIES) install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endif() set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") install(DIRECTORY "${NATIVE_ASSETS_DIR}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) set(FLUTTER_ASSET_DIR_NAME "flutter_assets") install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" CONFIGURATIONS Profile;Release COMPONENT Runtime) ``` -------------------------------- ### Setup Dependencies Source: https://github.com/simolus3/drift/blob/develop/docs/content/platforms/postgres.md Add drift and drift_postgres to your pubspec.yaml file to enable PostgreSQL support. ```APIDOC ## Setup Dependencies ### Description Add `drift` and `drift_postgres` to your `pubspec.yaml` to use drift with PostgreSQL. ### Method Add dependencies to `pubspec.yaml` ### Endpoint N/A ### Parameters N/A ### Request Example ```yaml dependencies: drift: ^{{ versions.drift }} drift_postgres: ^{{ versions.drift_postgres }} dev_dependencies: drift_dev: ^{{ versions.drift_dev }} build_runner: ^{{ versions.build_runner }} ``` ### Response N/A ``` -------------------------------- ### Installation Bundle Configuration Source: https://github.com/simolus3/drift/blob/develop/examples/encryption/linux/CMakeLists.txt Configures the installation process to create a relocatable bundle. It sets the install prefix to a bundle directory and ensures the bundle directory is cleaned before each installation. ```cmake set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) endif() install(CODE " file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") " COMPONENT Runtime) ``` -------------------------------- ### Open Database with Custom Worker Setup Source: https://github.com/simolus3/drift/blob/develop/docs/content/platforms/web.md Use this to open a Drift database from your application, referencing a custom worker that handles database setup. The `setupDatabase` value is duplicated with `localSetup` for cases where the database doesn't run in a worker. ```dart final database = await WasmDatabase.open( File('my_db.sqlite'), driftWorkerUri: Uri.parse('my_worker.js'), setupDatabase: setupAllDatabases, localSetup: localSetup, ); // If you want to use a database that is not running in a worker, you can // pass `setupDatabase: localSetup` to WasmDatabase.open. final databaseWithoutWorker = await WasmDatabase.open( File('my_db.sqlite'), setupDatabase: localSetup, ); ``` -------------------------------- ### Installation Rules for Application Bundle (CMake) Source: https://github.com/simolus3/drift/blob/develop/examples/app/linux/CMakeLists.txt Defines installation rules for creating a relocatable application bundle, including clearing the build directory, installing the executable, data files, libraries, and assets. ```cmake set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) endif() install(CODE " file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") " COMPONENT Runtime) set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) install(FILES "${bundled_library}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endforeach(bundled_library) set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") install(DIRECTORY "${NATIVE_ASSETS_DIR}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) set(FLUTTER_ASSET_DIR_NAME "flutter_assets") install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endif() ``` -------------------------------- ### Initialize Encrypted NativeDatabase Source: https://github.com/simolus3/drift/blob/develop/docs/content/platforms/encryption.md Use the setup parameter in NativeDatabase to execute the pragma key command before the database is accessed. ```dart NativeDatabase.createFile(file, setup: (database) { database.execute("PRAGMA key = 'secret';"); }); ``` -------------------------------- ### Set up Drift Database with PostgreSQL Connection Source: https://github.com/simolus3/drift/blob/develop/docs/content/platforms/postgres.md Example of setting up a Drift database instance for PostgreSQL. It demonstrates using the PgDatabase constructor with connection details. ```dart final database = PgDatabase.fromEndpoint(Endpoint( host: 'localhost', port: 5432, username: 'postgres', password: 'postgres', databaseName: 'drift_db', )); ``` -------------------------------- ### CMake Installation Rules for Application Bundle Source: https://github.com/simolus3/drift/blob/develop/examples/app/windows/CMakeLists.txt Configures installation rules for the application, including setting the installation prefix to the executable's directory for in-place execution. It defines destinations for data, libraries, and bundled plugins. ```cmake set(BUILD_BUNDLE_DIR "$") set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) endif() set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) if(PLUGIN_BUNDLED_LIBRARIES) install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endif() ``` -------------------------------- ### Insert Data on First App Start with MigrationStrategy Source: https://github.com/simolus3/drift/blob/develop/docs/content/faq.md Demonstrates how to populate the database with initial data when it's first created using the onCreate callback within a MigrationStrategy. ```dart MigrationStrategy( onCreate: (m) async { await m.createAll(); // create all tables await into(myTable).insert(...); // insert on first run. } ) ``` -------------------------------- ### Moving to step-by-step Migrations with a Starting Point Source: https://github.com/simolus3/drift/blob/develop/docs/content/migrations/step_by_step.md Explains how to transition to step-by-step migrations by setting a 'floor' version in `Migrator.runMigrationSteps`, allowing existing migration work to be consolidated before adopting the new strategy. ```APIDOC ## Moving to step-by-step Migrations with a Starting Point ### Description This example shows how to adopt step-by-step migrations when you have existing migration logic or are migrating from an older Drift version. By specifying a `from` value in `Migrator.runMigrationSteps`, you can define a starting point for `stepByStep` migrations, ensuring all prior schema changes are applied before new step-by-step migrations take over. ### Method `Migrator.runMigrationSteps` with a `from` parameter ### Endpoint N/A (Code implementation detail) ### Parameters N/A ### Request Example ```dart // Assuming 'm' is the Migrator instance and 'schema' is the schema object await m.runMigrationSteps( // Set this to the schema version that your existing migrations bring the database to. // All migrations before this version should be handled by your existing logic. from: 2, // Example: start stepByStep migrations from version 2 to: schema.version, // The current latest schema version steps: [ // Define your step-by-step migrations here, e.g., from2To3, from3To4, etc. // These will be generated by `drift_dev schema steps`. ], ); ``` ### Response #### Success Response (200) N/A (This is a code implementation example) #### Response Example N/A ``` -------------------------------- ### Setting up In-Memory Drift Database for Tests Source: https://github.com/simolus3/drift/blob/develop/docs/content/testing.md Demonstrates how to set up an in-memory Drift database for unit tests using `NativeDatabase.memory()` within `setUp` and `tearDown` methods. ```dart import 'package:drift/native.dart'; import 'package:test/test.dart'; // Assuming MyDatabase is defined as in the previous example late MyDatabase database; setUp(() { database = MyDatabase(NativeDatabase.memory()); }); tearDown(() async { await database.close(); }); // ... tests go here ... ``` -------------------------------- ### Basic Migration Test Structure Source: https://github.com/simolus3/drift/blob/develop/docs/content/migrations/tests.md An example of a basic unit test for database migrations using Drift's testing utilities. It demonstrates how to start at a specific schema version, create the application database, and migrate and validate against a target version. ```dart import 'package:drift/drift.dart';\nimport 'package:drift/testing.dart';\nimport 'package:test/test.dart';\n\n// Assuming your database and schema are defined elsewhere\nimport 'package:your_app/database.dart'; // Adjust import path\nimport 'package:your_app/generated_migrations/schema.dart'; // Adjust import path\n\nFuture main() async {\n test('migrations are correct', () async {\n final schemaVerifier = SchemaVerifier(GeneratedDatabase.schema);\n\n // Start at version 1\n final db = await schemaVerifier.startAt(1);\n\n // Create your application database with the test connection\n final appDb = YourAppDatabase(db); // Replace YourAppDatabase with your actual database class\n\n // Migrate to version 2 and validate\n await schemaVerifier.migrateAndValidate(appDb, 2);\n\n // Add more assertions here if needed\n expect(true, isTrue); // Placeholder assertion\n });\n} ``` -------------------------------- ### Flutter Web Database Setup Source: https://github.com/simolus3/drift/blob/develop/docs/content/platforms/web.md Configure web support for `package:drift_flutter` by providing `DriftWebOptions` with URIs for the WebAssembly module and the drift worker. ```dart final options = DriftWebOptions( // The location of the sqlite3.wasm file sqlite3WasmUri: Uri.parse('sqlite3.wasm'), // The location of the drift_worker.dart.js file workerUri: Uri.parse('drift_worker.dart.js'), ); // Use this in your database constructor: final database = AppDatabase(options); ``` -------------------------------- ### Installing Application Components Source: https://github.com/simolus3/drift/blob/develop/examples/encryption/linux/CMakeLists.txt Installs the main executable, Flutter ICU data, Flutter library, bundled plugin libraries, and native assets into the designated bundle directories. It also ensures the assets directory is re-copied on each build. ```cmake set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) install(FILES "${bundled_library}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endforeach(bundled_library) set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") install(DIRECTORY "${NATIVE_ASSETS_DIR}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) set(FLUTTER_ASSET_DIR_NAME "flutter_assets") install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) ``` -------------------------------- ### Project and Build Configuration (CMake) Source: https://github.com/simolus3/drift/blob/develop/examples/app/linux/CMakeLists.txt Sets up the minimum CMake version, project name, executable name, and application ID. It also configures build policies and installation paths for libraries. ```cmake cmake_minimum_required(VERSION 3.13) project(runner LANGUAGES CXX) set(BINARY_NAME "app") set(APPLICATION_ID "com.example.app") cmake_policy(SET CMP0063 NEW) set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") if(FLUTTER_TARGET_PLATFORM_SYSROOT) set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) endif() if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Flutter build mode" FORCE) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Profile" "Release") endif() ``` -------------------------------- ### Migrate Custom WasmDatabase Setup Source: https://github.com/simolus3/drift/blob/develop/docs/content/platforms/web.md Replace custom `WasmDatabase` constructions that manually loaded the WASM binary and created a `CommonSqlite3` instance. `WasmDatabase.open` now manages this internally. ```dart import "package:drift/drift.dart"; import "package:drift/wasm.dart"; // This is an example of how you might have opened a database in older drift versions. // You can now replace this with a call to WasmDatabase.open. final database = WasmDatabase( "my_database.db", // The `sqlite3` instance is now created internally by WasmDatabase.open. await commonRuntime.createDatabase(), ); // You can now use the database as usual. // final myDao = MyDao(database); ``` -------------------------------- ### Example Drift Database Schema Upgrade Source: https://github.com/simolus3/drift/blob/develop/docs/content/migrations/index.md Illustrates how to implement a schema upgrade in a Drift database class. It shows how to use the `stepByStep` migration strategy to define incremental schema changes. ```dart import 'package:drift/drift.dart'; import 'database.steps.dart'; part 'database.g.dart'; @DriftDatabase(...) class MyDatabase extends _$MyDatabase { MyDatabase(super.e); @override int get schemaVersion => 2; // bump because the tables have changed. @override MigrationStrategy get migration { return MigrationStrategy( onUpgrade: _schemaUpgrade, ); } } extension Migrations on GeneratedDatabase { // Extracting the `stepByStep` call into a static field or method ensures that you're not // accidentally referring to the current database schema (via a getter on the database class). // This ensures that each step brings the database into the correct snapshot. OnUpgrade get _schemaUpgrade => stepByStep( from1To2: (m, schema) async { await m.createTable(schema.groups); }, ); } ``` -------------------------------- ### CMake Project Setup and Configuration Source: https://github.com/simolus3/drift/blob/develop/examples/app/windows/CMakeLists.txt Initializes the CMake project, sets the minimum version, project name, and executable name. It also configures CMake policies and defines build types based on whether the generator is multi-configuration. ```cmake cmake_minimum_required(VERSION 3.14) project(app LANGUAGES CXX) set(BINARY_NAME "app") cmake_policy(VERSION 3.14...3.25) get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(IS_MULTICONFIG) set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" CACHE STRING "" FORCE) else() if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Flutter build mode" FORCE) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Profile" "Release") endif() endif() ``` -------------------------------- ### Initialize Drift with LazyDatabase Source: https://github.com/simolus3/drift/blob/develop/docs/content/platforms/vm.md Uses LazyDatabase to perform asynchronous setup tasks, such as checking for file existence or copying assets, before opening the database. ```dart LazyDatabase(() async { final file = File('...'); if (!await file.exists()) { // Perform setup logic like copying from assets } return NativeDatabase(file); }); ``` -------------------------------- ### Drift Schema Migration Example Source: https://github.com/simolus3/drift/blob/develop/docs/content/migrations/index.md Demonstrates how to define and apply schema migrations in Drift. It shows how to increment the schema version and provide migration strategies for different versions, including adding new columns to existing tables. ```dart class MyDatabase extends _$MyDatabase { // ... @override int get schemaVersion => 3; @override MigrationStrategy get migration { return MigrationStrategy( onCreate: (m) async { await m.createAllTables(); }, onUpgrade: (m, from, to) async { if (from == 1) { await m.addColumn(todos, todos.dueDate); } // ... more migrations }, ); } } ``` -------------------------------- ### CMake Project Setup and Build Configuration Source: https://github.com/simolus3/drift/blob/develop/examples/encryption/windows/CMakeLists.txt Initializes the CMake project, sets the minimum required version, defines the project name and languages, and configures build types (Debug, Profile, Release) based on whether the generator supports multi-configuration builds. It also sets default build types if not explicitly defined. ```cmake cmake_minimum_required(VERSION 3.14) project(drift_encryption_sample LANGUAGES CXX) set(BINARY_NAME "drift_encryption_sample") cmake_policy(VERSION 3.14...3.25) get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(IS_MULTICONFIG) set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" CACHE STRING "" FORCE) else() if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Flutter build mode" FORCE) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Profile" "Release") endif() endif() set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") ``` -------------------------------- ### Run MariaDB Docker Container Source: https://github.com/simolus3/drift/blob/develop/extras/drift_mariadb/README.md This command starts a MariaDB instance in a Docker container, exposing port 3306 and setting up a root password and database. This is required for testing the drift_mariadb package. ```bash docker run -p 3306:3306 -e MARIADB_ROOT_PASSWORD=password -e MARIADB_DATABASE=database mariadb:latest ``` -------------------------------- ### Initialize Drift Database in Dart Source: https://github.com/simolus3/drift/blob/develop/docs/content/sql_api/drift_files.md Basic setup for a Drift database class that uses generated code from drift files. It requires the generated _$MyDb superclass. ```dart import 'package:drift/drift.dart'; import 'database.g.dart'; @DriftDatabase(include: {'tables.drift'}) class MyDatabase extends _$MyDb { MyDatabase(super.e); @override int get schemaVersion => 1; } ``` -------------------------------- ### Initialize Existing Database with package:drift/native.dart Source: https://github.com/simolus3/drift/blob/develop/docs/content/examples/existing_databases.md This code snippet shows how to initialize a Drift database using an existing SQLite file with `package:drift/native.dart`. It employs `LazyDatabase` to manage the asynchronous loading and setup of the database, ensuring it's ready before use. This method is intended for native platform development. ```dart LazyDatabase _openConnection() { return LazyDatabase(() async { final dbFolder = await getApplicationDocumentsDirectory(); final file = File(join(dbFolder.path, 'my_database.db')); if (!await file.exists()) { final byteData = await rootBundle.load('assets/my_database.db'); final buffer = byteData.buffer; await file.writeAsBytes(buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes)); } return NativeDatabase.createBackgroundConnection(file); }); } ``` -------------------------------- ### Open Drift Database with drift_flutter Source: https://github.com/simolus3/drift/blob/develop/drift_flutter/README.md Demonstrates how to use the `driftDatabase` method to initialize a Drift database instance within a Flutter application. This method simplifies the setup process by abstracting platform-specific configurations. ```dart import 'package:drift/drift.dart'; import 'package:drift_flutter/drift_flutter.dart'; @DriftDatabase(...) final class MyAppDatabase extends _$MyAppDatabase { // Keeping a custom constructor is useful for unit tests which may want to // open an in-memory database only. MyAppDatabase(super.e); MyAppDatabase.defaults(): super(driftDatabase(name: 'app_db')); } ``` -------------------------------- ### Build Drift Documentation Source: https://github.com/simolus3/drift/blob/develop/docs/README.md Execute this script to build the Drift project website. ```shell ./tool/build.sh ``` -------------------------------- ### CMake: Install Assets and AOT Library Source: https://github.com/simolus3/drift/blob/develop/extras/integration_tests/ffi_on_flutter/windows/CMakeLists.txt Handles the installation of the Flutter assets directory and the AOT (Ahead-Of-Time) compiled library. The assets directory is completely re-copied on each build to prevent stale files. The AOT library is installed only for Profile and Release configurations. ```cmake set(FLUTTER_ASSET_DIR_NAME "flutter_assets") install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" CONFIGURATIONS Profile;Release COMPONENT Runtime) ``` -------------------------------- ### Conditional Installation of AOT Library Source: https://github.com/simolus3/drift/blob/develop/examples/encryption/linux/CMakeLists.txt Installs the Ahead-Of-Time (AOT) compiled library only for non-Debug build types. This optimizes performance for release builds. ```cmake if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endif() ``` -------------------------------- ### CMake Installation of AOT Library Source: https://github.com/simolus3/drift/blob/develop/examples/app/windows/CMakeLists.txt Installs the Ahead-Of-Time (AOT) compiled library. This is conditionally included only for 'Profile' and 'Release' build configurations, not for 'Debug' builds. ```cmake install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" CONFIGURATIONS Profile;Release COMPONENT Runtime) ``` -------------------------------- ### CMake Installation of Native Assets and Flutter Assets Source: https://github.com/simolus3/drift/blob/develop/examples/app/windows/CMakeLists.txt Installs native assets and Flutter assets to the application bundle. It ensures that the assets directory is fully re-copied on each build to prevent stale files. ```cmake set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") install(DIRECTORY "${NATIVE_ASSETS_DIR}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) set(FLUTTER_ASSET_DIR_NAME "flutter_assets") install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) ``` -------------------------------- ### Switching to `make-migrations` Source: https://github.com/simolus3/drift/blob/develop/docs/content/migrations/index.md Steps to transition from Drift's older `schema` tools to the `make-migrations` command. ```APIDOC ### Switching to `make-migrations` If you've already been using the `schema` tools to write migrations, you can switch to `make-migrations` by following these steps: 1. Run the `make-migrations` command to generate the initial schema file. 2. Move all of your existing `schema` files into the schema directory for your database. 3. Run the `make-migrations` command again to generate the step-by-step migration file and test files. ``` -------------------------------- ### Initialize MyDatabase Singleton with GetX Source: https://github.com/simolus3/drift/blob/develop/docs/content/faq.md Illustrates how to register MyDatabase as a service using the GetX package in Flutter, making it accessible throughout the application. ```dart void main() { Get.put(MyDatabase()); runApp(MyFlutterApp()); } ``` -------------------------------- ### Configure Database Opening for Flutter (sqlite3) Source: https://github.com/simolus3/drift/blob/develop/docs/content/setup.md This code configures the Drift database to open using sqlite3 for a Flutter application. It demonstrates how to use `FlutterQueryExecutor.shared` for a default setup. It also includes an option for manual database setup with platform-specific workarounds for Android. ```dart import 'package:drift/drift.dart'; import 'package:flutter/foundation.dart'; // These imports are used in the manual setup example: // import 'package:path_provider/path_provider.dart'; // import 'package:path/path.dart' as p; // import 'package:sqlite3_flutter_libs/sqlite3_flutter_libs.dart'; // The name of the database class is customizable. 'AppDatabase' is just an example. @DriftDatabase(tables: [TodoItems]) class AppDatabase extends _$AppDatabase { AppDatabase() : super(FlutterQueryExecutor.shared); // A List of tables from the database. The names of the tables are customizable. @override Iterable> get allTables => allSchemaEntities.whereType>(); @override int get schemaVersion => 1; // Example of how to open the database in a Flutter app: // AppDatabase() : super(FlutterQueryExecutor.shared); // Example of manual database setup: /* AppDatabase() : super(LazyDatabase(() async { final dbFolder = await getApplicationDocumentsDirectory(); // Ensure that the path is a temporary directory on Android final file = File(p.join(dbFolder.path, 'db.sqlite')); // Also ensure that the correct platform specific sqlite library is loaded. if (kIsWeb) { await applyWebImplementation(); } return NativeDatabase.createBackgroundConnection(file); })); */ } class TodoItems extends Table { IntColumn get id => integer().autoIncrement()(); TextColumn get title => text().withLength(min: 1, max: 50)(); DateTimeColumn get dueDate => dateTime().nullable()(); BoolColumn get completed => boolean().withDefault(const Constant(false))(); } ``` -------------------------------- ### Run Server and Client Applications Source: https://github.com/simolus3/drift/blob/develop/examples/multi_package/README.md Launches the Drift server and client applications. The server uses Postgres, and the client uses SQLite. These commands assume the project is set up and dependencies are met. ```bash dart run server/bin/server.dart ``` ```bash dart run client/bin/client.dart ``` -------------------------------- ### GET /queries/custom-columns Source: https://github.com/simolus3/drift/blob/develop/docs/content/dart_api/select.md Demonstrates how to include complex expressions in select statements that are evaluated by the database engine. ```APIDOC ## GET /queries/custom-columns ### Description Allows the inclusion of complex expressions in select statements, which are computed directly by the database engine for efficiency. ### Method GET ### Endpoint /queries/custom-columns ### Request Example N/A (Dart API usage) ### Response #### Success Response (200) - **result** (List) - A list of rows containing the evaluated expressions. ``` -------------------------------- ### GET /queries/joins-and-aliases Source: https://github.com/simolus3/drift/blob/develop/docs/content/dart_api/select.md Explains how to use table aliases when joining the same table multiple times in a single query. ```APIDOC ## GET /queries/joins-and-aliases ### Description Uses table aliases to reference the same table multiple times within a single join operation, useful for mapping multiple foreign keys to the same reference table. ### Method GET ### Endpoint /queries/joins-and-aliases ### Request Example N/A (Dart API usage) ### Response #### Success Response (200) - **data** (Object) - The result set containing joined data with aliased table references. ``` -------------------------------- ### GET /queries/aggregation Source: https://github.com/simolus3/drift/blob/develop/docs/content/dart_api/select.md Covers aggregate functions like count and average using selectOnly to optimize query performance. ```APIDOC ## GET /queries/aggregation ### Description Performs data aggregation using functions like count and average. Uses `selectOnly` to avoid fetching unnecessary columns from the database. ### Method GET ### Endpoint /queries/aggregation ### Request Example N/A (Dart API usage) ### Response #### Success Response (200) - **value** (Number) - The aggregated result (e.g., count or average). ``` -------------------------------- ### Using stepByStep for Schema Migrations Source: https://github.com/simolus3/drift/blob/develop/docs/content/migrations/step_by_step.md Demonstrates how to use the `stepByStep` utility generated by `drift_dev schema steps` to manage incremental database schema migrations. ```APIDOC ## Using stepByStep for Schema Migrations ### Description This example shows how to integrate the `stepByStep` migration strategy into your Drift database class. The `stepByStep` function, generated by `drift_dev schema steps`, provides a structured way to define migrations between schema versions, ensuring that each migration function has access to the schema of the target version. ### Method `onUpgrade` callback within `MigrationStrategy` ### Endpoint N/A (Code implementation detail) ### Parameters N/A ### Request Example ```dart // This is the default file generated by make-migrations. When you invoke `drift_dev schema steps` // manually, you control the name and path of the generated file. import 'database.steps.dart'; @DriftDatabase() class Database extends _$Database { // Constructor and other methods @override MigrationStrategy get migration { return MigrationStrategy( onUpgrade: stepByStep( from1To2: (m, schema) async { await m.addColumn(schema.users, schema.users.birthdate); }, from2To3: (m, schema) async { await m.deleteTable('users'); }, ), ); } } ``` ### Response #### Success Response (200) N/A (This is a code implementation example) #### Response Example N/A ``` -------------------------------- ### Customizing step-by-step Migrations with Migrator.runMigrationSteps Source: https://github.com/simolus3/drift/blob/develop/docs/content/migrations/step_by_step.md Illustrates how to customize the `stepByStep` migration process by using `Migrator.runMigrationSteps` to add pre- and post-migration logic, such as managing foreign key constraints. ```APIDOC ## Customizing step-by-step Migrations with Migrator.runMigrationSteps ### Description This example demonstrates how to customize the `stepByStep` migration process by using the `Migrator.runMigrationSteps` helper. This allows for executing custom logic before and after a migration step, such as disabling and re-enabling foreign key checks or performing consistency checks. ### Method `Migrator.runMigrationSteps` ### Endpoint N/A (Code implementation detail) ### Parameters N/A ### Request Example ```dart // Assuming 'm' is the Migrator instance and 'schema' is the schema object await m.runMigrationSteps( // This is the schema version to migrate from. // If you are using `stepByStep`, this is the version that `stepByStep` will // run migrations for. from: schema.version, // Or a specific version number to: schema.version + 1, steps: [ // Custom steps can be added here if needed, but typically `stepByStep` handles this. ], before: (m) async { // Optional: Code to run before the migration steps. await m.disableForeignKeys(); }, after: (m) async { // Optional: Code to run after the migration steps. await m.checkIntegrity(); // Example: check database integrity await m.enableForeignKeys(); }, ); ``` ### Response #### Success Response (200) N/A (This is a code implementation example) #### Response Example N/A ``` -------------------------------- ### Add Drift Dependencies Source: https://github.com/simolus3/drift/blob/develop/docs/content/guides/migrating_to_drift.md Adds drift and related development dependencies to your pubspec.yaml file. This is the first step to start using drift in your project. ```yaml dependencies: drift: ^{{ versions.drift }} dev_dependencies: drift_dev: ^{{ versions.drift_dev }} build_runner: ^{{ versions.build_runner }} ``` ```bash dart pub add drift dev:drift_dev dev:build_runner ``` -------------------------------- ### Spawning a DriftIsolate Server Source: https://github.com/simolus3/drift/blob/develop/docs/content/isolates.md Demonstrates how to manually spawn a DriftIsolate server to share database connections across isolates. ```dart final driftIsolate = await DriftIsolate.spawn(() => MyDatabase(NativeDatabase(file))); ``` -------------------------------- ### Replace FlutterQueryExecutor with NativeDatabase in Dart Source: https://github.com/simolus3/drift/blob/develop/docs/content/platforms/vm.md This snippet shows how to replace the old FlutterQueryExecutor with the new NativeDatabase setup using LazyDatabase, getDatabasesPath from sqflite, and path.join. ```dart import 'package:sqflite/sqflite.dart' show getDatabasesPath; import 'package:path/path.dart' as p; LazyDatabase(() async { final dbFolder = await getDatabasesPath(); final file = File(p.join(dbFolder, 'db.sqlite')); return NativeDatabase(file); }) ``` -------------------------------- ### Initialize Database on Web Source: https://github.com/simolus3/drift/blob/develop/docs/content/platforms/web.md Use this function to provide an initial SQLite file when opening a database that doesn't exist on the web. Note that WAL mode is not supported. ```dart final database = await WasmDatabase.open(File('my_db.sqlite'), initializeDatabase: (db) async { await db.run... }); ``` -------------------------------- ### Initialize Drift Database with SqfliteQueryExecutor Source: https://github.com/simolus3/drift/blob/develop/drift_sqflite/README.md This code demonstrates how to initialize a Drift database using SqfliteQueryExecutor. It shows the necessary annotations for the database class and how to open the database connection in a specified folder. This is useful for projects that need a persistent local database. ```dart @DriftDatabase(tables: [Todos, Categories]) class MyDatabase extends _$MyDatabase { // we tell the database where to store the data with this constructor MyDatabase() : super(_openConnection()); // you should bump this number whenever you change or add a table definition. // Migrations are covered later in the documentation. @override int get schemaVersion => 1; } QueryExecutor _openConnection() { return SqfliteQueryExecutor.inDatabaseFolder(path: 'db.sqlite'); } ``` -------------------------------- ### Run Background Tasks with computeWithDatabase Source: https://github.com/simolus3/drift/blob/develop/docs/content/isolates.md Uses computeWithDatabase to perform heavy operations on a background isolate. It automatically handles the setup of communication ports and database synchronization. ```dart await computeWithDatabase( connect: () => MyDatabase(NativeDatabase.createInBackground(file)), computation: (db) async { await db.into(db.users).insert(UsersCompanion.insert(name: 'User')); }, ); ``` -------------------------------- ### Running Flutter with COOP and COEP Headers Source: https://github.com/simolus3/drift/blob/develop/docs/content/platforms/web.md This command demonstrates how to run the Flutter development server with the required Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers. These headers are necessary for certain web APIs used by Drift. ```bash flutter run --web-header=Cross-Origin-Opener-Policy=same-origin --web-header=Cross-Origin-Embedder-Policy=require-corp ``` -------------------------------- ### Testing User Creation and Updates with Drift Source: https://github.com/simolus3/drift/blob/develop/docs/content/testing.md Provides example unit tests for a Drift database, verifying user creation, retrieval via stream, and name updates. ```dart test('users can be created', () async { final id = await database.createUser('some user'); final user = await database.watchUserWithId(id).first; expect(user.name, 'some user'); }); test('stream emits a new user when the name updates', () async { final id = await database.createUser('first name'); final expectation = expectLater( database.watchUserWithId(id).map((user) => user.name), emitsInOrder(['first name', 'changed name']), ); await database.updateName(id, 'changed name'); await expectation; }); ``` -------------------------------- ### Utilize PostgreSQL-Specific Types in Drift Source: https://github.com/simolus3/drift/blob/develop/docs/content/platforms/postgres.md Example showcasing the use of PostgreSQL-specific types like UUID within Drift queries, mapping to native PostgreSQL column types. ```dart final id = uuid.v4(); await into(myTable).insert(MyTableData(id: PgTypes.uuid.fromJson(id))); ``` -------------------------------- ### Configure Drift Database in Background Isolate Source: https://github.com/simolus3/drift/blob/develop/docs/content/platforms/vm.md Demonstrates how to initialize a Drift database in a background isolate using NativeDatabase.createInBackground to prevent blocking the UI thread. ```dart final database = NativeDatabase.createInBackground(File('db.sqlite')); final myDb = MyDatabase(database); ``` -------------------------------- ### Generated Companion Class Structure Source: https://github.com/simolus3/drift/blob/develop/docs/content/dart_api/rows.md An example of a generated companion class used for handling partial rows, specifically for inserts where auto-incrementing primary keys are managed by the database. ```dart class UsersCompanion extends UpdateCompanion { final Value id; final Value username; const UsersCompanion({ this.id = const Value.absent(), this.username = const Value.absent(), }); UsersCompanion.insert({ this.id = const Value.absent(), required String username, }) : username = Value(username); @override Map toColumns(bool nullToAbsent) { return {}; } } ``` -------------------------------- ### Configure Application Executable and Dependencies Source: https://github.com/simolus3/drift/blob/develop/extras/integration_tests/ffi_on_flutter/linux/CMakeLists.txt Defines the main application executable, links necessary libraries like Flutter and GTK, and sets up build dependencies. It ensures the executable is placed in a specific directory to support relative resource loading. ```cmake add_executable(${BINARY_NAME} "main.cc" "my_application.cc" "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" ) apply_standard_settings(${BINARY_NAME}) target_link_libraries(${BINARY_NAME} PRIVATE flutter) target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) add_dependencies(${BINARY_NAME} flutter_assemble) ``` -------------------------------- ### Dart Code API Name Changes for Drift Source: https://github.com/simolus3/drift/blob/develop/docs/content/guides/upgrading.md This table outlines the changes in Dart API names when migrating from Moor to Drift. For example, `VmDatabase` in Moor is now `NativeDatabase` in Drift. ```dart // Moor: VmDatabase -> Drift: NativeDatabase // Moor: MoorIsolate -> Drift: DriftIsolate // Moor: MoorWebStorage -> Drift: DriftWebStorage // Moor: @UseMoor -> Drift: @DriftDatabase // Moor: @UseDao -> Drift: @DriftAccessor // Moor: MoorWrappedException -> Drift: DriftWrappedException // Moor: MoorRuntimeOptions -> Drift: DriftRuntimeOptions // Moor: moorRuntimeOptions -> Drift: driftRuntimeOptions // Moor: $mrjc and $mrjf -> Drift: Use Object.hash from dart:core // Moor: MoorServer -> Drift: DriftServer // Moor: FlutterQueryExecutor -> Drift: SqfliteQueryExecutor ``` -------------------------------- ### Define Database Schema with SQL Source: https://github.com/simolus3/drift/blob/develop/docs/content/guides/migrating_to_drift.md Shows how to define a database table using standard SQL CREATE TABLE statements within a Drift file and include it in the database configuration. ```dart openDatabase(..., onCreate: (db, version) async { await db.execute( 'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER, num REAL);'); }); ``` ```dart @DriftDatabase(include: {'schema.drift'}) ``` -------------------------------- ### Dart: Define Custom Primary Key Source: https://github.com/simolus3/drift/blob/develop/docs/content/dart_api/tables.md Shows how to define a custom primary key for a table by overriding the 'primaryKey' getter. This example sets the 'email' column as the primary key. ```dart class Users extends Table { TextColumn get email => text().clientDefault(() => '')(); ... @override Set> get primaryKey => {email}; } ``` -------------------------------- ### Use Pre-populated Database from Assets Source: https://github.com/simolus3/drift/blob/develop/docs/content/faq.md Explains how to initialize the drift database using a pre-populated database file included in the app's assets, falling back to asset loading if the database file doesn't exist. ```dart QueryExecutor databaseWithDefaultAsset(File file, String asset) { // A LazyDatabase lets us do async initialization work. return LazyDatabase(() async { if (!await file.exists()) { // Database does not exist yet, use default from asset final content = await rootBundle.load(asset); await file.parent.create(recursive: true); await file.writeAsBytes(content.buffer.asUint8List(0)); } }); } ``` -------------------------------- ### Implement Step-by-Step Migrations in Drift Source: https://github.com/simolus3/drift/blob/develop/docs/content/migrations/step_by_step.md Demonstrates how to use the generated stepByStep utility within a Drift database class to define incremental migration logic between specific schema versions. ```dart import 'database.steps.dart'; @DriftDatabase() class Database extends _$Database { @override MigrationStrategy get migration { return MigrationStrategy( onUpgrade: stepByStep( from1To2: (m, schema) async { await m.addColumn(schema.users, schema.users.birthdate); }, from2To3: (m, schema) async { await m.deleteTable('users'); }, ), ); } } ``` -------------------------------- ### Generated Row Class Structure Source: https://github.com/simolus3/drift/blob/develop/docs/content/dart_api/rows.md An example of the generated row class structure in Dart, demonstrating how Drift maps database columns to class fields with equality and hashing overrides. ```dart class User { final int id; final String username; const User({required this.id, required this.username}); @override String toString() { return 'User(id: $id, username: $username)'; } @override int get hashCode => Object.hash(id, username); @override bool operator ==(Object other) => identical(this, other) || (other is User && other.id == this.id && other.username == this.username); } ```