// // Resource.swift // Pods // // Created by Mauro Bender on 13/8/16. // // import Alamofire public protocol JSONSerializable { init( fromJSON json: [ String: AnyObject ] ) func toJSON() -> [ String: AnyObject ] } open class Resource { open let api: Api open let path: String open var responseKeyPath: String? = "response" open var paginationKeyPath: String? = "pagination" init( api: Api, path: String ) { self.api = api self.path = path } } // MARK: REQUESTS extension Resource { public func request( _ method: ApiMethod, path: String? = nil, parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = URLEncoding.default, headers: [String: String]? = nil, completion: @escaping (DataResponse) -> Void ) { let requestPath = path != nil ? "\(self.path)/\(path!)" : self.path api.request( method, path: requestPath, parameters: parameters, encoding: encoding, headers: headers, completion: completion ) } public func get( _ path: String? = nil, parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = URLEncoding.default, headers: [String: String]? = nil, completion: @escaping (DataResponse) -> Void ) { return request( .get, path: path, parameters: parameters, encoding: encoding, headers: headers, completion: completion) } public func post( _ path: String? = nil, parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = URLEncoding.default, headers: [String: String]? = nil, completion: @escaping (DataResponse) -> Void ) { return request( .post, path: path, parameters: parameters, encoding: encoding, headers: headers, completion: completion) } public func put( _ path: String? = nil, parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = URLEncoding.default, headers: [String: String]? = nil, completion: @escaping (DataResponse) -> Void ) { return request( .put, path: path, parameters: parameters, encoding: encoding, headers: headers, completion: completion) } public func patch( _ path: String? = nil, parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = URLEncoding.default, headers: [String: String]? = nil, completion: @escaping (DataResponse) -> Void ) { return request( .patch, path: path, parameters: parameters, encoding: encoding, headers: headers, completion: completion) } public func delete( _ path: String? = nil, parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = URLEncoding.default, headers: [String: String]? = nil, completion: @escaping (DataResponse) -> Void ) { return request( .delete, path: path, parameters: parameters, encoding: encoding, headers: headers, completion: completion) } } // MARK: CRUD extension Resource { public func item( _ id: Any, parameters: [ String: AnyObject ]? = nil, headers: [ String: String]? = nil, completion: @escaping ( ( ApiResult< T? > ) -> Void ) ) { get( "\(id)", parameters: parameters, headers: headers ) { response in completion( itemResult( response, keyPath: self.responseKeyPath ) ) } } public func list( _ parameters: [ String: AnyObject ]? = nil, headers: [ String: String]? = nil, completion: @escaping ( ( ApiResult< [T]? > ) -> Void ) ) { get( parameters: parameters, headers: headers ) { response in completion( listResult( response, keyPath: self.responseKeyPath ) ) } } public func paginate( _ parameters: [ String: AnyObject ]? = nil, headers: [ String: String]? = nil, completion: @escaping ( ( ApiResult< ([T], Pagination)? > ) -> Void ) ) { get( parameters: parameters, headers: headers ) { response in completion( paginatedListResult( response, keyPath: self.responseKeyPath, paginationKeyPath: self.paginationKeyPath ) ) } } public func create( _ item: T, parameters: [ String: AnyObject ]? = nil, headers: [ String: String]? = nil, encoding: ParameterEncoding = JSONEncoding.default, completion: @escaping ( ( ApiResult< T? > ) -> Void ) ) { var requestParameters = item.toJSON() if parameters != nil { requestParameters += parameters! } post( parameters: requestParameters, encoding: encoding, headers: headers ) { response in completion( itemResult( response, keyPath: self.responseKeyPath ) ) } } public func edit( _ id: Any, item: T, parameters: [ String: AnyObject ]? = nil, headers: [ String: String]? = nil, encoding: ParameterEncoding = JSONEncoding.default, completion: @escaping ( ( ApiResult< T? > ) -> Void ) ) { var requestParameters = item.toJSON() if parameters != nil { requestParameters += parameters! } patch( "\(id)", parameters: requestParameters, encoding: encoding, headers: headers ) { response in completion( itemResult( response, keyPath: self.responseKeyPath ) ) } } public func destroy( _ id: Any, parameters: [ String: AnyObject ]? = nil, headers: [ String: String]? = nil, completion: @escaping ( ( EmptyResult ) -> Void ) ) { delete( "\(id)", parameters: parameters, headers: headers ) { response in completion( emptyResult( response ) ) } } } // MARK: NESTED RESOURCES extension Resource { public func member( _ memberID: Any ) -> Resource { let memberPath = resourceMemberPath( memberID ) return Resource( api: api, path: memberPath ) } public func resource( _ resourcePath: String ) -> Resource { let nestedPath = nestedResourcePath( resourcePath ) return Resource( api: api, path: nestedPath ) } func resourceMemberPath( _ memberId: Any ) -> String { return "\(path)/\(memberId)" } func nestedResourcePath( _ nestedResourcePath: String ) -> String { return "\(path)/\(nestedResourcePath)" } }