Platform-independent foundation for the Specification Pattern in Swift.
SpecificationCore is a lightweight, platform-independent Swift package that provides the foundational components for building specification-based systems. It contains core protocols, type erasure wrappers, context providers, basic specifications, property wrappers, and macros necessary for implementing the Specification Pattern across all Swift platforms.
This package is extracted from SpecificationKit to provide a minimal, dependency-free core that can be used independently or as a foundation for platform-specific extensions.
- Specification - Base protocol for boolean specifications with composition operators
- DecisionSpec - Protocol for specifications that return typed results
- AsyncSpecification - Async/await support for asynchronous specifications
- ContextProviding - Protocol for providing evaluation context
- AnySpecification - Type-erased specification wrapper
- AnyAsyncSpecification - Type-erased async specification wrapper
- AnyDecisionSpec - Type-erased decision specification wrapper
- AnyContextProvider - Type-erased context provider wrapper
- EvaluationContext - Immutable context struct containing counters, events, flags, and user data
- DefaultContextProvider - Thread-safe singleton provider with mutable state
- MockContextProvider - Testing utility for controlled context scenarios
- PredicateSpec - Closure-based specification
- FirstMatchSpec - Priority-based decision specification
- MaxCountSpec - Counter limit checking
- CooldownIntervalSpec - Time-based cooldown
- TimeSinceEventSpec - Event timing validation
- DateRangeSpec - Date range checking
- DateComparisonSpec - Date comparison operators
- @Satisfies - Boolean specification evaluation
- @Decides - Non-optional decision with fallback
- @Maybe - Optional decision without fallback
- @AsyncSatisfies - Async specification evaluation
- @specs - Composite specification synthesis
- @AutoContext - Automatic context provider injection
- Swift 5.10+
- iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 6.0+
- Linux (Ubuntu 20.04+)
Add SpecificationCore to your Package.swift:
dependencies: [
.package(url: "https://github.com/yourusername/SpecificationCore.git", from: "0.1.0")
]Then add it to your target dependencies:
targets: [
.target(
name: "YourTarget",
dependencies: ["SpecificationCore"]
)
]import SpecificationCore
// Create a simple predicate specification
let isAdult = PredicateSpec<Int> { age in age >= 18 }
// Evaluate
let age = 25
print(isAdult.isSatisfiedBy(age)) // truelet isTeenager = PredicateSpec<Int> { age in age >= 13 && age < 20 }
let isMinor = PredicateSpec<Int> { age in age < 18 }
// Compose specifications
let isYoungAdult = isAdult.and(!isMinor)
let canVote = isAdult.or(isTeenager)struct User {
let age: Int
@Satisfies(using: PredicateSpec<Int> { $0 >= 18 })
var isAdult: Bool
}
// Usage
let user = User(age: 25)
print(user.isAdult) // Evaluates specification automatically// Setup context
DefaultContextProvider.shared.setCounter("loginAttempts", to: 3)
// Create specification using context
let loginAllowed = MaxCountSpec(counterKey: "loginAttempts", maximumCount: 5)
// Evaluate with context
let context = DefaultContextProvider.shared.currentContext()
print(loginAllowed.isSatisfiedBy(context)) // true (3 <= 5)enum DiscountTier { case none, basic, premium }
let discountDecision = FirstMatchSpec<EvaluationContext, DiscountTier>(
decisions: [
(MaxCountSpec(counterKey: "purchases", maximumCount: 10).not(), .premium),
(MaxCountSpec(counterKey: "purchases", maximumCount: 5).not(), .basic)
]
)
DefaultContextProvider.shared.setCounter("purchases", to: 7)
let context = DefaultContextProvider.shared.currentContext()
print(discountDecision.decide(context)) // Optional(.basic)import SpecificationCore
@specs
struct PaymentEligibility {
let hasValidPaymentMethod: PredicateSpec<User>
let hasActiveSubscription: PredicateSpec<User>
let isNotBlacklisted: PredicateSpec<User>
}
// Macro generates:
// - allSpecs: Specification
// - anySpec: SpecificationSpecificationCore follows a layered architecture:
- Foundation Layer - Core protocols and type erasure
- Context Layer - Evaluation context and providers
- Specifications Layer - Basic specification implementations
- Wrappers Layer - Property wrappers for declarative syntax
- Macros Layer - Compile-time code generation
All components are platform-independent and have zero dependencies on UI frameworks (SwiftUI, UIKit, AppKit).
SpecificationCore is designed to work on all Swift platforms:
- Apple Platforms: iOS, macOS, tvOS, watchOS
- Linux: Ubuntu 20.04+
- Windows: Windows 10+ (Swift 5.9+)
The package uses #if canImport(Combine) for optional Combine support, ensuring it compiles even on platforms without Combine.
SpecificationCore provides the platform-independent foundation.
SpecificationKit builds on SpecificationCore with:
- SwiftUI integrations (@ObservedSatisfies, @ObservedDecides, @ObservedMaybe)
- Platform-specific context providers (iOS, macOS, watchOS, tvOS)
- Advanced domain specifications (FeatureFlagSpec, SubscriptionStatusSpec)
- Performance profiling tools (PerformanceProfiler, SpecificationTracer)
- Example code and tutorials
If you only need core functionality without platform-specific features, use SpecificationCore alone for faster builds and minimal dependencies.
SpecificationCore is designed for high performance:
- Specification Evaluation: <1μs for simple predicates
- Context Creation: <1μs
- Type Erasure Overhead: <50ns
- Thread-Safe: All public APIs are concurrency-safe
SpecificationCore maintains >90% test coverage with comprehensive unit tests, integration tests, and performance benchmarks.
Run tests:
swift testRun tests with thread sanitizer:
swift test --sanitize=threadContributions are welcome! Please read our Contributing Guidelines first.
SpecificationCore is released under the MIT License. See LICENSE for details.
SpecificationCore is extracted from SpecificationKit to provide a platform-independent foundation for specification-based systems in Swift.