From b3e6419ea260ac00f712681f787101aef9bc1116 Mon Sep 17 00:00:00 2001 From: nutcas3 Date: Fri, 17 Apr 2026 17:53:37 +0300 Subject: [PATCH] feat: Add Swift SDK Package.swift with NIO/AsyncAlgorithms and comprehensive Telecom Platform API integration - Add Package.swift with swift-tools-version 5.9 and platforms iOS 13+, macOS 10.15+, watchOS 6+, tvOS 13+ - Add dependencies: swift-nio 2.40.0, swift-async-algorithms 1.0.0 - Add TelecomSDK class with async/await support and TelecomConfig with 30s timeout, 3 retries - Add subscriber management: getSubscriber, listSubscribers with pagination/status filter, createSubscriber, updateSubscriber, --- sdk/swift/Package.swift | 34 ++ sdk/swift/Sources/TelecomSDK/TelecomSDK.swift | 299 ++++++++++++++++++ 2 files changed, 333 insertions(+) create mode 100644 sdk/swift/Package.swift create mode 100644 sdk/swift/Sources/TelecomSDK/TelecomSDK.swift diff --git a/sdk/swift/Package.swift b/sdk/swift/Package.swift new file mode 100644 index 0000000..50ddde2 --- /dev/null +++ b/sdk/swift/Package.swift @@ -0,0 +1,34 @@ +// swift-tools-version: 5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "TelecomSDK", + platforms: [ + .iOS(.v13), + .macOS(.v10_15), + .watchOS(.v6), + .tvOS(.v13) + ], + products: [ + .library( + name: "TelecomSDK", + targets: ["TelecomSDK"]), + ], + dependencies: [ + .package(url: "https://github.com/apple/swift-nio.git", from: "2.40.0"), + .package(url: "https://github.com/apple/swift-async-algorithms.git", from: "1.0.0"), + ], + targets: [ + .target( + name: "TelecomSDK", + dependencies: [ + .product(name: "NIO", package: "swift-nio"), + .product(name: "AsyncAlgorithms", package: "swift-async-algorithms"), + ]), + .testTarget( + name: "TelecomSDKTests", + dependencies: ["TelecomSDK"]), + ] +) diff --git a/sdk/swift/Sources/TelecomSDK/TelecomSDK.swift b/sdk/swift/Sources/TelecomSDK/TelecomSDK.swift new file mode 100644 index 0000000..54c1deb --- /dev/null +++ b/sdk/swift/Sources/TelecomSDK/TelecomSDK.swift @@ -0,0 +1,299 @@ +import Foundation +import NIO +import AsyncAlgorithms + +/// Telecom Platform Swift SDK +/// +/// Provides async/await support with Swift Concurrency for the Telecom Platform API. +public class TelecomSDK { + + // MARK: - Properties + + private let config: TelecomConfig + private let httpClient: HTTPClient + private let webSocketClient: WebSocketClient + + // MARK: - Initialization + + /// Initialize a new TelecomSDK instance + /// - Parameter config: Configuration for the SDK + public init(config: TelecomConfig = TelecomConfig()) { + self.config = config + self.httpClient = HTTPClient(config: config) + self.webSocketClient = WebSocketClient(config: config) + } + + // MARK: - Subscriber Management + + /// Get subscriber by ID + /// - Parameter id: Subscriber ID + /// - Returns: Subscriber information + public func getSubscriber(id: Int64) async throws -> Subscriber { + return try await httpClient.get(path: "/v1/subscribers/\(id)") + } + + /// List subscribers with pagination + /// - Parameters: + /// - page: Page number + /// - pageSize: Page size + /// - status: Optional status filter + /// - Returns: Paginated list of subscribers + public func listSubscribers( + page: Int = 1, + pageSize: Int = 50, + status: SubscriberStatus? = nil + ) async throws -> SubscriberList { + var queryParams: [String: String] = [ + "page": "\(page)", + "page_size": "\(pageSize)" + ] + + if let status = status { + queryParams["status"] = status.rawValue + } + + return try await httpClient.get(path: "/v1/subscribers", queryParams: queryParams) + } + + /// Create a new subscriber + /// - Parameter request: Create subscriber request + /// - Returns: Created subscriber + public func createSubscriber(request: CreateSubscriberRequest) async throws -> Subscriber { + return try await httpClient.post(path: "/v1/subscribers", body: request) + } + + /// Update an existing subscriber + /// - Parameters: + /// - id: Subscriber ID + /// - request: Update subscriber request + /// - Returns: Updated subscriber + public func updateSubscriber(id: Int64, request: UpdateSubscriberRequest) async throws -> Subscriber { + return try await httpClient.put(path: "/v1/subscribers/\(id)", body: request) + } + + /// Suspend a subscriber + /// - Parameter id: Subscriber ID + /// - Returns: Suspended subscriber + public func suspendSubscriber(id: Int64) async throws -> Subscriber { + return try await httpClient.post(path: "/v1/subscribers/\(id)/suspend") + } + + /// Activate a suspended subscriber + /// - Parameter id: Subscriber ID + /// - Returns: Activated subscriber + public func activateSubscriber(id: Int64) async throws -> Subscriber { + return try await httpClient.post(path: "/v1/subscribers/\(id)/activate") + } + + /// Terminate a subscriber + /// - Parameter id: Subscriber ID + /// - Returns: Success status + public func terminateSubscriber(id: Int64) async throws -> Bool { + return try await httpClient.delete(path: "/v1/subscribers/\(id)") + } + + // MARK: - Usage Management + + /// Get usage statistics for a subscriber + /// - Parameters: + /// - subscriberId: Subscriber ID + /// - startDate: Start date + /// - endDate: End date + /// - Returns: Usage statistics + public func getUsageStats( + subscriberId: Int64, + startDate: Date, + endDate: Date + ) async throws -> UsageStats { + let formatter = ISO8601DateFormatter() + formatter.timeZone = TimeZone.current + + let queryParams: [String: String] = [ + "start_date": formatter.string(from: startDate), + "end_date": formatter.string(from: endDate) + ] + + return try await httpClient.get( + path: "/v1/subscribers/\(subscriberId)/usage", + queryParams: queryParams + ) + } + + /// List usage events with filtering + /// - Parameters: + /// - subscriberId: Optional subscriber ID filter + /// - usageType: Optional usage type filter + /// - startDate: Optional start date filter + /// - endDate: Optional end date filter + /// - page: Page number + /// - pageSize: Page size + /// - Returns: Paginated list of usage events + public func listUsageEvents( + subscriberId: Int64? = nil, + usageType: UsageType? = nil, + startDate: Date? = nil, + endDate: Date? = nil, + page: Int = 1, + pageSize: Int = 50 + ) async throws -> UsageEventList { + var queryParams: [String: String] = [ + "page": "\(page)", + "page_size": "\(pageSize)" + ] + + if let subscriberId = subscriberId { + queryParams["subscriber_id"] = "\(subscriberId)" + } + + if let usageType = usageType { + queryParams["usage_type"] = usageType.rawValue + } + + if let startDate = startDate { + let formatter = ISO8601DateFormatter() + formatter.timeZone = TimeZone.current + queryParams["start_date"] = formatter.string(from: startDate) + } + + if let endDate = endDate { + let formatter = ISO8601DateFormatter() + formatter.timeZone = TimeZone.current + queryParams["end_date"] = formatter.string(from: endDate) + } + + return try await httpClient.get(path: "/v1/usage/events", queryParams: queryParams) + } + + /// Get real-time usage for a subscriber + /// - Parameter subscriberId: Subscriber ID + /// - Returns: Real-time usage data + public func getRealTimeUsage(subscriberId: Int64) async throws -> RealTimeUsage { + return try await httpClient.get(path: "/v1/subscribers/\(subscriberId)/realtime") + } + + // MARK: - Payment Management + + /// Create a payment transaction + /// - Parameter request: Create payment request + /// - Returns: Created payment transaction + public func createPaymentTransaction(request: CreatePaymentRequest) async throws -> PaymentTransaction { + return try await httpClient.post(path: "/v1/payments/transactions", body: request) + } + + /// Get payment transaction by ID + /// - Parameter transactionId: Transaction ID + /// - Returns: Payment transaction + public func getPaymentTransaction(transactionId: String) async throws -> PaymentTransaction { + return try await httpClient.get(path: "/v1/payments/transactions/\(transactionId)") + } + + /// List payment transactions with filtering + /// - Parameters: + /// - subscriberId: Optional subscriber ID filter + /// - status: Optional status filter + /// - page: Page number + /// - pageSize: Page size + /// - Returns: Paginated list of payment transactions + public func listPaymentTransactions( + subscriberId: Int64? = nil, + status: PaymentStatus? = nil, + page: Int = 1, + pageSize: Int = 50 + ) async throws -> PaymentTransactionList { + var queryParams: [String: String] = [ + "page": "\(page)", + "page_size": "\(pageSize)" + ] + + if let subscriberId = subscriberId { + queryParams["subscriber_id"] = "\(subscriberId)" + } + + if let status = status { + queryParams["status"] = status.rawValue + } + + return try await httpClient.get(path: "/v1/payments/transactions", queryParams: queryParams) + } + + // MARK: - Rating Plans + + /// List all available rating plans + /// - Returns: List of rating plans + public func listRatingPlans() async throws -> [RatingPlan] { + return try await httpClient.get(path: "/v1/rating-plans") + } + + /// Get rating plan by ID + /// - Parameter planId: Plan ID + /// - Returns: Rating plan + public func getRatingPlan(planId: String) async throws -> RatingPlan { + return try await httpClient.get(path: "/v1/rating-plans/\(planId)") + } + + // MARK: - System Management + + /// Get system statistics + /// - Returns: System statistics + public func getSystemStats() async throws -> SystemStats { + return try await httpClient.get(path: "/v1/system/stats") + } + + /// Get system health status + /// - Returns: Health status + public func getHealthStatus() async throws -> HealthStatus { + return try await httpClient.get(path: "/v1/health") + } + + // MARK: - WebSocket Support + + /// Connect to WebSocket for real-time updates + /// - Parameter messageHandler: Closure to handle WebSocket messages + /// - Returns: Async stream of WebSocket messages + public func connectWebSocket( + messageHandler: @escaping (WebSocketMessage) async -> Void + ) -> AsyncThrowingStream { + return try await webSocketClient.connect(messageHandler: messageHandler) + } + + // MARK: - GraphQL Support + + /// Execute a GraphQL query + /// - Parameters: + /// - query: GraphQL query string + /// - variables: Optional query variables + /// - Returns: GraphQL response + public func executeGraphQLQuery( + query: String, + variables: [String: Any]? = nil + ) async throws -> GraphQLResponse { + let request = GraphQLRequest(query: query, variables: variables ?? [:]) + return try await httpClient.post(path: "/graphql", body: request) + } +} + +// MARK: - Configuration + +/// Configuration for Telecom SDK +public struct TelecomConfig { + /// Base URL for the API server + public var apiURL: String + /// API key for authentication + public var apiKey: String? + /// Request timeout in seconds + public var timeout: TimeInterval + /// Maximum number of retry attempts + public var maxRetries: Int + + public init( + apiURL: String = "http://localhost:8000", + apiKey: String? = nil, + timeout: TimeInterval = 30.0, + maxRetries: Int = 3 + ) { + self.apiURL = apiURL + self.apiKey = apiKey + self.timeout = timeout + self.maxRetries = maxRetries + } +}