Skip to content

Commit

Permalink
get rid of AppDatabase in favour of free functions
Browse files Browse the repository at this point in the history
  • Loading branch information
vykut committed Dec 6, 2023
1 parent bcbedca commit fdc4613
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 235 deletions.
28 changes: 16 additions & 12 deletions FoodSpec.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@
EC7DC2892B1DF22900BC8FD5 /* FoodListReducerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC7DC2882B1DF22900BC8FD5 /* FoodListReducerTests.swift */; };
EC7DC28D2B1F32C400BC8FD5 /* GRDB in Frameworks */ = {isa = PBXBuildFile; productRef = EC7DC28C2B1F32C400BC8FD5 /* GRDB */; };
EC7DC2922B1F375100BC8FD5 /* Food.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC7DC2912B1F375100BC8FD5 /* Food.swift */; };
EC7DC2952B1F397D00BC8FD5 /* AppDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC7DC2932B1F397D00BC8FD5 /* AppDatabase.swift */; };
EC7DC2962B1F397D00BC8FD5 /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC7DC2942B1F397D00BC8FD5 /* Persistence.swift */; };
EC7DC2982B1F669D00BC8FD5 /* GRDBDatabaseClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC7DC2972B1F669D00BC8FD5 /* GRDBDatabaseClient.swift */; };
EC7DC2952B1F397D00BC8FD5 /* Database+Creation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC7DC2932B1F397D00BC8FD5 /* Database+Creation.swift */; };
EC7DC2982B1F669D00BC8FD5 /* DatabaseClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC7DC2972B1F669D00BC8FD5 /* DatabaseClient.swift */; };
EC9577B02B1869760082A0D1 /* FoodDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC9577AF2B1869760082A0D1 /* FoodDetails.swift */; };
EC9577B22B1872E60082A0D1 /* NutritionalValueCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC9577B12B1872E60082A0D1 /* NutritionalValueCard.swift */; };
ECA64C232B1DB18E0036EE4F /* Energy.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECA64C222B1DB18E0036EE4F /* Energy.swift */; };
Expand Down Expand Up @@ -60,9 +59,8 @@
EC7DC2882B1DF22900BC8FD5 /* FoodListReducerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FoodListReducerTests.swift; sourceTree = "<group>"; };
EC7DC28A2B1E02B600BC8FD5 /* FoodSpec.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = FoodSpec.xctestplan; sourceTree = "<group>"; };
EC7DC2912B1F375100BC8FD5 /* Food.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Food.swift; sourceTree = "<group>"; };
EC7DC2932B1F397D00BC8FD5 /* AppDatabase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDatabase.swift; sourceTree = "<group>"; };
EC7DC2942B1F397D00BC8FD5 /* Persistence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Persistence.swift; sourceTree = "<group>"; };
EC7DC2972B1F669D00BC8FD5 /* GRDBDatabaseClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GRDBDatabaseClient.swift; sourceTree = "<group>"; };
EC7DC2932B1F397D00BC8FD5 /* Database+Creation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Database+Creation.swift"; sourceTree = "<group>"; };
EC7DC2972B1F669D00BC8FD5 /* DatabaseClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseClient.swift; sourceTree = "<group>"; };
EC9577AF2B1869760082A0D1 /* FoodDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FoodDetails.swift; sourceTree = "<group>"; };
EC9577B12B1872E60082A0D1 /* NutritionalValueCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NutritionalValueCard.swift; sourceTree = "<group>"; };
ECA64C222B1DB18E0036EE4F /* Energy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Energy.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -179,13 +177,20 @@
path = Food;
sourceTree = "<group>";
};
EC864F852B207592004FE264 /* Database */ = {
isa = PBXGroup;
children = (
EC7DC2932B1F397D00BC8FD5 /* Database+Creation.swift */,
EC7DC2972B1F669D00BC8FD5 /* DatabaseClient.swift */,
);
path = Database;
sourceTree = "<group>";
};
ECA64C212B1C53380036EE4F /* Clients */ = {
isa = PBXGroup;
children = (
EC7DC2932B1F397D00BC8FD5 /* AppDatabase.swift */,
EC7DC2942B1F397D00BC8FD5 /* Persistence.swift */,
EC864F852B207592004FE264 /* Database */,
EC2799892B1B304900D9E4B0 /* ApiKeysClient.swift */,
EC7DC2972B1F669D00BC8FD5 /* GRDBDatabaseClient.swift */,
ECCA83F52B177A1400C9EF4D /* FoodClient.swift */,
EC7DC2862B1DC38100BC8FD5 /* UserDefaultsClient.swift */,
);
Expand Down Expand Up @@ -305,16 +310,15 @@
buildActionMask = 2147483647;
files = (
EC43E55C2B175A140007CD40 /* FoodList.swift in Sources */,
EC7DC2962B1F397D00BC8FD5 /* Persistence.swift in Sources */,
EC7DC2952B1F397D00BC8FD5 /* AppDatabase.swift in Sources */,
EC7DC2952B1F397D00BC8FD5 /* Database+Creation.swift in Sources */,
EC9577B02B1869760082A0D1 /* FoodDetails.swift in Sources */,
EC7DC2872B1DC38100BC8FD5 /* UserDefaultsClient.swift in Sources */,
EC2799902B1B390E00D9E4B0 /* FoodDetailsReducer.swift in Sources */,
ECCA83F82B177A1400C9EF4D /* FoodClient.swift in Sources */,
EC43E55A2B175A140007CD40 /* FoodSpecApp.swift in Sources */,
EC9577B22B1872E60082A0D1 /* NutritionalValueCard.swift in Sources */,
EC7DC2922B1F375100BC8FD5 /* Food.swift in Sources */,
EC7DC2982B1F669D00BC8FD5 /* GRDBDatabaseClient.swift in Sources */,
EC7DC2982B1F669D00BC8FD5 /* DatabaseClient.swift in Sources */,
EC4717A62B1C4DD5007B491C /* FoodListRow.swift in Sources */,
EC4717A42B1B8474007B491C /* Quantity.swift in Sources */,
ECA64C232B1DB18E0036EE4F /* Energy.swift in Sources */,
Expand Down
160 changes: 0 additions & 160 deletions FoodSpec/Clients/AppDatabase.swift

This file was deleted.

116 changes: 116 additions & 0 deletions FoodSpec/Clients/Database/Database+Creation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import Foundation
import GRDB
import os

func createAppDatabase() -> some DatabaseWriter {
do {
// Apply recommendations from
// <https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databaseconnections>
//
// Create the "Application Support/Database" directory if needed
let fileManager = FileManager.default
let appSupportURL = try fileManager.url(
for: .applicationSupportDirectory, in: .userDomainMask,
appropriateFor: nil, create: true)
let directoryURL = appSupportURL.appendingPathComponent("Database", isDirectory: true)

// Support for tests: delete the database if requested
if CommandLine.arguments.contains("-reset") {
try? fileManager.removeItem(at: directoryURL)
}

// Create the database folder if needed
try fileManager.createDirectory(at: directoryURL, withIntermediateDirectories: true)

// Open or create the database
let databaseURL = directoryURL.appendingPathComponent("db.sqlite")
NSLog("Database stored at \(databaseURL.path)")
let dbPool = try DatabasePool(
path: databaseURL.path,
// Use default AppDatabase configuration
configuration: createDatabaseConfiguration()
)

// Create the AppDatabase
try setupDatabase(dbPool)

return dbPool
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate.
//
// Typical reasons for an error here include:
// * The parent directory cannot be created, or disallows writing.
// * The database is not accessible, due to permissions or data protection when the device is locked.
// * The device is out of space.
// * The database could not be migrated to its latest schema version.
// Check the error message to determine what the actual problem was.
fatalError("Unresolved error \(error)")
}
}

fileprivate func setupDatabase(_ writer: any DatabaseWriter) throws {
var migrator = DatabaseMigrator()

#if DEBUG
// Speed up development by nuking the database when migrations change
// See <https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/migrations>
migrator.eraseDatabaseOnSchemaChange = true
#endif

migrator.registerMigration("createFood") { db in
// Create a table
// See <https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databaseschema>
try db.create(table: "food") { t in
t.autoIncrementedPrimaryKey("id")
t.column("name", .text).notNull().unique(onConflict: .replace)
t.column("energy", .double)
t.column("fatTotal", .double)
t.column("fatSaturated", .double)
t.column("protein", .double)
t.column("sodium", .double)
t.column("potassium", .double)
t.column("cholesterol", .double)
t.column("carbohydrates", .double)
t.column("fiber", .double)
t.column("sugar", .double)
}
}

// Migrations for future application versions will be inserted here:
// migrator.registerMigration(...) { db in
// ...
// }

try migrator.migrate(writer)
}

fileprivate func createDatabaseConfiguration(_ base: Configuration = Configuration()) -> Configuration {
var config = base

// An opportunity to add required custom SQL functions or
// collations, if needed:
// config.prepareDatabase { db in
// db.add(function: ...)
// }

// Log SQL statements if the `SQL_TRACE` environment variable is set.
// See <https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/database/trace(options:_:)>
if ProcessInfo.processInfo.environment["SQL_TRACE"] != nil {
let sqlLogger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "GRDB")
config.prepareDatabase { db in
db.trace {
sqlLogger.log(level: .debug, "\($0)")
}
}
}

#if DEBUG
// Protect sensitive information by enabling verbose debugging in
// DEBUG builds only.
// See <https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/configuration/publicstatementarguments>
config.publicStatementArguments = true
#endif

return config
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// GRDBDatabaseClient.swift
// DatabaseClient.swift
// FoodSpec
//
// Created by Victor Socaciu on 05/12/2023.
Expand All @@ -10,15 +10,15 @@ import GRDB
import ComposableArchitecture

@DependencyClient
struct GRDBDatabaseClient {
struct DatabaseClient {
var getRecentFoods: (_ sortedBy: Food.SortingStrategy, _ order: SortOrder) async throws -> [Food]
var insert: (_ food: Food) async throws -> Food
var delete: (_ food: Food) async throws -> Void
}

extension GRDBDatabaseClient: DependencyKey {
static var liveValue: GRDBDatabaseClient = {
let db = AppDatabase.shared.dbWriter
extension DatabaseClient: DependencyKey {
static var liveValue: DatabaseClient = {
let db = createAppDatabase()
return .init(
getRecentFoods: { sortedBy, order in
let column = sortedBy.column
Expand All @@ -41,12 +41,12 @@ extension GRDBDatabaseClient: DependencyKey {
)
}()

static let testValue: GRDBDatabaseClient = .init()
static let testValue: DatabaseClient = .init()
}

extension DependencyValues {
var grdbDatabaseClient: GRDBDatabaseClient {
get { self[GRDBDatabaseClient.self] }
set { self[GRDBDatabaseClient.self] = newValue }
var databaseClient: DatabaseClient {
get { self[DatabaseClient.self] }
set { self[DatabaseClient.self] = newValue }
}
}
Loading

0 comments on commit fdc4613

Please sign in to comment.