Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.prism.byescaleira.com/llms.txt

Use this file to discover all available pages before exploring further.

PrismFoundation is the base layer of the Prism SDK. Every other module depends on it, but it has no dependencies of its own—so you can adopt it in any Swift target without pulling in additional code. It covers the core primitives that recur throughout every Apple-platform app: structured data models, logging, analytics, locale management, persistence helpers, and typed error handling.

Installation

import PrismFoundation

Entities

PrismEntity is the base protocol for all data models in Prism. Conforming to it gives your struct Codable, Equatable, Hashable, CustomStringConvertible, and structured logging support in one declaration.
// Adopt PrismEntity to get Codable + logging for free
struct User: PrismEntity {
    var id: UUID
    var name: String
    var email: String
}

let user = User(id: UUID(), name: "Jane", email: "jane@example.com")
user.log()          // prints JSON via os.Logger
print(user)         // pretty JSON description
Arrays of PrismEntity values also conform automatically, so [User] supports .log() without any extra code.

Logging

Prism uses two logging protocols built on top of os.Logger. PrismLogger adds a single log() method to any type. Call it when you want to emit the current value to the system log. PrismSystemLogger is for concrete loggers that own a Logger instance and expose info, warning, and error methods. All built-in Prism modules use a PrismSystemLogger internally, so your logs stay consistent with the framework’s output in Console.app.
// PrismError automatically calls log() on throw, including failure reason
struct AuthError: PrismError {
    var errorDescription: String? { "Authentication failed" }
    var failureReason: String? { "Invalid token" }
    var recoverySuggestion: String? { "Sign in again to refresh your session" }
}

Analytics

PrismAnalyticsProvider is a provider-agnostic protocol for analytics backends. Implement it once and Prism’s UI components emit structured events to your backend automatically.
struct FirebaseAnalytics: PrismAnalyticsProvider {
    func track(_ event: PrismAnalyticsEvent) {
        Analytics.logEvent(event.name, parameters: event.parameters)
    }
}

// Register with your root view
ContentView()
    .prism(analytics: FirebaseAnalytics())
PrismAnalyticsEvent is a Sendable value type with a name, string parameters, and a timestamp. Prism ships pre-built event factories for common interactions:
FactoryEvent nameParameters
.buttonTap(label:testID:)button_taplabel, test_id
.screenView(name:route:)screen_viewscreen_name, route
.fieldInteraction(testID:action:)field_interactiontest_id, action
.carouselScroll(testID:index:)carousel_scrolltest_id, index
.tabSelect(testID:tab:)tab_selecttest_id, tab
.menuAction(testID:action:)menu_actiontest_id, action
.custom(_:parameters:)any stringany [String: String]

Locale

PrismLocale is an enumeration of eight supported locales with built-in formatting, currency, calendar, and right-to-left information:
PrismLocale.englishUS    // en_US, USD, Gregorian
PrismLocale.portugueseBR // pt_BR, BRL, Gregorian
PrismLocale.arabicSA     // ar_SA, SAR, Islamic Umm al-Qura, RTL
PrismLocale.japaneseJP   // ja_JP, JPY, Japanese calendar
// … and four more
For runtime language switching, use PrismLocaleManager. It’s an @Observable class that you inject into your app’s environment. Changing current propagates to all PrismUI components in the hierarchy, and the selection is persisted to UserDefaults by default.
@main struct MyApp: App {
    @State var localeManager = PrismLocaleManager()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .prism(localeManager: localeManager)
        }
    }
}

// Switch language at runtime
localeManager.current = .spanishES

User defaults

PrismDefaults wraps UserDefaults with full Codable type support and automatic JSON encoding and decoding.
let defaults = PrismDefaults()

// Store any Codable value
defaults.set(user, for: "currentUser")

// Retrieve it later
let saved: User? = defaults.get(for: "currentUser")

// Remove it
defaults.set(nil as User?, for: "currentUser")
It uses the prism.defaults suite name by default, keeping your app’s keys separate from standard defaults.

Date and number formatting

PrismDateFormatter is a protocol that wraps DateFormatter and hooks into PrismLocale.current automatically. Implement it to build locale-aware formatters with minimal boilerplate:
struct ISODateFormatter: PrismDateFormatter {
    var rawValue: DateFormatter {
        getFormatter(from: "yyyy-MM-dd")
    }
}

let formatter = ISODateFormatter()
let text = formatter.string(from: Date())       // "2026-04-28"
let date = formatter.date(from: "2026-01-01")   // Date?

Error types

PrismError extends Error with LocalizedError, CustomStringConvertible, and PrismLogger. The default log() implementation emits the error description, failure reason, and recovery suggestion to separate log levels automatically:
enum NetworkError: PrismError {
    case timeout

    var errorDescription: String? { "Request timed out" }
    var failureReason: String? { "The server did not respond within the timeout interval." }
    var recoverySuggestion: String? { "Check your connection and try again." }
}

// On throw, call log() to emit all three levels to Console
let error = NetworkError.timeout
error.log()

Bundle and file helpers

PrismBundle reads app metadata from Bundle.main.infoDictionary:
let bundle = PrismBundle()
bundle.applicationName       // "MyApp"
bundle.applicationIdentifier // "com.example.myapp"
bundle.applicationVersion    // "1.0.0"
bundle.applicationBuild      // "42"
bundle.operatingSystemVersion // OperatingSystemVersion
PrismFileManager resolves paths in the Documents directory and supports public and private storage compartments. Pass .private to automatically create an isolated subdirectory:
let fileManager = PrismFileManager()

let publicURL  = fileManager.path(with: "report.pdf")
let privateURL = fileManager.path(with: "token.json", privacy: .private)

let fileSize = fileManager.size(at: publicURL)  // e.g. "1.2 MB"
Use privacy: .private for any file that should not be visible in the Files app or shared via iCloud Drive.