diff options
| author | Christian Cleberg <[email protected]> | 2026-04-22 13:47:37 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-04-22 13:47:37 -0500 |
| commit | 6c23daaaba2a954220ece2afa7193dbdcad55c22 (patch) | |
| tree | febfca71eba8a025374d993e7a39fdb13194af25 /DomainDig/UsageCreditService.swift | |
| parent | dcf4135ec376d357b8fafc0101a75b674e76329a (diff) | |
| download | domain-dig-6c23daaaba2a954220ece2afa7193dbdcad55c22.tar.gz domain-dig-6c23daaaba2a954220ece2afa7193dbdcad55c22.tar.bz2 domain-dig-6c23daaaba2a954220ece2afa7193dbdcad55c22.zip | |
feat(v3.2.0): add Data+ tier and external data integrations
- introduce Data+ tier for advanced data features
- add ownership history and DNS history
- expand subdomain discovery with external sources
- add domain pricing insights
- implement local usage/credit system
- integrate external data service layer with rate limiting
- extend export and CLI for Data+ features
Diffstat (limited to 'DomainDig/UsageCreditService.swift')
| -rw-r--r-- | DomainDig/UsageCreditService.swift | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/DomainDig/UsageCreditService.swift b/DomainDig/UsageCreditService.swift new file mode 100644 index 0000000..48f40be --- /dev/null +++ b/DomainDig/UsageCreditService.swift @@ -0,0 +1,73 @@ +import Foundation + +actor UsageCreditService { + static let shared = UsageCreditService() + + private struct CreditLedger: Codable { + let appVersion: String + var remainingByFeature: [UsageCreditFeature: Int] + } + + private let storageKey = "usageCredits.ledger" + private var ledger: CreditLedger + + init(defaults: UserDefaults = .standard) { + if let data = defaults.data(forKey: storageKey), + let decoded = try? JSONDecoder().decode(CreditLedger.self, from: data), + decoded.appVersion == AppVersion.current { + ledger = decoded + } else { + ledger = Self.makeLedger() + if let data = try? JSONEncoder().encode(ledger) { + defaults.set(data, forKey: storageKey) + } + } + } + + func status(for feature: UsageCreditFeature) -> UsageCreditStatus { + let total = feature.defaultAllowance + let remaining = ledger.remainingByFeature[feature] ?? total + return UsageCreditStatus( + feature: feature, + remaining: remaining, + total: total, + resetContext: "Resets with app version \(ledger.appVersion)" + ) + } + + func allStatuses() -> [UsageCreditStatus] { + UsageCreditFeature.allCases.map { status(for: $0) } + } + + func canUse(_ feature: UsageCreditFeature) -> Bool { + status(for: feature).remaining > 0 + } + + @discardableResult + func consume(_ feature: UsageCreditFeature) -> UsageCreditStatus { + let current = ledger.remainingByFeature[feature] ?? feature.defaultAllowance + ledger.remainingByFeature[feature] = max(0, current - 1) + persist() + return status(for: feature) + } + + func resetForCurrentVersion() { + ledger = Self.makeLedger() + persist() + } + + private static func makeLedger() -> CreditLedger { + CreditLedger( + appVersion: AppVersion.current, + remainingByFeature: Dictionary( + uniqueKeysWithValues: UsageCreditFeature.allCases.map { ($0, $0.defaultAllowance) } + ) + ) + } + + private func persist(defaults: UserDefaults = .standard) { + if let data = try? JSONEncoder().encode(ledger) { + defaults.set(data, forKey: storageKey) + } + } +} |
