diff --git a/.gitignore b/.gitignore index d71d057..3a79a35 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,15 @@ nimcache/ *.a # OS -.DS_Store +.DS_Store + +# Temporary files +*.db + +# Compiled files +chat_sdk/* +!*.nim +apps/* +!*.nim nimble.develop nimble.paths diff --git a/apps/nim.cfg b/apps/nim.cfg new file mode 100644 index 0000000..d4a2be8 --- /dev/null +++ b/apps/nim.cfg @@ -0,0 +1 @@ +path = ".." \ No newline at end of file diff --git a/apps/run_migration.nim b/apps/run_migration.nim new file mode 100644 index 0000000..abf28e4 --- /dev/null +++ b/apps/run_migration.nim @@ -0,0 +1,12 @@ +import db_connector/db_sqlite +import chat_sdk/migration + +proc main() = + let db = open("test.db", "", "", "") + defer: + db.close() + + runMigrations(db) + +when isMainModule: + main() \ No newline at end of file diff --git a/chat_sdk.nimble b/chat_sdk.nimble index cd2c463..b7d1da0 100644 --- a/chat_sdk.nimble +++ b/chat_sdk.nimble @@ -1,22 +1,19 @@ # Package -version = "0.0.1" -author = "Waku Chat Team" -description = "Chat features over Waku" -license = "MIT" -srcDir = "src" - - +version = "0.0.1" +author = "Waku Chat Team" +description = "Chat features over Waku" +license = "MIT" +srcDir = "src" ### Dependencies -requires "nim >= 2.2.4", - "chronicles", - "chronos", - "db_connector", - "waku" +requires "nim >= 2.2.4", "chronicles", "chronos", "db_connector", "waku" task buildSharedLib, "Build shared library for C bindings": exec "nim c --mm:refc --app:lib --out:../library/c-bindings/libchatsdk.so chat_sdk/chat_sdk.nim" task buildStaticLib, "Build static library for C bindings": - exec "nim c --mm:refc --app:staticLib --out:../library/c-bindings/libchatsdk.a chat_sdk/chat_sdk.nim" + exec "nim c --mm:refc --app:staticLib --out:../library/c-bindings/libchatsdk.a chat_sdk/chat_sdk.nim" + +task migrate, "Run database migrations": + exec "nim c -r apps/run_migration.nim" diff --git a/chat_sdk/migration.nim b/chat_sdk/migration.nim new file mode 100644 index 0000000..8af88d3 --- /dev/null +++ b/chat_sdk/migration.nim @@ -0,0 +1,32 @@ +import os, sequtils, algorithm +import db_connector/db_sqlite +import chronicles + +proc ensureMigrationTable(db: DbConn) = + db.exec(sql""" + CREATE TABLE IF NOT EXISTS schema_migrations ( + filename TEXT PRIMARY KEY, + applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) + """) + +proc hasMigrationRun(db: DbConn, filename: string): bool = + for row in db.fastRows(sql"SELECT 1 FROM schema_migrations WHERE filename = ?", filename): + return true + return false + +proc markMigrationRun(db: DbConn, filename: string) = + db.exec(sql"INSERT INTO schema_migrations (filename) VALUES (?)", filename) + +proc runMigrations*(db: DbConn, dir = "migrations") = + info "Migration process starting up" + ensureMigrationTable(db) + let files = walkFiles(dir / "*.sql").toSeq().sorted() + for file in files: + if hasMigrationRun(db, file): + info "Migration already applied", file + else: + info "Applying migration", file + let sql = readFile(file) + db.exec(sql(sql)) + markMigrationRun(db, file) diff --git a/migrations/README.md b/migrations/README.md new file mode 100644 index 0000000..2aca949 --- /dev/null +++ b/migrations/README.md @@ -0,0 +1,9 @@ +## Database Migrations + +This directory contains SQL migration files for the Nim Chat SDK. + +Each migration file should be named in the format `NNN_description.sql`, where `NNN` is a zero-padded number indicating the order of the migration. For example, `001_create_user_table.sql` is the first migration. + +## Running Migrations + +If you want to install a test sqlite database with tables setup, you can run `nimble migrate` from the command line. This will execute all migration files in order, ensuring that your database schema is up to date. \ No newline at end of file