Extrahiert die zuvor zweimal von Hand gebaute Plumbing aus pageta-native + nutriphi-native in ein Paket ManaEventSync (Counterpart zu @mana/event-sync): - Core: EventEnvelope (+clientId/payloadHash), JSONValue, ULID, JWTSubject, EventSyncError - EventStorage (SwiftData): parametrierbar (Store/App-Group/additionalModels/In-Memory), Outbox, Claim-Reattribute, Anonymous-Retention-Prune - Transport: SyncHTTPClient (+X-Schema-Hash/422), optionaler SyncWSClient - Crypto: CryptoProvider/NoOp/MasterKey (AES-GCM enc:1:), VaultClient — opt-in - EventSyncEngine: besitzt die Identität (makeEnvelope anon/echt), emit offline, signIn(realUserId) re-taggt idempotent + drained, Retention 10k/90d 18 Tests grün. Plan: mana/docs/playbooks/MANA_SWIFT_EVENT_SYNC.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
22 lines
839 B
Swift
22 lines
839 B
Swift
import Foundation
|
|
|
|
/// Lexikografisch sortierbare ID. 26 Zeichen, Crockford-Base32.
|
|
///
|
|
/// Matched die ULID-Generierung in `@mana/event-sync` (gleicher
|
|
/// 12-Char-Zeitstempel + 14-Char-Random aus dem 32er-Alphabet), damit
|
|
/// IDs konsistent zwischen Web und Native sortieren.
|
|
public enum ULID {
|
|
private static let alphabet = Array("0123456789ABCDEFGHJKMNPQRSTVWXYZ")
|
|
|
|
public static func generate() -> String {
|
|
let millis = UInt64(Date().timeIntervalSince1970 * 1000)
|
|
let timePart = String(millis, radix: 16, uppercase: true)
|
|
.padding(toLength: 12, withPad: "0", startingAt: 0)
|
|
var random = ""
|
|
for _ in 0 ..< 14 {
|
|
let idx = Int.random(in: 0 ..< alphabet.count)
|
|
random.append(alphabet[idx])
|
|
}
|
|
return String((timePart + random).prefix(26))
|
|
}
|
|
}
|