Merge pull request #27 from writefreely/refactor-wfclient-with-templates
Refactor WFClient with Templates
This commit is contained in:
commit
a01bad4a25
|
@ -0,0 +1,18 @@
|
||||||
|
# Types
|
||||||
|
|
||||||
|
- [WFClient](/WFClient)
|
||||||
|
- [WFError](/WFError)
|
||||||
|
- [WFCollection](/WFCollection)
|
||||||
|
- [WFPost](/WFPost)
|
||||||
|
- [WFUser](/WFUser)
|
||||||
|
|
||||||
|
# Protocols
|
||||||
|
|
||||||
|
- [URLSessionProtocol](/URLSessionProtocol):
|
||||||
|
Define requirements for `URLSession`s here for dependency-injection purposes (specifically, for testing).
|
||||||
|
- [URLSessionDataTaskProtocol](/URLSessionDataTaskProtocol):
|
||||||
|
Define requirements for `URLSessionDataTask`s here for dependency-injection purposes (specifically, for testing).
|
||||||
|
|
||||||
|
# Extensions
|
||||||
|
|
||||||
|
- [URLSession](/URLSession)
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Extensions on URLSession
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
### `dataTask(with:completionHandler:)`
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public func dataTask(
|
||||||
|
with request: URLRequest,
|
||||||
|
completionHandler: @escaping DataTaskResult
|
||||||
|
) -> URLSessionDataTaskProtocol
|
||||||
|
```
|
|
@ -0,0 +1,15 @@
|
||||||
|
# URLSessionDataTaskProtocol
|
||||||
|
|
||||||
|
Define requirements for `URLSessionDataTask`s here for dependency-injection purposes (specifically, for testing).
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public protocol URLSessionDataTaskProtocol
|
||||||
|
```
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### resume()
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
func resume()
|
||||||
|
```
|
|
@ -0,0 +1,21 @@
|
||||||
|
# URLSessionProtocol
|
||||||
|
|
||||||
|
Define requirements for `URLSession`s here for dependency-injection purposes (specifically, for testing).
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public protocol URLSessionProtocol
|
||||||
|
```
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### DataTaskResult
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
typealias DataTaskResult = (Data?, URLResponse?, Error?) -> Void
|
||||||
|
```
|
||||||
|
|
||||||
|
### dataTask(with:completionHandler:)
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
func dataTask(with request: URLRequest, completionHandler: @escaping DataTaskResult) -> URLSessionDataTaskProtocol
|
||||||
|
```
|
|
@ -0,0 +1,373 @@
|
||||||
|
# WFClient
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public class WFClient
|
||||||
|
```
|
||||||
|
|
||||||
|
## Initializers
|
||||||
|
|
||||||
|
### `init(for:with:)`
|
||||||
|
|
||||||
|
Initializes the WriteFreely client.
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public init(for instanceURL: URL, with session: URLSessionProtocol = URLSession.shared)
|
||||||
|
```
|
||||||
|
|
||||||
|
Required for connecting to the API endpoints of a WriteFreely instance.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- instanceURL: The URL for the WriteFreely instance to which we're connecting, including the protocol.
|
||||||
|
- session: The URL session to use for connections; defaults to `URLSession.shared`.
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
### `requestURL`
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public var requestURL: URL
|
||||||
|
```
|
||||||
|
|
||||||
|
### `user`
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public var user: WFUser?
|
||||||
|
```
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
### `createCollection(token:withTitle:alias:completion:)`
|
||||||
|
|
||||||
|
Creates a new collection.
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public func createCollection(
|
||||||
|
token: String? = nil,
|
||||||
|
withTitle title: String,
|
||||||
|
alias: String? = nil,
|
||||||
|
completion: @escaping (Result<WFCollection, Error>) -> Void
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
If only a `title` is given, the server will generate and return an alias; in this case, clients should store
|
||||||
|
the returned `alias` for future operations.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- token: The access token for the user creating the collection.
|
||||||
|
- title: The title of the new collection.
|
||||||
|
- alias: The alias of the collection.
|
||||||
|
- completion: A handler for the returned `WFCollection` on success, or `Error` on failure.
|
||||||
|
|
||||||
|
### `getCollection(token:withAlias:completion:)`
|
||||||
|
|
||||||
|
Retrieves a collection's metadata.
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public func getCollection(
|
||||||
|
token: String? = nil,
|
||||||
|
withAlias alias: String,
|
||||||
|
completion: @escaping (Result<WFCollection, Error>) -> Void
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Collections can be retrieved without authentication. However, authentication is required for retrieving a
|
||||||
|
private collection or one with scheduled posts.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- token: The access token for the user retrieving the collection.
|
||||||
|
- alias: The alias for the collection to be retrieved.
|
||||||
|
- completion: A handler for the returned `WFCollection` on success, or `Error` on failure.
|
||||||
|
|
||||||
|
### `deleteCollection(token:withAlias:completion:)`
|
||||||
|
|
||||||
|
Permanently deletes a collection.
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public func deleteCollection(
|
||||||
|
token: String? = nil,
|
||||||
|
withAlias alias: String,
|
||||||
|
completion: @escaping (Result<Bool, Error>) -> Void
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Any posts in the collection are not deleted; rather, they are made anonymous.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- token: The access token for the user deleting the collection.
|
||||||
|
- alias: The alias for the collection to be deleted.
|
||||||
|
- completion: A hander for the returned `Bool` on success, or `Error` on failure.
|
||||||
|
|
||||||
|
### `getPosts(token:in:completion:)`
|
||||||
|
|
||||||
|
Retrieves an array of posts.
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public func getPosts(
|
||||||
|
token: String? = nil,
|
||||||
|
in collectionAlias: String? = nil,
|
||||||
|
completion: @escaping (Result<[WFPost], Error>) -> Void
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
If the `collectionAlias` argument is provided, an array of all posts in that collection is retrieved; if
|
||||||
|
omitted, an array of all posts created by the user whose access token is provided is retrieved.
|
||||||
|
|
||||||
|
Collection posts can be retrieved without authentication; however, authentication is required for retrieving a
|
||||||
|
private collection or one with scheduled posts.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- token: The access token for the user retrieving the posts.
|
||||||
|
- collectionAlias: The alias for the collection whose posts are to be retrieved.
|
||||||
|
- completion: A handler for the returned `[WFPost]` on success, or `Error` on failure.
|
||||||
|
|
||||||
|
### `movePost(token:postId:with:to:completion:)`
|
||||||
|
|
||||||
|
Moves a post to a collection.
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public func movePost(
|
||||||
|
token: String? = nil,
|
||||||
|
postId: String,
|
||||||
|
with modifyToken: String? = nil,
|
||||||
|
to collectionAlias: String?,
|
||||||
|
completion: @escaping (Result<Bool, Error>) -> Void
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
>
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- token: The access token for the user moving the post to a collection.
|
||||||
|
- postId: The ID of the post to add to the collection.
|
||||||
|
- modifyToken: The post's modify token; required if the post doesn't belong to the requesting user. If `collectionAlias` is `nil`, do not include a `modifyToken`.
|
||||||
|
- collectionAlias: The alias of the collection to which the post should be added; if `nil`, this removes the post from any collection.
|
||||||
|
- completion: A handler for the returned `Bool` on success, or `Error` on failure.
|
||||||
|
|
||||||
|
### `pinPost(token:postId:at:in:completion:)`
|
||||||
|
|
||||||
|
Pins a post to a collection.
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public func pinPost(
|
||||||
|
token: String? = nil,
|
||||||
|
postId: String,
|
||||||
|
at position: Int? = nil,
|
||||||
|
in collectionAlias: String,
|
||||||
|
completion: @escaping (Result<Bool, Error>) -> Void
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Pinning a post to a collection adds it as a navigation item in the collection/blog home page header, rather
|
||||||
|
than on the blog itself. While the API endpoint can take an array of posts, this function only accepts a single
|
||||||
|
post.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- token: The access token of the user pinning the post to the collection.
|
||||||
|
- postId: The ID of the post to be pinned.
|
||||||
|
- position: The numeric position in which to pin the post; if `nil`, will pin at the end of the list.
|
||||||
|
- collectionAlias: The alias of the collection to which the post should be pinned.
|
||||||
|
- completion: A handler for the `Bool` returned on success, or `Error` on failure.
|
||||||
|
|
||||||
|
### `unpinPost(token:postId:from:completion:)`
|
||||||
|
|
||||||
|
Unpins a post from a collection.
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public func unpinPost(
|
||||||
|
token: String? = nil,
|
||||||
|
postId: String,
|
||||||
|
from collectionAlias: String,
|
||||||
|
completion: @escaping (Result<Bool, Error>) -> Void
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Removes the post from a navigation item and puts it back on the blog itself. While the API endpoint can take an
|
||||||
|
array of posts, this function only accepts a single post.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- token: The access token of the user un-pinning the post from the collection.
|
||||||
|
- postId: The ID of the post to be un-pinned.
|
||||||
|
- collectionAlias: The alias of the collection to which the post should be un-pinned.
|
||||||
|
- completion: A handler for the `Bool` returned on success, or `Error` on failure.
|
||||||
|
|
||||||
|
### `createPost(token:post:in:completion:)`
|
||||||
|
|
||||||
|
Creates a new post.
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public func createPost(
|
||||||
|
token: String? = nil,
|
||||||
|
post: WFPost,
|
||||||
|
in collectionAlias: String? = nil,
|
||||||
|
completion: @escaping (Result<WFPost, Error>) -> Void
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Creates a new post. If a `collectionAlias` is provided, the post is published to that collection; otherwise, it
|
||||||
|
is posted to the user's Drafts.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- token: The access token of the user creating the post.
|
||||||
|
- post: The `WFPost` object to be published.
|
||||||
|
- collectionAlias: The collection to which the post should be published.
|
||||||
|
- completion: A handler for the `WFPost` object returned on success, or `Error` on failure.
|
||||||
|
|
||||||
|
### `getPost(token:byId:completion:)`
|
||||||
|
|
||||||
|
Retrieves a post.
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public func getPost(
|
||||||
|
token: String? = nil,
|
||||||
|
byId postId: String,
|
||||||
|
completion: @escaping (Result<WFPost, Error>) -> Void
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
The `WFPost` object returned may include additional data, including page views and extracted tags.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- token: The access token of the user retrieving the post.
|
||||||
|
- postId: The ID of the post to be retrieved.
|
||||||
|
- completion: A handler for the `WFPost` object returned on success, or `Error` on failure.
|
||||||
|
|
||||||
|
### `getPost(token:bySlug:from:completion:)`
|
||||||
|
|
||||||
|
Retrieves a post from a collection.
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public func getPost(
|
||||||
|
token: String? = nil,
|
||||||
|
bySlug slug: String,
|
||||||
|
from collectionAlias: String,
|
||||||
|
completion: @escaping (Result<WFPost, Error>) -> Void
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Collection posts can be retrieved without authentication. However, authentication is required for retrieving a
|
||||||
|
post from a private collection.
|
||||||
|
|
||||||
|
The `WFPost` object returned may include additional data, including page views and extracted tags.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- token: The access token of the user retrieving the post.
|
||||||
|
- slug: The slug of the post to be retrieved.
|
||||||
|
- collectionAlias: The alias of the collection from which the post should be retrieved.
|
||||||
|
- completion: A handler for the `WFPost` object returned on success, or `Error` on failure.
|
||||||
|
|
||||||
|
### `updatePost(token:postId:updatedPost:with:completion:)`
|
||||||
|
|
||||||
|
Updates an existing post.
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public func updatePost(
|
||||||
|
token: String? = nil,
|
||||||
|
postId: String,
|
||||||
|
updatedPost: WFPost,
|
||||||
|
with modifyToken: String? = nil,
|
||||||
|
completion: @escaping (Result<WFPost, Error>) -> Void
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that if the `updatedPost` object is provided without a title, the original post's title will be removed.
|
||||||
|
|
||||||
|
>
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- token: The access token for the user updating the post.
|
||||||
|
- postId: The ID of the post to be updated.
|
||||||
|
- updatedPost: The `WFPost` object with which to update the existing post.
|
||||||
|
- modifyToken: The post's modify token; required if the post doesn't belong to the requesting user.
|
||||||
|
- completion: A handler for the `WFPost` object returned on success, or `Error` on failure.
|
||||||
|
|
||||||
|
### `deletePost(token:postId:with:completion:)`
|
||||||
|
|
||||||
|
Deletes an existing post.
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public func deletePost(
|
||||||
|
token: String? = nil,
|
||||||
|
postId: String,
|
||||||
|
with modifyToken: String? = nil,
|
||||||
|
completion: @escaping (Result<Bool, Error>) -> Void
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
>
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- token: The access token for the user deleting the post.
|
||||||
|
- postId: The ID of the post to be deleted.
|
||||||
|
- modifyToken: The post's modify token; required if the post doesn't belong to the requesting user.
|
||||||
|
- completion: A handler for the `Bool` object returned on success, or `Error` on failure.
|
||||||
|
|
||||||
|
### `login(username:password:completion:)`
|
||||||
|
|
||||||
|
Logs the user in to their account on the WriteFreely instance.
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public func login(username: String, password: String, completion: @escaping (Result<WFUser, Error>) -> Void)
|
||||||
|
```
|
||||||
|
|
||||||
|
On successful login, the `WFClient`'s `user` property is set to the returned `WFUser` object; this allows
|
||||||
|
authenticated requests to be made without having to provide an access token.
|
||||||
|
|
||||||
|
It is otherwise not necessary to login the user if their access token is provided to the calling function.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- username: The user's username.
|
||||||
|
- password: The user's password.
|
||||||
|
- completion: A handler for the `WFUser` object returned on success, or `Error` on failure.
|
||||||
|
|
||||||
|
### `logout(token:completion:)`
|
||||||
|
|
||||||
|
Invalidates the user's access token.
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public func logout(token: String? = nil, completion: @escaping (Result<Bool, Error>) -> Void)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- token: The token to invalidate.
|
||||||
|
- completion: A handler for the `Bool` object returned on success, or `Error` on failure.
|
||||||
|
|
||||||
|
### `getUserData(token:completion:)`
|
||||||
|
|
||||||
|
Retrieves a user's basic data.
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public func getUserData(token: String? = nil, completion: @escaping (Result<Data, Error>) -> Void)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- token: The access token for the user to fetch.
|
||||||
|
- completion: A handler for the `Data` object returned on success, or `Error` on failure.
|
||||||
|
|
||||||
|
### `getUserCollections(token:completion:)`
|
||||||
|
|
||||||
|
Retrieves a user's collections.
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public func getUserCollections(token: String? = nil, completion: @escaping (Result<[WFCollection], Error>) -> Void)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- token: The access token for the user whose collections are to be retrieved.
|
||||||
|
- completion: A handler for the `[WFCollection]` object returned on success, or `Error` on failure.
|
|
@ -1,7 +1,7 @@
|
||||||
# WFCollection
|
# WFCollection
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
public struct WFCollection
|
public struct WFCollection
|
||||||
```
|
```
|
||||||
|
|
||||||
## Inheritance
|
## Inheritance
|
||||||
|
@ -15,7 +15,7 @@ public struct WFCollection
|
||||||
Creates a basic `WFCollection` object.
|
Creates a basic `WFCollection` object.
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
public init(title: String, alias: String?)
|
public init(title: String, alias: String?)
|
||||||
```
|
```
|
||||||
|
|
||||||
This initializer creates a bare-minimum `WFCollection` object for sending to the server; use the decoder-based
|
This initializer creates a bare-minimum `WFCollection` object for sending to the server; use the decoder-based
|
||||||
|
@ -25,22 +25,22 @@ If no `alias` parameter is provided, one will be generated by the server.
|
||||||
|
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
||||||
- title: - title: The title to give the Collection.
|
- title: The title to give the Collection.
|
||||||
- alias: - alias: The alias for the Collection.
|
- alias: The alias for the Collection.
|
||||||
|
|
||||||
### `init(from:)`
|
### `init(from:)`
|
||||||
|
|
||||||
Creates a `WFCollection` object from the server response.
|
Creates a `WFCollection` object from the server response.
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
public init(from decoder: Decoder) throws
|
public init(from decoder: Decoder) throws
|
||||||
```
|
```
|
||||||
|
|
||||||
Primarily used by the `WFClient` to create a `WFCollection` object from the JSON returned by the server.
|
Primarily used by the `WFClient` to create a `WFCollection` object from the JSON returned by the server.
|
||||||
|
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
||||||
- decoder: - decoder: The decoder to use for translating the server response to a Swift object.
|
- decoder: The decoder to use for translating the server response to a Swift object.
|
||||||
|
|
||||||
#### Throws
|
#### Throws
|
||||||
|
|
||||||
|
@ -51,47 +51,47 @@ Error thrown by the `try` attempt when decoding any given property.
|
||||||
### `alias`
|
### `alias`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var alias: String?
|
public var alias: String?
|
||||||
```
|
```
|
||||||
|
|
||||||
### `title`
|
### `title`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var title: String
|
public var title: String
|
||||||
```
|
```
|
||||||
|
|
||||||
### `description`
|
### `description`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var description: String?
|
public var description: String?
|
||||||
```
|
```
|
||||||
|
|
||||||
### `styleSheet`
|
### `styleSheet`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var styleSheet: String?
|
public var styleSheet: String?
|
||||||
```
|
```
|
||||||
|
|
||||||
### `isPublic`
|
### `isPublic`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var isPublic: Bool?
|
public var isPublic: Bool?
|
||||||
```
|
```
|
||||||
|
|
||||||
### `views`
|
### `views`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var views: Int?
|
public var views: Int?
|
||||||
```
|
```
|
||||||
|
|
||||||
### `email`
|
### `email`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var email: String?
|
public var email: String?
|
||||||
```
|
```
|
||||||
|
|
||||||
### `url`
|
### `url`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var url: String?
|
public var url: String?
|
||||||
```
|
```
|
|
@ -0,0 +1,101 @@
|
||||||
|
# WFError
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
public enum WFError: Int, Error
|
||||||
|
```
|
||||||
|
|
||||||
|
## Inheritance
|
||||||
|
|
||||||
|
`Error`, `Int`
|
||||||
|
|
||||||
|
## Enumeration Cases
|
||||||
|
|
||||||
|
### `badRequest`
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
case badRequest = 400
|
||||||
|
```
|
||||||
|
|
||||||
|
### `unauthorized`
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
case unauthorized = 401
|
||||||
|
```
|
||||||
|
|
||||||
|
### `forbidden`
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
case forbidden = 403
|
||||||
|
```
|
||||||
|
|
||||||
|
### `notFound`
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
case notFound = 404
|
||||||
|
```
|
||||||
|
|
||||||
|
### `methodNotAllowed`
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
case methodNotAllowed = 405
|
||||||
|
```
|
||||||
|
|
||||||
|
### `gone`
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
case gone = 410
|
||||||
|
```
|
||||||
|
|
||||||
|
### `preconditionFailed`
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
case preconditionFailed = 412
|
||||||
|
```
|
||||||
|
|
||||||
|
### `tooManyRequests`
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
case tooManyRequests = 429
|
||||||
|
```
|
||||||
|
|
||||||
|
### `internalServerError`
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
case internalServerError = 500
|
||||||
|
```
|
||||||
|
|
||||||
|
### `badGateway`
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
case badGateway = 502
|
||||||
|
```
|
||||||
|
|
||||||
|
### `serviceUnavailable`
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
case serviceUnavailable = 503
|
||||||
|
```
|
||||||
|
|
||||||
|
### `unknownError`
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
case unknownError = -1
|
||||||
|
```
|
||||||
|
|
||||||
|
### `couldNotComplete`
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
case couldNotComplete = -2
|
||||||
|
```
|
||||||
|
|
||||||
|
### `invalidResponse`
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
case invalidResponse = -3
|
||||||
|
```
|
||||||
|
|
||||||
|
### `invalidData`
|
||||||
|
|
||||||
|
``` swift
|
||||||
|
case invalidData = -4
|
||||||
|
```
|
|
@ -1,7 +1,7 @@
|
||||||
# WFPost
|
# WFPost
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
public struct WFPost
|
public struct WFPost
|
||||||
```
|
```
|
||||||
|
|
||||||
## Inheritance
|
## Inheritance
|
||||||
|
@ -15,7 +15,14 @@ public struct WFPost
|
||||||
Creates a basic `WFPost` object.
|
Creates a basic `WFPost` object.
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
public init(body: String, title: String? = nil, appearance: String? = nil, language: String? = nil, rtl: Bool? = nil, createdDate: Date? = nil)
|
public init(
|
||||||
|
body: String,
|
||||||
|
title: String? = nil,
|
||||||
|
appearance: String? = nil,
|
||||||
|
language: String? = nil,
|
||||||
|
rtl: Bool? = nil,
|
||||||
|
createdDate: Date? = nil
|
||||||
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
This initializer creates a bare-minimum `WFPost` object for sending to the server; use the decoder-based
|
This initializer creates a bare-minimum `WFPost` object for sending to the server; use the decoder-based
|
||||||
|
@ -26,26 +33,26 @@ the server.
|
||||||
|
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
||||||
- body: - body: The body text for the post.
|
- body: The body text for the post.
|
||||||
- title: - title: The title for the post.
|
- title: The title for the post.
|
||||||
- appearance: - appearance: The appearance for the post; one of `sans`, `serif`/`norm`, `wrap`, `mono`, or `code`. Defaults to `serif`.
|
- appearance: The appearance for the post; one of `sans`, `serif`/`norm`, `wrap`, `mono`, or `code`. Defaults to `serif`.
|
||||||
- language: - language: An ISO 639-1 language code.
|
- language: An ISO 639-1 language code.
|
||||||
- rtl: - rtl: Set to `true` to show content right-to-left.
|
- rtl: Set to `true` to show content right-to-left.
|
||||||
- createdDate: - createdDate: The published date for the post.
|
- createdDate: The published date for the post.
|
||||||
|
|
||||||
### `init(from:)`
|
### `init(from:)`
|
||||||
|
|
||||||
Creates a `WFPost` object from the server response.
|
Creates a `WFPost` object from the server response.
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
public init(from decoder: Decoder) throws
|
public init(from decoder: Decoder) throws
|
||||||
```
|
```
|
||||||
|
|
||||||
Primarily used by the `WFClient` to create a `WFPost` object from the JSON returned by the server.
|
Primarily used by the `WFClient` to create a `WFPost` object from the JSON returned by the server.
|
||||||
|
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
||||||
- decoder: - decoder: The decoder to use for translating the server response to a Swift object.
|
- decoder: The decoder to use for translating the server response to a Swift object.
|
||||||
|
|
||||||
#### Throws
|
#### Throws
|
||||||
|
|
||||||
|
@ -56,71 +63,71 @@ Error thrown by the `try` attempt when decoding any given property.
|
||||||
### `postId`
|
### `postId`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var postId: String?
|
public var postId: String?
|
||||||
```
|
```
|
||||||
|
|
||||||
### `slug`
|
### `slug`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var slug: String?
|
public var slug: String?
|
||||||
```
|
```
|
||||||
|
|
||||||
### `appearance`
|
### `appearance`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var appearance: String?
|
public var appearance: String?
|
||||||
```
|
```
|
||||||
|
|
||||||
### `language`
|
### `language`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var language: String?
|
public var language: String?
|
||||||
```
|
```
|
||||||
|
|
||||||
### `rtl`
|
### `rtl`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var rtl: Bool?
|
public var rtl: Bool?
|
||||||
```
|
```
|
||||||
|
|
||||||
### `createdDate`
|
### `createdDate`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var createdDate: Date?
|
public var createdDate: Date?
|
||||||
```
|
```
|
||||||
|
|
||||||
### `updatedDate`
|
### `updatedDate`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var updatedDate: Date?
|
public var updatedDate: Date?
|
||||||
```
|
```
|
||||||
|
|
||||||
### `title`
|
### `title`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var title: String?
|
public var title: String?
|
||||||
```
|
```
|
||||||
|
|
||||||
### `body`
|
### `body`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var body: String
|
public var body: String
|
||||||
```
|
```
|
||||||
|
|
||||||
### `tags`
|
### `tags`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var tags: [String]?
|
public var tags: [String]?
|
||||||
```
|
```
|
||||||
|
|
||||||
### `views`
|
### `views`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var views: Int?
|
public var views: Int?
|
||||||
```
|
```
|
||||||
|
|
||||||
### `collectionAlias`
|
### `collectionAlias`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var collectionAlias: String?
|
public var collectionAlias: String?
|
||||||
```
|
```
|
|
@ -1,7 +1,7 @@
|
||||||
# WFUser
|
# WFUser
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
public struct WFUser
|
public struct WFUser
|
||||||
```
|
```
|
||||||
|
|
||||||
## Inheritance
|
## Inheritance
|
||||||
|
@ -15,29 +15,29 @@ public struct WFUser
|
||||||
Creates a minimum `WFUser` object from a stored token.
|
Creates a minimum `WFUser` object from a stored token.
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
public init(token: String, username: String?)
|
public init(token: String, username: String?)
|
||||||
```
|
```
|
||||||
|
|
||||||
Use this when the client has already logged in a user and only needs to reconstruct the type from saved properties.
|
Use this when the client has already logged in a user and only needs to reconstruct the type from saved properties.
|
||||||
|
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
||||||
- token: - token: The user's access token
|
- token: The user's access token
|
||||||
- username: - username: The user's username (optional)
|
- username: The user's username (optional)
|
||||||
|
|
||||||
### `init(from:)`
|
### `init(from:)`
|
||||||
|
|
||||||
Creates a `WFUser` object from the server response.
|
Creates a `WFUser` object from the server response.
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
public init(from decoder: Decoder) throws
|
public init(from decoder: Decoder) throws
|
||||||
```
|
```
|
||||||
|
|
||||||
Primarily used by the `WFClient` to create a `WFUser` object from the JSON returned by the server.
|
Primarily used by the `WFClient` to create a `WFUser` object from the JSON returned by the server.
|
||||||
|
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
||||||
- decoder: - decoder: The decoder to use for translating the server response to a Swift object.
|
- decoder: The decoder to use for translating the server response to a Swift object.
|
||||||
|
|
||||||
#### Throws
|
#### Throws
|
||||||
|
|
||||||
|
@ -48,23 +48,23 @@ Error thrown by the `try` attempt when decoding any given property.
|
||||||
### `token`
|
### `token`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var token: String
|
public var token: String
|
||||||
```
|
```
|
||||||
|
|
||||||
### `username`
|
### `username`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var username: String?
|
public var username: String?
|
||||||
```
|
```
|
||||||
|
|
||||||
### `email`
|
### `email`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var email: String?
|
public var email: String?
|
||||||
```
|
```
|
||||||
|
|
||||||
### `createdDate`
|
### `createdDate`
|
||||||
|
|
||||||
``` swift
|
``` swift
|
||||||
var createdDate: Date?
|
public var createdDate: Date?
|
||||||
```
|
```
|
|
@ -0,0 +1 @@
|
||||||
|
Generated at 2021-05-20T15:56:24-0400 using [swift-doc](https://github.com/SwiftDocOrg/swift-doc) 1.0.0-beta.6.
|
|
@ -0,0 +1,25 @@
|
||||||
|
<details>
|
||||||
|
<summary>Types</summary>
|
||||||
|
|
||||||
|
- [WFClient](/WFClient)
|
||||||
|
- [WFCollection](/WFCollection)
|
||||||
|
- [WFError](/WFError)
|
||||||
|
- [WFPost](/WFPost)
|
||||||
|
- [WFUser](/WFUser)
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Protocols</summary>
|
||||||
|
|
||||||
|
- [URLSessionDataTaskProtocol](/URLSessionDataTaskProtocol)
|
||||||
|
- [URLSessionProtocol](/URLSessionProtocol)
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Extensions</summary>
|
||||||
|
|
||||||
|
- [URLSession](/URLSession)
|
||||||
|
|
||||||
|
</details>
|
|
@ -1,5 +1,7 @@
|
||||||
.DS_Store
|
.DS_Store
|
||||||
/.build
|
|
||||||
/Packages
|
/Packages
|
||||||
/*.xcodeproj
|
/*.xcodeproj
|
||||||
xcuserdata/
|
xcuserdata/
|
||||||
|
!/.build/
|
||||||
|
/.build/*
|
||||||
|
!/.build/documentation/
|
||||||
|
|
|
@ -13,8 +13,8 @@ You'll need Xcode 11.5 / Swift 5.2 installed along with the command line tools t
|
||||||
Additionally, documentation is generated by [SwiftDoc](https://github.com/SwiftDocOrg/swift-doc). After making any changes to the package's public API, you'll need to regenerate the docs; to do so, run the following commands in the terminal from the root directory of the package:
|
Additionally, documentation is generated by [SwiftDoc](https://github.com/SwiftDocOrg/swift-doc). After making any changes to the package's public API, you'll need to regenerate the docs; to do so, run the following commands in the terminal from the root directory of the package:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ rm -rf docs/
|
$ rm -rf .build/documentation
|
||||||
$ swift doc generate Sources --module-name WriteFreely --output docs
|
$ swift doc generate Sources --module-name WriteFreely
|
||||||
```
|
```
|
||||||
|
|
||||||
### Installing
|
### Installing
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct ServerData<T: Decodable>: Decodable {
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case code
|
||||||
|
case data
|
||||||
|
}
|
||||||
|
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
code = try container.decode(Int.self, forKey: .code)
|
||||||
|
data = try container.decode(T.self, forKey: .data)
|
||||||
|
}
|
||||||
|
|
||||||
|
let code: Int
|
||||||
|
let data: T
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NestedPostsJson: Decodable {
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case code
|
||||||
|
case data
|
||||||
|
|
||||||
|
enum PostKeys: String, CodingKey {
|
||||||
|
case posts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
let postsContainer = try container.nestedContainer(keyedBy: CodingKeys.PostKeys.self, forKey: .data)
|
||||||
|
data = try postsContainer.decode([WFPost].self, forKey: .posts)
|
||||||
|
}
|
||||||
|
|
||||||
|
let data: [WFPost]
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension WFClient {
|
||||||
|
|
||||||
|
/// Sends a `GET` request.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - request: The `URLRequest` for the `GET` request
|
||||||
|
/// - completion: A closure that captures a `Result` with a `Data` object on success, or a `WFError` on failure.
|
||||||
|
func get(with request: URLRequest, completion: @escaping (Result<Data, WFError>) -> Void) {
|
||||||
|
if request.httpMethod != "GET" {
|
||||||
|
preconditionFailure("Expected GET request, but got \(request.httpMethod ?? "nil")")
|
||||||
|
}
|
||||||
|
|
||||||
|
let dataTask = session.dataTask(with: request) { (data, response, error) in
|
||||||
|
if error != nil {
|
||||||
|
completion(.failure(.couldNotComplete))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
|
||||||
|
if let response = response as? HTTPURLResponse {
|
||||||
|
completion(.failure(WFError(rawValue: response.statusCode) ?? .invalidResponse))
|
||||||
|
} else {
|
||||||
|
completion(.failure(.invalidResponse))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let data = data else {
|
||||||
|
completion(.failure(.invalidData))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
completion(.success(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
dataTask.resume()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sends a `POST` request.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - request: The `URLRequest` for the `POST` request
|
||||||
|
/// - expecting: The status code expected to be returned by the server
|
||||||
|
/// - completion: A closure that captures a `Result` with a `Data` object on success, or a `WFError` on failure.
|
||||||
|
func post(
|
||||||
|
with request: URLRequest,
|
||||||
|
expecting statusCode: Int,
|
||||||
|
completion: @escaping (Result<Data, WFError>) -> Void
|
||||||
|
) {
|
||||||
|
if request.httpMethod != "POST" {
|
||||||
|
preconditionFailure("Expected POST request, but got \(request.httpMethod ?? "nil")")
|
||||||
|
}
|
||||||
|
|
||||||
|
let dataTask = session.dataTask(with: request) { (data, response, error) in
|
||||||
|
if error != nil {
|
||||||
|
completion(.failure(.couldNotComplete))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let response = response as? HTTPURLResponse, response.statusCode == statusCode else {
|
||||||
|
if let response = response as? HTTPURLResponse {
|
||||||
|
completion(.failure(WFError(rawValue: response.statusCode) ?? .invalidResponse))
|
||||||
|
} else {
|
||||||
|
completion(.failure(.invalidResponse))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let data = data else {
|
||||||
|
completion(.failure(.invalidData))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
completion(.success(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
dataTask.resume()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sends a `DELETE` request.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - request: The `URLRequest` for the `DELETE` request
|
||||||
|
/// - completion: A closure that captures a `Result` with a `Data` object on success, or a `WFError` on failure.
|
||||||
|
func delete(with request: URLRequest, completion: @escaping (Result<Data, WFError>) -> Void) {
|
||||||
|
if request.httpMethod != "DELETE" {
|
||||||
|
preconditionFailure("Expected DELETE request, but got \(request.httpMethod ?? "nil")")
|
||||||
|
}
|
||||||
|
|
||||||
|
let dataTask = session.dataTask(with: request) { (data, response, error) in
|
||||||
|
if error != nil {
|
||||||
|
completion(.failure(.couldNotComplete))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let response = response as? HTTPURLResponse, response.statusCode == 204 else {
|
||||||
|
if let response = response as? HTTPURLResponse {
|
||||||
|
completion(.failure(WFError(rawValue: response.statusCode) ?? .invalidResponse))
|
||||||
|
} else {
|
||||||
|
completion(.failure(.invalidResponse))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let data = data else {
|
||||||
|
completion(.failure(.invalidData))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
completion(.success(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
dataTask.resume()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,42 +1,23 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct ServerData<T: Decodable>: Decodable {
|
// MARK: - URLSession-related protocols
|
||||||
enum CodingKeys: String, CodingKey {
|
|
||||||
case code
|
|
||||||
case data
|
|
||||||
}
|
|
||||||
|
|
||||||
init(from decoder: Decoder) throws {
|
/// Define requirements for `URLSession`s here for dependency-injection purposes (specifically, for testing).
|
||||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
public protocol URLSessionProtocol {
|
||||||
code = try container.decode(Int.self, forKey: .code)
|
typealias DataTaskResult = (Data?, URLResponse?, Error?) -> Void
|
||||||
data = try container.decode(T.self, forKey: .data)
|
func dataTask(with request: URLRequest, completionHandler: @escaping DataTaskResult) -> URLSessionDataTaskProtocol
|
||||||
}
|
|
||||||
|
|
||||||
let code: Int
|
|
||||||
let data: T
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NestedPostsJson: Decodable {
|
/// Define requirements for `URLSessionDataTask`s here for dependency-injection purposes (specifically, for testing).
|
||||||
enum CodingKeys: String, CodingKey {
|
public protocol URLSessionDataTaskProtocol {
|
||||||
case code
|
func resume()
|
||||||
case data
|
|
||||||
|
|
||||||
enum PostKeys: String, CodingKey {
|
|
||||||
case posts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
init(from decoder: Decoder) throws {
|
|
||||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
||||||
let postsContainer = try container.nestedContainer(keyedBy: CodingKeys.PostKeys.self, forKey: .data)
|
|
||||||
data = try postsContainer.decode([WFPost].self, forKey: .posts)
|
|
||||||
}
|
|
||||||
|
|
||||||
let data: [WFPost]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Class definition
|
||||||
|
|
||||||
public class WFClient {
|
public class WFClient {
|
||||||
let decoder = JSONDecoder()
|
let decoder: JSONDecoder
|
||||||
|
let session: URLSessionProtocol
|
||||||
|
|
||||||
public var requestURL: URL
|
public var requestURL: URL
|
||||||
public var user: WFUser?
|
public var user: WFUser?
|
||||||
|
@ -45,11 +26,17 @@ public class WFClient {
|
||||||
///
|
///
|
||||||
/// Required for connecting to the API endpoints of a WriteFreely instance.
|
/// Required for connecting to the API endpoints of a WriteFreely instance.
|
||||||
///
|
///
|
||||||
/// - Parameter instanceURL: The URL for the WriteFreely instance to which we're connecting, including the protocol.
|
/// - Parameters:
|
||||||
public init(for instanceURL: URL) {
|
/// - instanceURL: The URL for the WriteFreely instance to which we're connecting, including the protocol.
|
||||||
|
/// - session: The URL session to use for connections; defaults to `URLSession.shared`.
|
||||||
|
public init(for instanceURL: URL, with session: URLSessionProtocol = URLSession.shared) {
|
||||||
|
decoder = JSONDecoder()
|
||||||
|
decoder.dateDecodingStrategy = .iso8601
|
||||||
|
|
||||||
|
self.session = session
|
||||||
|
|
||||||
// TODO: - Check that the protocol for instanceURL is HTTPS
|
// TODO: - Check that the protocol for instanceURL is HTTPS
|
||||||
requestURL = URL(string: "api/", relativeTo: instanceURL) ?? instanceURL
|
requestURL = URL(string: "api/", relativeTo: instanceURL) ?? instanceURL
|
||||||
decoder.dateDecodingStrategy = .iso8601
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Collection-related methods
|
// MARK: - Collection-related methods
|
||||||
|
@ -98,33 +85,19 @@ public class WFClient {
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
|
post(with: request, expecting: 201) { result in
|
||||||
// Something went wrong; return the error message.
|
switch result {
|
||||||
if let error = error {
|
case .success(let data):
|
||||||
completion(.failure(error))
|
do {
|
||||||
}
|
let collection = try self.decoder.decode(ServerData<WFCollection>.self, from: data)
|
||||||
|
completion(.success(collection.data))
|
||||||
if let response = response as? HTTPURLResponse {
|
} catch {
|
||||||
guard let data = data else { return }
|
|
||||||
|
|
||||||
// If we get a 201 CREATED, return the WFCollection as success; if not, return a WFError as failure.
|
|
||||||
if response.statusCode == 201 {
|
|
||||||
do {
|
|
||||||
let collection = try self.decoder.decode(ServerData<WFCollection>.self, from: data)
|
|
||||||
|
|
||||||
completion(.success(collection.data))
|
|
||||||
} catch {
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// We didn't get a 200 OK, so return a WFError
|
|
||||||
guard let error = self.translateWFError(fromServerResponse: data) else { return }
|
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
case .failure(let error):
|
||||||
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTask.resume()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves a collection's metadata.
|
/// Retrieves a collection's metadata.
|
||||||
|
@ -150,33 +123,19 @@ public class WFClient {
|
||||||
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
||||||
request.addValue(tokenToVerify, forHTTPHeaderField: "Authorization")
|
request.addValue(tokenToVerify, forHTTPHeaderField: "Authorization")
|
||||||
|
|
||||||
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
|
get(with: request) { result in
|
||||||
// Something went wrong; return the error message.
|
switch result {
|
||||||
if let error = error {
|
case .success(let data):
|
||||||
|
do {
|
||||||
|
let collection = try self.decoder.decode(ServerData<WFCollection>.self, from: data)
|
||||||
|
completion(.success(collection.data))
|
||||||
|
} catch {
|
||||||
|
completion(.failure(WFError.invalidData))
|
||||||
|
}
|
||||||
|
case .failure(let error):
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let response = response as? HTTPURLResponse {
|
|
||||||
guard let data = data else { return }
|
|
||||||
|
|
||||||
// If we get a 200 OK, return the WFUser as success; if not, return a WFError as failure.
|
|
||||||
if response.statusCode == 200 {
|
|
||||||
do {
|
|
||||||
let collection = try self.decoder.decode(ServerData<WFCollection>.self, from: data)
|
|
||||||
|
|
||||||
completion(.success(collection.data))
|
|
||||||
} catch {
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// We didn't get a 200 OK, so return a WFError
|
|
||||||
guard let error = self.translateWFError(fromServerResponse: data) else { return }
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTask.resume()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Permanently deletes a collection.
|
/// Permanently deletes a collection.
|
||||||
|
@ -202,48 +161,14 @@ public class WFClient {
|
||||||
request.addValue(tokenToVerify, forHTTPHeaderField: "Authorization")
|
request.addValue(tokenToVerify, forHTTPHeaderField: "Authorization")
|
||||||
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
||||||
|
|
||||||
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
|
delete(with: request) { result in
|
||||||
// Something went wrong; return the error message.
|
switch result {
|
||||||
if let error = error {
|
case .success(_):
|
||||||
// ⚠️ HACK: There's something that URLSession doesn't like about 204 NO CONTENT response that the API
|
completion(.success(true))
|
||||||
// server is returning. If we get back a "protocol error", the operation probably succeeded,
|
case .failure(let error):
|
||||||
// but URLSession is being pedantic/cranky and throwing an NSPOSIXErrorDomain error code 100.
|
completion(.failure(error))
|
||||||
// Here, we check for that error, make sure the token was invalidated, and only then fire the
|
|
||||||
// success case in the completion block.
|
|
||||||
let nsError = error as NSError
|
|
||||||
if nsError.code == 100 && nsError.domain == NSPOSIXErrorDomain {
|
|
||||||
// Confirm that the operation succeeded by testing for a 404 on the same token.
|
|
||||||
self.deleteCollection(withAlias: alias) { result in
|
|
||||||
do {
|
|
||||||
_ = try result.get()
|
|
||||||
completion(.failure(error))
|
|
||||||
} catch WFError.notFound {
|
|
||||||
completion(.success(true))
|
|
||||||
} catch WFError.unauthorized {
|
|
||||||
completion(.success(true))
|
|
||||||
} catch {
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let response = response as? HTTPURLResponse {
|
|
||||||
// We got a response. If it's a 204 NO CONTENT, return true as success;
|
|
||||||
// if not, return a WFError as failure.
|
|
||||||
if response.statusCode != 204 {
|
|
||||||
guard let data = data else { return }
|
|
||||||
guard let error = self.translateWFError(fromServerResponse: data) else { return }
|
|
||||||
completion(.failure(error))
|
|
||||||
} else {
|
|
||||||
completion(.success(true))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTask.resume()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Post-related methods
|
// MARK: - Post-related methods
|
||||||
|
@ -282,40 +207,27 @@ public class WFClient {
|
||||||
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
||||||
request.addValue(tokenToVerify, forHTTPHeaderField: "Authorization")
|
request.addValue(tokenToVerify, forHTTPHeaderField: "Authorization")
|
||||||
|
|
||||||
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
|
get(with: request) { result in
|
||||||
// Something went wrong; return the error message.
|
switch result {
|
||||||
if let error = error {
|
case .success(let data):
|
||||||
completion(.failure(error))
|
do {
|
||||||
}
|
// The response is formatted differently depending on if we're getting user posts or collection
|
||||||
|
// posts,so we need to determine what kind of structure we're decoding based on the
|
||||||
if let response = response as? HTTPURLResponse {
|
// collectionAlias argument.
|
||||||
guard let data = data else { return }
|
if collectionAlias != nil {
|
||||||
|
let post = try self.decoder.decode(NestedPostsJson.self, from: data)
|
||||||
// If we get a 200 OK, return the WFUser as success; if not, return a WFError as failure.
|
completion(.success(post.data))
|
||||||
if response.statusCode == 200 {
|
} else {
|
||||||
do {
|
let post = try self.decoder.decode(ServerData<[WFPost]>.self, from: data)
|
||||||
// The response is formatted differently depending on if we're getting user posts or collection
|
completion(.success(post.data))
|
||||||
// posts,so we need to determine what kind of structure we're decoding based on the
|
|
||||||
// collectionAlias argument.
|
|
||||||
if collectionAlias != nil {
|
|
||||||
let post = try self.decoder.decode(NestedPostsJson.self, from: data)
|
|
||||||
completion(.success(post.data))
|
|
||||||
} else {
|
|
||||||
let post = try self.decoder.decode(ServerData<[WFPost]>.self, from: data)
|
|
||||||
completion(.success(post.data))
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
}
|
||||||
} else {
|
} catch {
|
||||||
// We didn't get a 200 OK, so return a WFError.
|
|
||||||
guard let error = self.translateWFError(fromServerResponse: data) else { return }
|
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
case .failure(let error):
|
||||||
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTask.resume()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Moves a post to a collection.
|
/// Moves a post to a collection.
|
||||||
|
@ -368,27 +280,14 @@ public class WFClient {
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
|
post(with: request, expecting: 200) { result in
|
||||||
// Something went wrong; return the error message.
|
switch result {
|
||||||
if let error = error {
|
case .success(_):
|
||||||
|
completion(.success(true))
|
||||||
|
case .failure(let error):
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let response = response as? HTTPURLResponse {
|
|
||||||
guard let data = data else { return }
|
|
||||||
|
|
||||||
// If we get a 200 OK, return true as success; if not, return a WFError as failure.
|
|
||||||
if response.statusCode == 200 {
|
|
||||||
completion(.success(true))
|
|
||||||
} else {
|
|
||||||
// We didn't get a 200 OK, so return a WFError
|
|
||||||
guard let error = self.translateWFError(fromServerResponse: data) else { return }
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTask.resume()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pins a post to a collection.
|
/// Pins a post to a collection.
|
||||||
|
@ -442,27 +341,14 @@ public class WFClient {
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
|
post(with: request, expecting: 200) { result in
|
||||||
// Something went wrong; return the error message.
|
switch result {
|
||||||
if let error = error {
|
case .success(_):
|
||||||
|
completion(.success(true))
|
||||||
|
case .failure(let error):
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let response = response as? HTTPURLResponse {
|
|
||||||
guard let data = data else { return }
|
|
||||||
|
|
||||||
// If we get a 200 OK, return the WFUser as success; if not, return a WFError as failure.
|
|
||||||
if response.statusCode == 200 {
|
|
||||||
completion(.success(true))
|
|
||||||
} else {
|
|
||||||
// We didn't get a 200 OK, so return a WFError
|
|
||||||
guard let error = self.translateWFError(fromServerResponse: data) else { return }
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTask.resume()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unpins a post from a collection.
|
/// Unpins a post from a collection.
|
||||||
|
@ -503,27 +389,14 @@ public class WFClient {
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
|
post(with: request, expecting: 200) { result in
|
||||||
// Something went wrong; return the error message.
|
switch result {
|
||||||
if let error = error {
|
case .success(_):
|
||||||
|
completion(.success(true))
|
||||||
|
case .failure(let error):
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let response = response as? HTTPURLResponse {
|
|
||||||
guard let data = data else { return }
|
|
||||||
|
|
||||||
// If we get a 200 OK, return the WFUser as success; if not, return a WFError as failure.
|
|
||||||
if response.statusCode == 200 {
|
|
||||||
completion(.success(true))
|
|
||||||
} else {
|
|
||||||
// We didn't get a 200 OK, so return a WFError
|
|
||||||
guard let error = self.translateWFError(fromServerResponse: data) else { return }
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTask.resume()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new post.
|
/// Creates a new post.
|
||||||
|
@ -581,33 +454,19 @@ public class WFClient {
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
|
self.post(with: request, expecting: 201) { result in
|
||||||
// Something went wrong; return the error message.
|
switch result {
|
||||||
if let error = error {
|
case .success(let data):
|
||||||
completion(.failure(error))
|
do {
|
||||||
}
|
let post = try self.decoder.decode(ServerData<WFPost>.self, from: data)
|
||||||
|
completion(.success(post.data))
|
||||||
if let response = response as? HTTPURLResponse {
|
} catch {
|
||||||
guard let data = data else { return }
|
|
||||||
|
|
||||||
// If we get a 200 OK, return the WFPost as success; if not, return a WFError as failure.
|
|
||||||
if response.statusCode == 201 {
|
|
||||||
do {
|
|
||||||
let post = try self.decoder.decode(ServerData<WFPost>.self, from: data)
|
|
||||||
|
|
||||||
completion(.success(post.data))
|
|
||||||
} catch {
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// We didn't get a 200 OK, so return a WFError
|
|
||||||
guard let error = self.translateWFError(fromServerResponse: data) else { return }
|
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
case .failure(let error):
|
||||||
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTask.resume()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves a post.
|
/// Retrieves a post.
|
||||||
|
@ -632,33 +491,19 @@ public class WFClient {
|
||||||
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
||||||
request.addValue(tokenToVerify, forHTTPHeaderField: "Authorization")
|
request.addValue(tokenToVerify, forHTTPHeaderField: "Authorization")
|
||||||
|
|
||||||
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
|
get(with: request) { result in
|
||||||
// Something went wrong; return the error message.
|
switch result {
|
||||||
if let error = error {
|
case .success(let data):
|
||||||
completion(.failure(error))
|
do {
|
||||||
}
|
let post = try self.decoder.decode(ServerData<WFPost>.self, from: data)
|
||||||
|
completion(.success(post.data))
|
||||||
if let response = response as? HTTPURLResponse {
|
} catch {
|
||||||
guard let data = data else { return }
|
|
||||||
|
|
||||||
// If we get a 200 OK, return the WFUser as success; if not, return a WFError as failure.
|
|
||||||
if response.statusCode == 200 {
|
|
||||||
do {
|
|
||||||
let post = try self.decoder.decode(ServerData<WFPost>.self, from: data)
|
|
||||||
|
|
||||||
completion(.success(post.data))
|
|
||||||
} catch {
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// We didn't get a 200 OK, so return a WFError
|
|
||||||
guard let error = self.translateWFError(fromServerResponse: data) else { return }
|
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
case .failure(let error):
|
||||||
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTask.resume()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves a post from a collection.
|
/// Retrieves a post from a collection.
|
||||||
|
@ -689,33 +534,19 @@ public class WFClient {
|
||||||
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
||||||
request.addValue(tokenToVerify, forHTTPHeaderField: "Authorization")
|
request.addValue(tokenToVerify, forHTTPHeaderField: "Authorization")
|
||||||
|
|
||||||
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
|
get(with: request) { result in
|
||||||
// Something went wrong; return the error message.
|
switch result {
|
||||||
if let error = error {
|
case .success(let data):
|
||||||
completion(.failure(error))
|
do {
|
||||||
}
|
let post = try self.decoder.decode(ServerData<WFPost>.self, from: data)
|
||||||
|
completion(.success(post.data))
|
||||||
if let response = response as? HTTPURLResponse {
|
} catch {
|
||||||
guard let data = data else { return }
|
|
||||||
|
|
||||||
// If we get a 200 OK, return the WFUser as success; if not, return a WFError as failure.
|
|
||||||
if response.statusCode == 200 {
|
|
||||||
do {
|
|
||||||
let post = try self.decoder.decode(ServerData<WFPost>.self, from: data)
|
|
||||||
|
|
||||||
completion(.success(post.data))
|
|
||||||
} catch {
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// We didn't get a 200 OK, so return a WFError
|
|
||||||
guard let error = self.translateWFError(fromServerResponse: data) else { return }
|
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
case .failure(let error):
|
||||||
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTask.resume()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates an existing post.
|
/// Updates an existing post.
|
||||||
|
@ -762,33 +593,19 @@ public class WFClient {
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
|
post(with: request, expecting: 200) { result in
|
||||||
// Something went wrong; return the error message.
|
switch result {
|
||||||
if let error = error {
|
case .success(let data):
|
||||||
completion(.failure(error))
|
do {
|
||||||
}
|
let post = try self.decoder.decode(ServerData<WFPost>.self, from: data)
|
||||||
|
completion(.success(post.data))
|
||||||
if let response = response as? HTTPURLResponse {
|
} catch {
|
||||||
guard let data = data else { return }
|
|
||||||
|
|
||||||
// If we get a 200 OK, return the WFPost as success; if not, return a WFError as failure.
|
|
||||||
if response.statusCode == 200 {
|
|
||||||
do {
|
|
||||||
let post = try self.decoder.decode(ServerData<WFPost>.self, from: data)
|
|
||||||
|
|
||||||
completion(.success(post.data))
|
|
||||||
} catch {
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// We didn't get a 200 OK, so return a WFError
|
|
||||||
guard let error = self.translateWFError(fromServerResponse: data) else { return }
|
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
case .failure(let error):
|
||||||
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTask.resume()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deletes an existing post.
|
/// Deletes an existing post.
|
||||||
|
@ -817,51 +634,14 @@ public class WFClient {
|
||||||
request.addValue(tokenToVerify, forHTTPHeaderField: "Authorization")
|
request.addValue(tokenToVerify, forHTTPHeaderField: "Authorization")
|
||||||
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
||||||
|
|
||||||
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
|
delete(with: request) { result in
|
||||||
// Something went wrong; return the error message.
|
switch result {
|
||||||
if let error = error {
|
case .success(_):
|
||||||
// ⚠️ HACK: There's something that URLSession doesn't like about 204 NO CONTENT response that the API
|
completion(.success(true))
|
||||||
// server is returning. If we get back a "protocol error", the operation probably succeeded,
|
case .failure(let error):
|
||||||
// but URLSession is being pedantic/cranky and throwing an NSPOSIXErrorDomain error code 100.
|
completion(.failure(error))
|
||||||
// Here, we check for that error, make sure the token was invalidated, and only then fire the
|
|
||||||
// success case in the completion block.
|
|
||||||
let nsError = error as NSError
|
|
||||||
if nsError.code == 100 && nsError.domain == NSPOSIXErrorDomain {
|
|
||||||
// Confirm that the operation succeeded by testing for a 404 on the same token.
|
|
||||||
self.deletePost(postId: postId) { result in
|
|
||||||
do {
|
|
||||||
_ = try result.get()
|
|
||||||
completion(.failure(error))
|
|
||||||
} catch WFError.notFound {
|
|
||||||
completion(.success(true))
|
|
||||||
} catch WFError.unauthorized {
|
|
||||||
completion(.success(true))
|
|
||||||
} catch WFError.internalServerError {
|
|
||||||
// If you try to delete a non-existent post, the API returns a 500 Internal Server Error.
|
|
||||||
completion(.success(true))
|
|
||||||
} catch {
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let response = response as? HTTPURLResponse {
|
|
||||||
// We got a response. If it's a 204 NO CONTENT, return true as success;
|
|
||||||
// if not, return a WFError as failure.
|
|
||||||
if response.statusCode != 204 {
|
|
||||||
guard let data = data else { return }
|
|
||||||
guard let error = self.translateWFError(fromServerResponse: data) else { return }
|
|
||||||
completion(.failure(error))
|
|
||||||
} else {
|
|
||||||
completion(.success(true))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTask.resume()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Placeholder method stub: API design for this feature is not yet finalized.
|
/* Placeholder method stub: API design for this feature is not yet finalized.
|
||||||
|
@ -903,37 +683,20 @@ public class WFClient {
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
|
post(with: request, expecting: 200) { result in
|
||||||
// Something went wrong; return the error message.
|
switch result {
|
||||||
if let error = error {
|
case .success(let data):
|
||||||
completion(.failure(error))
|
do {
|
||||||
}
|
let user = try self.decoder.decode(WFUser.self, from: data)
|
||||||
|
self.user = user
|
||||||
if let response = response as? HTTPURLResponse {
|
completion(.success(user))
|
||||||
guard let data = data else { return }
|
} catch {
|
||||||
|
|
||||||
// If we get a 200 OK, return the WFUser as success; if not, return a WFError as failure.
|
|
||||||
if response.statusCode == 200 {
|
|
||||||
do {
|
|
||||||
let user = try self.decoder.decode(WFUser.self, from: data)
|
|
||||||
self.user = user
|
|
||||||
completion(.success(user))
|
|
||||||
} catch {
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// We didn't get a 200 OK, so return a WFError
|
|
||||||
guard let error = self.translateWFError(fromServerResponse: data) else {
|
|
||||||
// We couldn't generate a WFError from the server response data, so return an unknown error.
|
|
||||||
completion(.failure(WFError.unknownError))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
case .failure(let error):
|
||||||
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTask.resume()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invalidates the user's access token.
|
/// Invalidates the user's access token.
|
||||||
|
@ -953,51 +716,15 @@ public class WFClient {
|
||||||
request.addValue(tokenToDelete, forHTTPHeaderField: "Authorization")
|
request.addValue(tokenToDelete, forHTTPHeaderField: "Authorization")
|
||||||
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
||||||
|
|
||||||
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
|
delete(with: request) { result in
|
||||||
// Something went wrong; return the error message.
|
switch result {
|
||||||
if let error = error {
|
case .success(_):
|
||||||
// ⚠️ HACK: There's something that URLSession doesn't like about 204 NO CONTENT response that the API
|
self.user = nil
|
||||||
// server is returning. If we get back a "protocol error", the operation probably succeeded,
|
completion(.success(true))
|
||||||
// but URLSession is being pedantic/cranky and throwing an NSPOSIXErrorDomain error code 100.
|
case .failure(let error):
|
||||||
// Here, we check for that error, make sure the token was invalidated, and only then fire the
|
completion(.failure(error))
|
||||||
// success case in the completion block.
|
|
||||||
let nsError = error as NSError
|
|
||||||
if nsError.code == 100 && nsError.domain == NSPOSIXErrorDomain {
|
|
||||||
// Confirm that the operation succeeded by testing for a 404 on the same token.
|
|
||||||
self.logout(token: tokenToDelete) { result in
|
|
||||||
do {
|
|
||||||
_ = try result.get()
|
|
||||||
completion(.failure(error))
|
|
||||||
} catch WFError.notFound {
|
|
||||||
self.user = nil
|
|
||||||
completion(.success(true))
|
|
||||||
} catch WFError.unauthorized {
|
|
||||||
self.user = nil
|
|
||||||
completion(.success(true))
|
|
||||||
} catch {
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let response = response as? HTTPURLResponse {
|
|
||||||
// We got a response. If it's a 204 NO CONTENT, return true as success;
|
|
||||||
// if not, return a WFError as failure.
|
|
||||||
if response.statusCode != 204 {
|
|
||||||
guard let data = data else { return }
|
|
||||||
guard let error = self.translateWFError(fromServerResponse: data) else { return }
|
|
||||||
completion(.failure(error))
|
|
||||||
} else {
|
|
||||||
self.user = nil
|
|
||||||
completion(.success(true))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTask.resume()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves a user's basic data.
|
/// Retrieves a user's basic data.
|
||||||
|
@ -1016,27 +743,14 @@ public class WFClient {
|
||||||
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
||||||
request.addValue(tokenToVerify, forHTTPHeaderField: "Authorization")
|
request.addValue(tokenToVerify, forHTTPHeaderField: "Authorization")
|
||||||
|
|
||||||
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
|
get(with: request) { result in
|
||||||
// Something went wrong; return the error message.
|
switch result {
|
||||||
if let error = error {
|
case .success(let data):
|
||||||
|
completion(.success(data))
|
||||||
|
case .failure(let error):
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let response = response as? HTTPURLResponse {
|
|
||||||
guard let data = data else { return }
|
|
||||||
|
|
||||||
// If we get a 200 OK, return the WFUser as success; if not, return a WFError as failure.
|
|
||||||
if response.statusCode == 200 {
|
|
||||||
completion(.success(data))
|
|
||||||
} else {
|
|
||||||
// We didn't get a 200 OK, so return a WFError.
|
|
||||||
guard let error = self.translateWFError(fromServerResponse: data) else { return }
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTask.resume()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves a user's collections.
|
/// Retrieves a user's collections.
|
||||||
|
@ -1055,32 +769,19 @@ public class WFClient {
|
||||||
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
||||||
request.addValue(tokenToVerify, forHTTPHeaderField: "Authorization")
|
request.addValue(tokenToVerify, forHTTPHeaderField: "Authorization")
|
||||||
|
|
||||||
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
|
get(with: request) { result in
|
||||||
// Something went wrong; return the error message.
|
switch result {
|
||||||
if let error = error {
|
case .success(let data):
|
||||||
completion(.failure(error))
|
do {
|
||||||
}
|
let collection = try self.decoder.decode(ServerData<[WFCollection]>.self, from: data)
|
||||||
|
completion(.success(collection.data))
|
||||||
if let response = response as? HTTPURLResponse {
|
} catch {
|
||||||
guard let data = data else { return }
|
|
||||||
|
|
||||||
// If we get a 200 OK, return the WFUser as success; if not, return a WFError as failure.
|
|
||||||
if response.statusCode == 200 {
|
|
||||||
do {
|
|
||||||
let collection = try self.decoder.decode(ServerData<[WFCollection]>.self, from: data)
|
|
||||||
completion(.success(collection.data))
|
|
||||||
} catch {
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// We didn't get a 200 OK, so return a WFError.
|
|
||||||
guard let error = self.translateWFError(fromServerResponse: data) else { return }
|
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
case .failure(let error):
|
||||||
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTask.resume()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1096,3 +797,16 @@ private extension WFClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Protocol conformance
|
||||||
|
|
||||||
|
extension URLSession: URLSessionProtocol {
|
||||||
|
public func dataTask(
|
||||||
|
with request: URLRequest,
|
||||||
|
completionHandler: @escaping DataTaskResult
|
||||||
|
) -> URLSessionDataTaskProtocol {
|
||||||
|
return dataTask(with: request, completionHandler: completionHandler) as URLSessionDataTask
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension URLSessionDataTask: URLSessionDataTaskProtocol {}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public enum WFError: Int, Error {
|
public enum WFError: Int, Error {
|
||||||
|
// Errors returned by the server
|
||||||
case badRequest = 400
|
case badRequest = 400
|
||||||
case unauthorized = 401
|
case unauthorized = 401
|
||||||
case forbidden = 403
|
case forbidden = 403
|
||||||
|
@ -12,7 +13,12 @@ public enum WFError: Int, Error {
|
||||||
case internalServerError = 500
|
case internalServerError = 500
|
||||||
case badGateway = 502
|
case badGateway = 502
|
||||||
case serviceUnavailable = 503
|
case serviceUnavailable = 503
|
||||||
|
|
||||||
|
// Other errors
|
||||||
case unknownError = -1
|
case unknownError = -1
|
||||||
|
case couldNotComplete = -2
|
||||||
|
case invalidResponse = -3
|
||||||
|
case invalidData = -4
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ErrorMessage: Codable {
|
struct ErrorMessage: Codable {
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
# Types
|
|
||||||
|
|
||||||
- [WFClient](/WFClient)
|
|
||||||
- [WFCollection](/WFCollection)
|
|
||||||
- [WFError](/WFError)
|
|
||||||
- [WFPost](/WFPost)
|
|
||||||
- [WFUser](/WFUser)
|
|
329
docs/WFClient.md
329
docs/WFClient.md
|
@ -1,329 +0,0 @@
|
||||||
# WFClient
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
public class WFClient
|
|
||||||
```
|
|
||||||
|
|
||||||
## Initializers
|
|
||||||
|
|
||||||
### `init(for:)`
|
|
||||||
|
|
||||||
Initializes the WriteFreely client.
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
public init(for instanceURL: URL)
|
|
||||||
```
|
|
||||||
|
|
||||||
Required for connecting to the API endpoints of a WriteFreely instance.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
|
|
||||||
- instanceURL: - instanceURL: The URL for the WriteFreely instance to which we're connecting, including the protocol.
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
### `decoder`
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
let decoder
|
|
||||||
```
|
|
||||||
|
|
||||||
### `requestURL`
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
var requestURL: URL
|
|
||||||
```
|
|
||||||
|
|
||||||
### `user`
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
var user: WFUser?
|
|
||||||
```
|
|
||||||
|
|
||||||
## Methods
|
|
||||||
|
|
||||||
### `createCollection(token:withTitle:alias:completion:)`
|
|
||||||
|
|
||||||
Creates a new collection.
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
public func createCollection(token: String? = nil, withTitle title: String, alias: String? = nil, completion: @escaping (Result<WFCollection, Error>) -> Void)
|
|
||||||
```
|
|
||||||
|
|
||||||
If only a `title` is given, the server will generate and return an alias; in this case, clients should store
|
|
||||||
the returned `alias` for future operations.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
|
|
||||||
- token: - token: The access token for the user creating the collection.
|
|
||||||
- title: - title: The title of the new collection.
|
|
||||||
- alias: - alias: The alias of the collection.
|
|
||||||
- completion: - completion: A handler for the returned `WFCollection` on success, or `Error` on failure.
|
|
||||||
|
|
||||||
### `getCollection(token:withAlias:completion:)`
|
|
||||||
|
|
||||||
Retrieves a collection's metadata.
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
public func getCollection(token: String? = nil, withAlias alias: String, completion: @escaping (Result<WFCollection, Error>) -> Void)
|
|
||||||
```
|
|
||||||
|
|
||||||
Collections can be retrieved without authentication. However, authentication is required for retrieving a
|
|
||||||
private collection or one with scheduled posts.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
|
|
||||||
- token: - token: The access token for the user retrieving the collection.
|
|
||||||
- alias: - alias: The alias for the collection to be retrieved.
|
|
||||||
- completion: - completion: A handler for the returned `WFCollection` on success, or `Error` on failure.
|
|
||||||
|
|
||||||
### `deleteCollection(token:withAlias:completion:)`
|
|
||||||
|
|
||||||
Permanently deletes a collection.
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
public func deleteCollection(token: String? = nil, withAlias alias: String, completion: @escaping (Result<Bool, Error>) -> Void)
|
|
||||||
```
|
|
||||||
|
|
||||||
Any posts in the collection are not deleted; rather, they are made anonymous.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
|
|
||||||
- token: - token: The access token for the user deleting the collection.
|
|
||||||
- alias: - alias: The alias for the collection to be deleted.
|
|
||||||
- completion: - completion: A hander for the returned `Bool` on success, or `Error` on failure.
|
|
||||||
|
|
||||||
### `getPosts(token:in:completion:)`
|
|
||||||
|
|
||||||
Retrieves an array of posts.
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
public func getPosts(token: String? = nil, in collectionAlias: String? = nil, completion: @escaping (Result<[WFPost], Error>) -> Void)
|
|
||||||
```
|
|
||||||
|
|
||||||
If the `collectionAlias` argument is provided, an array of all posts in that collection is retrieved; if
|
|
||||||
omitted, an array of all posts created by the user whose access token is provided is retrieved.
|
|
||||||
|
|
||||||
Collection posts can be retrieved without authentication; however, authentication is required for retrieving a
|
|
||||||
private collection or one with scheduled posts.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
|
|
||||||
- token: - token: The access token for the user retrieving the posts.
|
|
||||||
- collectionAlias: - collectionAlias: The alias for the collection whose posts are to be retrieved.
|
|
||||||
- completion: - completion: A handler for the returned `[WFPost]` on success, or `Error` on failure.
|
|
||||||
|
|
||||||
### `movePost(token:postId:with:to:completion:)`
|
|
||||||
|
|
||||||
Moves a post to a collection.
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
public func movePost(token: String? = nil, postId: String, with modifyToken: String? = nil, to collectionAlias: String, completion: @escaping (Result<Bool, Error>) -> Void)
|
|
||||||
```
|
|
||||||
|
|
||||||
> Attention: - The closure should return a result type of \`\<\[WFPost\], Error\>\`.
|
|
||||||
> - The modifyToken for the post is currently ignored.
|
|
||||||
>
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
|
|
||||||
- token: - token: The access token for the user moving the post to a collection.
|
|
||||||
- postId: - postId: The ID of the post to add to the collection.
|
|
||||||
- modifyToken: - modifyToken: The post's modify token; required if the post doesn't belong to the requesting user.
|
|
||||||
- collectionAlias: - collectionAlias: The alias of the collection to which the post should be added.
|
|
||||||
- completion: - completion: A handler for the returned `Bool` on success, or `Error` on failure.
|
|
||||||
|
|
||||||
### `pinPost(token:postId:at:in:completion:)`
|
|
||||||
|
|
||||||
Pins a post to a collection.
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
public func pinPost(token: String? = nil, postId: String, at position: Int? = nil, in collectionAlias: String, completion: @escaping (Result<Bool, Error>) -> Void)
|
|
||||||
```
|
|
||||||
|
|
||||||
Pinning a post to a collection adds it as a navigation item in the collection/blog home page header, rather
|
|
||||||
than on the blog itself. While the API endpoint can take an array of posts, this function only accepts a single
|
|
||||||
post.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
|
|
||||||
- token: - token: The access token of the user pinning the post to the collection.
|
|
||||||
- postId: - postId: The ID of the post to be pinned.
|
|
||||||
- position: - position: The numeric position in which to pin the post; if `nil`, will pin at the end of the list.
|
|
||||||
- collectionAlias: - collectionAlias: The alias of the collection to which the post should be pinned.
|
|
||||||
- completion: - completion: A handler for the `Bool` returned on success, or `Error` on failure.
|
|
||||||
|
|
||||||
### `unpinPost(token:postId:from:completion:)`
|
|
||||||
|
|
||||||
Unpins a post from a collection.
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
public func unpinPost(token: String? = nil, postId: String, from collectionAlias: String, completion: @escaping (Result<Bool, Error>) -> Void)
|
|
||||||
```
|
|
||||||
|
|
||||||
Removes the post from a navigation item and puts it back on the blog itself. While the API endpoint can take an
|
|
||||||
array of posts, this function only accepts a single post.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
|
|
||||||
- token: - token: The access token of the user un-pinning the post from the collection.
|
|
||||||
- postId: - postId: The ID of the post to be un-pinned.
|
|
||||||
- collectionAlias: - collectionAlias: The alias of the collection to which the post should be un-pinned.
|
|
||||||
- completion: - completion: A handler for the `Bool` returned on success, or `Error` on failure.
|
|
||||||
|
|
||||||
### `createPost(token:post:in:completion:)`
|
|
||||||
|
|
||||||
Creates a new post.
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
public func createPost(token: String? = nil, post: WFPost, in collectionAlias: String? = nil, completion: @escaping (Result<WFPost, Error>) -> Void)
|
|
||||||
```
|
|
||||||
|
|
||||||
Creates a new post. If a `collectionAlias` is provided, the post is published to that collection; otherwise, it
|
|
||||||
is posted to the user's Drafts.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
|
|
||||||
- token: - token: The access token of the user creating the post.
|
|
||||||
- post: - post: The `WFPost` object to be published.
|
|
||||||
- collectionAlias: - collectionAlias: The collection to which the post should be published.
|
|
||||||
- completion: - completion: A handler for the `WFPost` object returned on success, or `Error` on failure.
|
|
||||||
|
|
||||||
### `getPost(token:byId:completion:)`
|
|
||||||
|
|
||||||
Retrieves a post.
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
public func getPost(token: String? = nil, byId postId: String, completion: @escaping (Result<WFPost, Error>) -> Void)
|
|
||||||
```
|
|
||||||
|
|
||||||
The `WFPost` object returned may include additional data, including page views and extracted tags.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
|
|
||||||
- token: - token: The access token of the user retrieving the post.
|
|
||||||
- postId: - postId: The ID of the post to be retrieved.
|
|
||||||
- completion: - completion: A handler for the `WFPost` object returned on success, or `Error` on failure.
|
|
||||||
|
|
||||||
### `getPost(token:bySlug:from:completion:)`
|
|
||||||
|
|
||||||
Retrieves a post from a collection.
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
public func getPost(token: String? = nil, bySlug slug: String, from collectionAlias: String, completion: @escaping (Result<WFPost, Error>) -> Void)
|
|
||||||
```
|
|
||||||
|
|
||||||
Collection posts can be retrieved without authentication. However, authentication is required for retrieving a
|
|
||||||
post from a private collection.
|
|
||||||
|
|
||||||
The `WFPost` object returned may include additional data, including page views and extracted tags.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
|
|
||||||
- token: - token: The access token of the user retrieving the post.
|
|
||||||
- slug: - slug: The slug of the post to be retrieved.
|
|
||||||
- collectionAlias: - collectionAlias: The alias of the collection from which the post should be retrieved.
|
|
||||||
- completion: - completion: A handler for the `WFPost` object returned on success, or `Error` on failure.
|
|
||||||
|
|
||||||
### `updatePost(token:postId:updatedPost:with:completion:)`
|
|
||||||
|
|
||||||
Updates an existing post.
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
public func updatePost(token: String? = nil, postId: String, updatedPost: WFPost, with modifyToken: String? = nil, completion: @escaping (Result<WFPost, Error>) -> Void)
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that if the `updatedPost` object is provided without a title, the original post's title will be removed.
|
|
||||||
|
|
||||||
> Attention: - The modifyToken for the post is currently ignored.
|
|
||||||
>
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
|
|
||||||
- token: - token: The access token for the user updating the post.
|
|
||||||
- postId: - postId: The ID of the post to be updated.
|
|
||||||
- updatedPost: - updatedPost: The `WFPost` object with which to update the existing post.
|
|
||||||
- modifyToken: - modifyToken: The post's modify token; required if the post doesn't belong to the requesting user.
|
|
||||||
- completion: - completion: A handler for the `WFPost` object returned on success, or `Error` on failure.
|
|
||||||
|
|
||||||
### `deletePost(token:postId:with:completion:)`
|
|
||||||
|
|
||||||
Deletes an existing post.
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
public func deletePost(token: String? = nil, postId: String, with modifyToken: String? = nil, completion: @escaping (Result<Bool, Error>) -> Void)
|
|
||||||
```
|
|
||||||
|
|
||||||
> Attention: - The modifyToken for the post is currently ignored.
|
|
||||||
>
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
|
|
||||||
- token: - token: The access token for the user deleting the post.
|
|
||||||
- postId: - postId: The ID of the post to be deleted.
|
|
||||||
- modifyToken: - modifyToken: The post's modify token; required if the post doesn't belong to the requesting user.
|
|
||||||
- completion: - completion: A handler for the `Bool` object returned on success, or `Error` on failure.
|
|
||||||
|
|
||||||
### `login(username:password:completion:)`
|
|
||||||
|
|
||||||
Logs the user in to their account on the WriteFreely instance.
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
public func login(username: String, password: String, completion: @escaping (Result<WFUser, Error>) -> Void)
|
|
||||||
```
|
|
||||||
|
|
||||||
On successful login, the `WFClient`'s `user` property is set to the returned `WFUser` object; this allows
|
|
||||||
authenticated requests to be made without having to provide an access token.
|
|
||||||
|
|
||||||
It is otherwise not necessary to login the user if their access token is provided to the calling function.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
|
|
||||||
- username: - username: The user's username.
|
|
||||||
- password: - password: The user's password.
|
|
||||||
- completion: - completion: A handler for the `WFUser` object returned on success, or `Error` on failure.
|
|
||||||
|
|
||||||
### `logout(token:completion:)`
|
|
||||||
|
|
||||||
Invalidates the user's access token.
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
public func logout(token: String? = nil, completion: @escaping (Result<Bool, Error>) -> Void)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
|
|
||||||
- token: - token: The token to invalidate.
|
|
||||||
- completion: - completion: A handler for the `Bool` object returned on success, or `Error` on failure.
|
|
||||||
|
|
||||||
### `getUserData(token:completion:)`
|
|
||||||
|
|
||||||
Retrieves a user's basic data.
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
public func getUserData(token: String? = nil, completion: @escaping (Result<Data, Error>) -> Void)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
|
|
||||||
- token: - token: The access token for the user to fetch.
|
|
||||||
- completion: - completion: A handler for the `Data` object returned on success, or `Error` on failure.
|
|
||||||
|
|
||||||
### `getUserCollections(token:completion:)`
|
|
||||||
|
|
||||||
Retrieves a user's collections.
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
public func getUserCollections(token: String? = nil, completion: @escaping (Result<[WFCollection], Error>) -> Void)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
|
|
||||||
- token: - token: The access token for the user whose collections are to be retrieved.
|
|
||||||
- completion: - completion: A handler for the `[WFCollection]` object returned on success, or `Error` on failure.
|
|
||||||
|
|
||||||
### `translateWFError(fromServerResponse:)`
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
func translateWFError(fromServerResponse response: Data) -> WFError?
|
|
||||||
```
|
|
|
@ -1,77 +0,0 @@
|
||||||
# WFError
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
public enum WFError
|
|
||||||
```
|
|
||||||
|
|
||||||
## Inheritance
|
|
||||||
|
|
||||||
`Error`, `Int`
|
|
||||||
|
|
||||||
## Enumeration Cases
|
|
||||||
|
|
||||||
### `badRequest`
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
case badRequest
|
|
||||||
```
|
|
||||||
|
|
||||||
### `unauthorized`
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
case unauthorized
|
|
||||||
```
|
|
||||||
|
|
||||||
### `forbidden`
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
case forbidden
|
|
||||||
```
|
|
||||||
|
|
||||||
### `notFound`
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
case notFound
|
|
||||||
```
|
|
||||||
|
|
||||||
### `methodNotAllowed`
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
case methodNotAllowed
|
|
||||||
```
|
|
||||||
|
|
||||||
### `gone`
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
case gone
|
|
||||||
```
|
|
||||||
|
|
||||||
### `preconditionFailed`
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
case preconditionFailed
|
|
||||||
```
|
|
||||||
|
|
||||||
### `tooManyRequests`
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
case tooManyRequests
|
|
||||||
```
|
|
||||||
|
|
||||||
### `internalServerError`
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
case internalServerError
|
|
||||||
```
|
|
||||||
|
|
||||||
### `badGateway`
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
case badGateway
|
|
||||||
```
|
|
||||||
|
|
||||||
### `serviceUnavailable`
|
|
||||||
|
|
||||||
``` swift
|
|
||||||
case serviceUnavailable
|
|
||||||
```
|
|
|
@ -1 +0,0 @@
|
||||||
Generated at 2020-08-31T10:27:33-0400 using [swift-doc](https://github.com/SwiftDocOrg/swift-doc) 1.0.0-beta.3.
|
|
|
@ -1,10 +0,0 @@
|
||||||
<details>
|
|
||||||
<summary>Types</summary>
|
|
||||||
|
|
||||||
- [WFClient](/WFClient)
|
|
||||||
- [WFCollection](/WFCollection)
|
|
||||||
- [WFError](/WFError)
|
|
||||||
- [WFPost](/WFPost)
|
|
||||||
- [WFUser](/WFUser)
|
|
||||||
|
|
||||||
</details>
|
|
Loading…
Reference in New Issue