YaniPayCore Framework
Package Swift partage entre toutes les plateformes Apple. Models, Protocols et Services reutilisables via Swift Package Manager.
Overview
YaniPayCoreest un module Swift Package Manager partage entre toutes les applications Apple de l'ecosysteme YaniPay. Il contient les Models,Protocols et Services agnostiques de plateforme, permettant une reutilisation maximale du code metier.
Le package utilise Swift 5.9+ avec le mode strict concurrencyactive, garantissant la surete des acces concurrents dans l'ensemble du code partage. Chaque application plateforme (iOS, watchOS, macOS, tvOS) importe ce package et le complete avec des couches UI et des integrations specifiques.
Architecture Modulaire
YaniPayCore est concu comme un module autonome sans dependance sur UIKit, SwiftUI ou tout framework specifique a une plateforme. Cela permet de le tester independamment et de le reutiliser sur toutes les cibles Apple.
Structure du Package
Le package suit la convention standard SPM avec une separation claire entre les sources, les tests et la declaration du package.
YaniPayCore/
├── Package.swift // SPM declaration (v5.9)
├── Sources/YaniPayCore/
│ ├── Models/ // Codable data models
│ ├── Protocols/ // Interface contracts
│ └── Services/ // Business logic
└── Tests/YaniPayCoreTests/Models/
Structures Codable pour User, Transaction, WalletPass et toutes les entites Core Data.
Protocols/
Contrats d'interface definissant les services, repositories et managers implementes par chaque plateforme.
Services/
Logique metier partagee : validation, calculs financiers, gestion des tokens et chiffrement.
Support Plateformes
YaniPayCore supporte l'ensemble des plateformes Apple avec des versions minimales et recommandees pour chaque OS.
| Plateforme | Minimum | Recommande | Statut |
|---|---|---|---|
| iOS | iOS 17+ | iOS 18.5 | Production |
| watchOS | watchOS 10+ | watchOS 11 | Beta |
| macOS | macOS 14+ | Sequoia 15 | Beta |
| tvOS | tvOS 17+ | tvOS 18 | Experimental |
Package.swift
Le fichier Package.swift declare le package avec support multi-plateforme. Deux variantes de la librairie sont exposees : dynamique (partage en memoire entre cibles) et statique (inlining pour les performances).
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "YaniPayCore",
platforms: [
.iOS(.v17),
.watchOS(.v10),
.macOS(.v14),
.tvOS(.v17)
],
products: [
.library(name: "YaniPayCore", type: .dynamic, targets: ["YaniPayCore"]),
.library(name: "YaniPayCoreStatic", type: .static, targets: ["YaniPayCore"]),
],
targets: [
.target(
name: "YaniPayCore",
path: "Sources/YaniPayCore",
swiftSettings: [.enableExperimentalFeature("StrictConcurrency")]
),
.testTarget(name: "YaniPayCoreTests", dependencies: ["YaniPayCore"]),
]
)YaniPayCore (Dynamic)
Librairie dynamique partagee en memoire entre les cibles. Recommande pour le developpement et les builds Debug afin de reduire les temps de compilation.
YaniPayCoreStatic (Static)
Librairie statique avec inlining complet. Recommande pour les builds Release et les soumissions App Store pour des performances optimales.
Core Data Entities
YaniPayCore definit les entites de donnees centrales utilisees par toutes les applications. Chaque entite est un struct Codable avec validation integree via des proprietes calculees.
User
Identite utilisateur avec authentification multi-facteurs et donnees biometriques.
Transaction
Mouvement financier avec montant en centimes, horodatage et suivi de statut.
WalletPass
Integration Apple Wallet pour les passes de paiement et fidelite.
YANIConversation
Historique des conversations avec l'assistant IA Y.A.N.I.
LoyaltyCard
Programme de fidelite marchand et cartes client associees.
Market / Store
Commercants partenaires et points de vente geolocalises.
MLInteraction
Donnees d'entrainement ML pour ameliorer les predictions on-device.
import Foundation
/// Represents a YaniPay user across all Apple platforms.
/// Conforms to Codable for persistence and Sendable for concurrency safety.
public struct User: Codable, Sendable, Identifiable {
public let id: UUID
public var fullName: String
public var email: String
public var phone: String?
public var pinHash: Data
public var biometricEnabled: Bool
public var createdAt: Date
public var updatedAt: Date
/// Masked email for display purposes (e.g., "j***@yanipay.com")
public var maskedEmail: String {
guard let atIndex = email.firstIndex(of: "@") else { return email }
let prefix = email[email.startIndex]
let domain = email[atIndex...]
return "\(prefix)***\(domain)"
}
}import Foundation
/// Financial transaction with amount stored in centimes to avoid floating-point errors.
public struct Transaction: Codable, Sendable, Identifiable {
public let id: UUID
public var amountInCentimes: Int64
public var currency: Currency
public var date: Date
public var merchantName: String?
public var status: TransactionStatus
public var category: TransactionCategory
/// Formatted amount for display (e.g., "10,99 EUR")
public var formattedAmount: String {
let value = Double(amountInCentimes) / 100.0
return String(format: "%.2f %@", value, currency.rawValue)
}
}
public enum TransactionStatus: String, Codable, Sendable {
case pending, completed, failed, refunded, cancelled
}
public enum Currency: String, Codable, Sendable {
case EUR, USD, GBP, YANI
}Strict Concurrency
YaniPayCore active le mode Strict Concurrency de Swift 5.9, qui sera le comportement par defaut dans Swift 6. Ce mode garantit que toutes les structures partagees entre threads sont thread-safe.
Swift Strict Concurrency
Le mode Strict Concurrency est active via le flag.enableExperimentalFeature("StrictConcurrency") dans Package.swift. Toutes les structures publiques doivent conformer au protocoleSendable. Les classes mutables doivent etre marquees comme@MainActor ou protegees par un actor.
// Struct immutables -> automatiquement Sendable
public struct User: Codable, Sendable { ... }
public struct Transaction: Codable, Sendable { ... }
// Actor pour les etats mutables partages
public actor WalletManager {
private var balance: Int64 = 0
public func deposit(amount: Int64) {
balance += amount
}
public func getBalance() -> Int64 {
return balance
}
}
// MainActor pour les services lies a l'UI
@MainActor
public final class TransactionViewModel: ObservableObject {
@Published public var transactions: [Transaction] = []
@Published public var isLoading: Bool = false
public func refresh() async {
isLoading = true
defer { isLoading = false }
transactions = await TransactionService.shared.fetchAll()
}
}Sendable
Toutes les structures de donnees conforment a Sendable pour un partage thread-safe.
Actor Isolation
Les etats mutables sont proteges par des actor pour eviter les data races.
MainActor
Les ViewModels utilisent @MainActor pour les mises a jour UI sur le thread principal.