Add Logger

This commit is contained in:
Matt Bruce 2026-01-14 16:17:20 -06:00
parent 5d39a3336f
commit c48f8fbc65
11 changed files with 83 additions and 9 deletions

8
.gitignore vendored
View File

@ -2,5 +2,9 @@
.build/ .build/
.swiftpm/ .swiftpm/
DerivedData/ DerivedData/
*.xcodeproj/project.xcworkspace/xcuserdata
*.xcodeproj/xcuserdata # Xcode User Data
xcuserdata/
*.xcodeproj/project.xcworkspace/xcuserdata/
*.xcodeproj/xcuserdata/
*.xcworkspace/xcuserdata/

View File

@ -5,5 +5,6 @@ INFOPLIST_KEY_CFBundleDisplayName = SecureStorage
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES
INFOPLIST_KEY_BaseBundleID = $(BASE_BUNDLE_ID) INFOPLIST_KEY_BaseBundleID = $(BASE_BUNDLE_ID)
INFOPLIST_KEY_TeamID = $(TEAM_ID) INFOPLIST_KEY_TeamID = $(TEAM_ID)
INFOPLIST_KEY_AppGroupID = $(APP_GROUP_ID)
CODE_SIGN_ENTITLEMENTS = SecureStorageSample/SecureStorageSample.entitlements CODE_SIGN_ENTITLEMENTS = SecureStorageSample/SecureStorageSample.entitlements

View File

@ -8,5 +8,6 @@ WATCHOS_DEPLOYMENT_TARGET = 10.0
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES
INFOPLIST_KEY_BaseBundleID = $(BASE_BUNDLE_ID) INFOPLIST_KEY_BaseBundleID = $(BASE_BUNDLE_ID)
INFOPLIST_KEY_TeamID = $(TEAM_ID) INFOPLIST_KEY_TeamID = $(TEAM_ID)
INFOPLIST_KEY_AppGroupID = $(APP_GROUP_ID)
CODE_SIGN_ENTITLEMENTS = SecureStorageSample Watch App/SecureStorageSample Watch App.entitlements CODE_SIGN_ENTITLEMENTS = SecureStorageSample Watch App/SecureStorageSample Watch App.entitlements

View File

@ -12,6 +12,7 @@ import SharedKit
@main @main
struct SecureStorageSampleApp: App { struct SecureStorageSampleApp: App {
init() { init() {
StorageServiceIdentifiers.logConfiguration()
_ = WatchConnectivityService.shared _ = WatchConnectivityService.shared
Task { Task {
// 1. Global Encryption Configuration // 1. Global Encryption Configuration

View File

@ -8,6 +8,7 @@
import SwiftUI import SwiftUI
import LocalData import LocalData
@MainActor
struct EncryptedStorageDemo: View { struct EncryptedStorageDemo: View {
@State private var logEntry = "" @State private var logEntry = ""
@State private var storedLogs: [String] = [] @State private var storedLogs: [String] = []

View File

@ -9,6 +9,7 @@ import SwiftUI
import LocalData import LocalData
import SharedKit import SharedKit
@MainActor
struct FileSystemDemo: View { struct FileSystemDemo: View {
@State private var profileName = "" @State private var profileName = ""
@State private var profileEmail = "" @State private var profileEmail = ""
@ -191,7 +192,14 @@ struct FileSystemDemo: View {
Task { Task {
do { do {
let key = StorageKeys.UserProfileFileKey(directory: selectedDirectory) let key = StorageKeys.UserProfileFileKey(directory: selectedDirectory)
storedProfile = try await StorageRouter.shared.get(key) let profile = try await StorageRouter.shared.get(key)
storedProfile = profile
// Sync to text fields
profileName = profile.name
profileEmail = profile.email
profileAge = profile.age.map(String.init) ?? ""
statusMessage = "✓ Loaded from file system" statusMessage = "✓ Loaded from file system"
} catch StorageError.notFound { } catch StorageError.notFound {
storedProfile = nil storedProfile = nil
@ -243,7 +251,14 @@ struct FileSystemDemo: View {
Task { Task {
do { do {
let key = StorageKeys.AppGroupUserProfileKey(directory: selectedDirectory) let key = StorageKeys.AppGroupUserProfileKey(directory: selectedDirectory)
appGroupProfile = try await StorageRouter.shared.get(key) let profile = try await StorageRouter.shared.get(key)
appGroupProfile = profile
// Sync to text fields
profileName = profile.name
profileEmail = profile.email
profileAge = profile.age.map(String.init) ?? ""
appGroupStatusMessage = "✓ App Group loaded from file system" appGroupStatusMessage = "✓ App Group loaded from file system"
} catch StorageError.notFound { } catch StorageError.notFound {
appGroupProfile = nil appGroupProfile = nil

View File

@ -8,6 +8,7 @@
import SwiftUI import SwiftUI
import LocalData import LocalData
@MainActor
struct KeychainDemo: View { struct KeychainDemo: View {
@State private var username = "" @State private var username = ""
@State private var password = "" @State private var password = ""
@ -141,6 +142,11 @@ struct KeychainDemo: View {
) )
let credential = try await StorageRouter.shared.get(key) let credential = try await StorageRouter.shared.get(key)
storedCredential = "Username: \(credential.username)\nPassword: ****" storedCredential = "Username: \(credential.username)\nPassword: ****"
// Sync to fields
username = credential.username
password = credential.password
statusMessage = "✓ Retrieved from Keychain" statusMessage = "✓ Retrieved from Keychain"
} catch StorageError.notFound { } catch StorageError.notFound {
storedCredential = "" storedCredential = ""

View File

@ -8,6 +8,7 @@
import SwiftUI import SwiftUI
import LocalData import LocalData
@MainActor
struct PlatformSyncDemo: View { struct PlatformSyncDemo: View {
@State private var settingValue = "" @State private var settingValue = ""
@State private var storedValue = "" @State private var storedValue = ""
@ -181,7 +182,9 @@ struct PlatformSyncDemo: View {
availability: selectedPlatform, availability: selectedPlatform,
syncPolicy: selectedSync syncPolicy: selectedSync
) )
storedValue = try await StorageRouter.shared.get(key) let value = try await StorageRouter.shared.get(key)
storedValue = value
settingValue = value // Sync to field
statusMessage = "✓ Loaded value" statusMessage = "✓ Loaded value"
} catch StorageError.notFound { } catch StorageError.notFound {
storedValue = "" storedValue = ""

View File

@ -8,6 +8,7 @@
import SwiftUI import SwiftUI
import LocalData import LocalData
@MainActor
struct UserDefaultsDemo: View { struct UserDefaultsDemo: View {
@State private var inputText = "" @State private var inputText = ""
@State private var storedValue = "" @State private var storedValue = ""
@ -155,7 +156,9 @@ struct UserDefaultsDemo: View {
Task { Task {
do { do {
let key = StorageKeys.AppVersionKey() let key = StorageKeys.AppVersionKey()
storedValue = try await StorageRouter.shared.get(key) let value = try await StorageRouter.shared.get(key)
storedValue = value
inputText = value // Sync to field
statusMessage = "✓ Loaded successfully" statusMessage = "✓ Loaded successfully"
} catch StorageError.notFound { } catch StorageError.notFound {
storedValue = "" storedValue = ""
@ -201,7 +204,9 @@ struct UserDefaultsDemo: View {
Task { Task {
do { do {
let key = StorageKeys.AppGroupUserDefaultsKey() let key = StorageKeys.AppGroupUserDefaultsKey()
appGroupStoredValue = try await StorageRouter.shared.get(key) let value = try await StorageRouter.shared.get(key)
appGroupStoredValue = value
inputText = value // Sync to field
statusMessage = "✓ App Group loaded successfully" statusMessage = "✓ App Group loaded successfully"
} catch StorageError.notFound { } catch StorageError.notFound {
appGroupStoredValue = "" appGroupStoredValue = ""

View File

@ -2,9 +2,10 @@ import Foundation
public enum StorageServiceIdentifiers { public enum StorageServiceIdentifiers {
public static var bundleIdentifier: String { public static var bundleIdentifier: String {
Bundle.main.object(forInfoDictionaryKey: "BaseBundleID") as? String ?? let identifier = Bundle.main.object(forInfoDictionaryKey: "BaseBundleID") as? String ??
Bundle.main.bundleIdentifier ?? Bundle.main.bundleIdentifier ??
"com.example.securestorage" "com.example.securestorage"
return identifier
} }
private static var teamIDPrefix: String { private static var teamIDPrefix: String {
@ -15,7 +16,17 @@ public enum StorageServiceIdentifiers {
} }
public static var appGroupIdentifier: String { public static var appGroupIdentifier: String {
"group.\(bundleIdentifier)" let identifier = Bundle.main.object(forInfoDictionaryKey: "AppGroupID") as? String ??
"group.\(bundleIdentifier.lowercased())"
return identifier
}
public static func logConfiguration() {
Logger.debug("--- STORAGE CONFIGURATION ---")
Logger.debug("Bundle ID: \(bundleIdentifier)")
Logger.debug("Team ID Prefix: \(teamIDPrefix)")
Logger.debug("App Group ID: \(appGroupIdentifier)")
Logger.debug("---------------------------")
} }
public static var keychainCredentials: String { public static var keychainCredentials: String {

View File

@ -0,0 +1,26 @@
import Foundation
/// Public logging utility for the SecureStorage workspace.
public enum Logger {
public static var isLoggingEnabled = true
public static func debug(_ message: String) {
#if DEBUG
if isLoggingEnabled {
print(" {SECURE_STORAGE} \(message)")
}
#endif
}
public static func error(_ message: String, error: Error? = nil) {
#if DEBUG
var logMessage = " {SECURE_STORAGE} ❌ \(message)"
if let error = error {
logMessage += " | Error: \(error.localizedDescription)"
}
if isLoggingEnabled {
print(logMessage)
}
#endif
}
}