Resource.swift 5.98 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//
//  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 ]
}

16
17
18
19
20
open class Resource {
	open let api: Api
	open let path: String
	open var responseKeyPath: String?   = "response"
	open var paginationKeyPath: String? = "pagination"
21
22
23
24
25
	
	init( api: Api, path: String ) {
		self.api  = api
		self.path = path
	}
26
27
28
29
}

// MARK: REQUESTS
extension Resource {
30
31
32
	public func request( _ method: ApiMethod, path: String? = nil,
	                     parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = URLEncoding.default,
	                     headers: [String: String]? = nil, completion: @escaping (DataResponse<Any>) -> Void )
33
34
35
36
37
38
	{
		let requestPath = path != nil ? "\(self.path)/\(path!)" : self.path
		api.request( method, path: requestPath, parameters: parameters, encoding: encoding,
		             headers: headers, completion: completion )
	}
	
39
40
	public func get( _ path: String? = nil, parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = URLEncoding.default,
	                 headers: [String: String]? = nil, completion: @escaping (DataResponse<Any>) -> Void )
41
	{
42
		return request( .get, path: path, parameters: parameters, encoding: encoding,
43
44
45
		                headers: headers, completion: completion)
	}
	
46
47
	public func post( _ path: String? = nil, parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = URLEncoding.default,
	                  headers: [String: String]? = nil, completion: @escaping (DataResponse<Any>) -> Void )
48
	{
49
		return request( .post, path: path, parameters: parameters, encoding: encoding,
50
51
52
		                headers: headers, completion: completion)
	}
	
53
54
	public func put( _ path: String? = nil, parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = URLEncoding.default,
	                 headers: [String: String]? = nil, completion: @escaping (DataResponse<Any>) -> Void )
55
	{
56
		return request( .put, path: path, parameters: parameters, encoding: encoding,
57
58
59
		                headers: headers, completion: completion)
	}
	
60
61
	public func patch( _ path: String? = nil, parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = URLEncoding.default,
	                 headers: [String: String]? = nil, completion: @escaping (DataResponse<Any>) -> Void )
62
	{
63
		return request( .patch, path: path, parameters: parameters, encoding: encoding,
64
65
66
		                headers: headers, completion: completion)
	}
	
67
68
	public func delete( _ path: String? = nil, parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = URLEncoding.default,
	                    headers: [String: String]? = nil, completion: @escaping (DataResponse<Any>) -> Void )
69
	{
70
		return request( .delete, path: path, parameters: parameters, encoding: encoding,
71
72
73
74
75
76
		                headers: headers, completion: completion)
	}
}

// MARK: CRUD
extension Resource {
77
78
	public func item<T: JSONSerializable>( _ id: Any, parameters: [ String: AnyObject ]? = nil,
	                 headers: [ String: String]? = nil, completion: @escaping ( ( ApiResult< T? > ) -> Void ) )
79
80
	{
		get( "\(id)", parameters: parameters, headers: headers ) { response in
81
			completion( itemResult( response, keyPath: self.responseKeyPath ) )
82
83
		}
	}
84
	
85
86
	public func list<T: JSONSerializable>( _ parameters: [ String: AnyObject ]? = nil,
	                 headers: [ String: String]? = nil, completion: @escaping ( (  ApiResult< [T]? > ) -> Void ) )
87
88
89
90
91
92
	{
		get( parameters: parameters, headers: headers ) { response in
			completion( listResult( response, keyPath: self.responseKeyPath ) )
		}
	}
	
93
94
	public func paginate<T: JSONSerializable>( _ parameters: [ String: AnyObject ]? = nil, headers: [ String: String]? = nil,
	                 completion: @escaping ( ( ApiResult< ([T], Pagination)? > ) -> Void ) )
95
96
	{
		get( parameters: parameters, headers: headers ) { response in
97
98
			completion( paginatedListResult( response,
				keyPath: self.responseKeyPath, paginationKeyPath: self.paginationKeyPath ) )
99
100
101
		}
	}
	
102
103
104
	public func create<T: JSONSerializable>( _ item: T, parameters: [ String: AnyObject ]? = nil,
	                   headers: [ String: String]? = nil, encoding: ParameterEncoding = JSONEncoding.default,
	                   completion: @escaping ( ( ApiResult< T? > ) -> Void ) )
105
106
107
108
109
	{
		var requestParameters = item.toJSON()
		if parameters != nil { requestParameters += parameters! }
		
		post( parameters: requestParameters, encoding: encoding, headers: headers ) { response in
110
			completion( itemResult( response, keyPath: self.responseKeyPath ) )
111
112
		}
	}
113
	
114
115
116
	public func edit<T: JSONSerializable>( _ id: Any, item: T, parameters: [ String: AnyObject ]? = nil,
	                   headers: [ String: String]? = nil, encoding: ParameterEncoding = JSONEncoding.default,
	                   completion: @escaping ( ( ApiResult< T? > ) -> Void ) )
117
118
119
120
121
122
123
124
125
	{
		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 ) )
		}
	}
	
126
127
	public func destroy( _ id: Any, parameters: [ String: AnyObject ]? = nil,
	                     headers: [ String: String]? = nil, completion: @escaping ( ( EmptyResult ) -> Void ) )
128
129
	{
		delete( "\(id)", parameters: parameters, headers: headers ) { response in
130
			completion( emptyResult( response ) )
131
132
		}
	}
133
134
135
136
}

// MARK: NESTED RESOURCES
extension Resource {
137
	public func member( _ memberID: Any ) -> Resource {
138
139
140
141
		let memberPath = resourceMemberPath( memberID )
		return Resource( api: api, path: memberPath )
	}
	
142
	public func resource( _ resourcePath: String ) -> Resource {
143
144
145
146
		let nestedPath = nestedResourcePath( resourcePath )
		return Resource( api: api, path: nestedPath )
	}
	
147
	func resourceMemberPath( _ memberId: Any ) -> String {
148
149
		return "\(path)/\(memberId)"
	}
150
	
151
	func nestedResourcePath( _ nestedResourcePath: String ) -> String {
152
153
154
		return "\(path)/\(nestedResourcePath)"
	}
}