Skip to content

Commit

Permalink
Models & endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
chojnac committed Jun 1, 2021
1 parent c9ccc85 commit 65d7576
Show file tree
Hide file tree
Showing 13 changed files with 272 additions and 70 deletions.
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
# NotionSwift

Unofficial Notion SDK for Swift.
Unofficial Notion SDK for iOS & macOS


## Supported Endpoints

### Databases
* Retrieve a database ✅
* Query a database ✅
* List databases ✅

### Pages
* Retrieve a page ✅
* Create a page
* Update page properties

### Blocks
* Retrieve block children
* Append block children

### Users
* Retrieve a user ✅
* List all users ✅

### Search
* Search
11 changes: 0 additions & 11 deletions Sources/NotionSwift/Models/BaseQueryParams.swift

This file was deleted.

16 changes: 15 additions & 1 deletion Sources/NotionSwift/Models/Block.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,21 @@

import Foundation

public struct Block {
public class Block {
public typealias Identifier = EntityIdentifier<Block, UUIDv4>

}

/// Block object read from server
public final class ReadBlock: Block {
public let id: Identifier
}

/// Block object used in adding new content
public final class WriteBlock: Block {

}

extension ReadBlock: Decodable {}

extension WriteBlock: Encodable {}
53 changes: 52 additions & 1 deletion Sources/NotionSwift/Models/User.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,58 @@
import Foundation

public struct User {
public enum UserType {
case person(Person)
case bot(Bot)
case unknown
}

public struct Person {
public let email: String
}

public struct Bot {}

public typealias Identifier = EntityIdentifier<User, UUIDv4>
public let id: Identifier
public let type: UserType?
public let name: String?
public let avatarURL: String?
}

extension User: Decodable {}
extension User.Person: Decodable {}
extension User.Bot: Decodable {}

extension User: Decodable {
enum CodingKeys: String, CodingKey {
case id
case type
case name
case avatarURL = "avatar_url"
case person
case bot
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(Identifier.self, forKey: .id)
self.name = try container.decode(String?.self, forKey: .name)
self.avatarURL = try container.decode(String?.self, forKey: .avatarURL)

if let type = try container.decode(String?.self, forKey: .type) {
switch type {
case "person":
let person = try container.decode(Person.self, forKey: .person)
self.type = .person(person)
case "bot":
let bot = try container.decode(Bot.self, forKey: .bot)
self.type = .bot(bot)
default:
self.type = .unknown
}
} else {
self.type = nil
}
}


}
3 changes: 2 additions & 1 deletion Sources/NotionSwift/Network/NetworkClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public protocol NetworkClient: AnyObject {

public class DefaultNetworkClient: NetworkClient {
private let encoder: JSONEncoder
private let decoder: JSONDecoder
private let decoder: JSONDecoder

public init() {
encoder = JSONEncoder()
Expand All @@ -60,6 +60,7 @@ public class DefaultNetworkClient: NetworkClient {
}

public func get<R: Decodable>(_ url: URL, headers: Network.HTTPHeaders, completed: @escaping (Result<R, Network.Errors>) -> Void) {

let request = buildRequest(method: .GET, url: url, headers: headers)
executeRequest(request: request, completed: completed)
}
Expand Down
57 changes: 57 additions & 0 deletions Sources/NotionSwift/Network/URLBuilder.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//
// File.swift
//
//
// Created by Wojciech Chojnacki on 01/06/2021.
//

import Foundation

public class URLBuilder {
let base: URL

init() {
self.base = Network.notionBaseURL
}

public func url<T>(
path: String,
identifier: EntityIdentifier<T, String>,
params: [String: String] = [:]
) -> URL {
let newPath = path.replacingOccurrences(of: "{identifier}", with: identifier.rawValue)
guard let url = URL(string: newPath, relativeTo: base) else {
fatalError("Invalid path, unable to create a URL: \(path)")
}

return buildURL(url: url, params: params)
}

public func url(
path: String,
params: [String: String] = [:]
) -> URL {
guard let url = URL(string: path, relativeTo: base) else {
fatalError("Invalid path, unable to create a URL: \(path)")
}

return buildURL(url: url, params: params)
}

private func buildURL(url: URL, params: [String: String]) -> URL {
guard var components = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
fatalError("Invalid url, unable to build components path")
}

if !params.isEmpty {
components.queryItems = params.map {
URLQueryItem(name: $0.key, value: $0.value)
}
}
guard let result = components.url else {
fatalError("Unable to create url from components (\(components)")
}

return result
}
}
24 changes: 20 additions & 4 deletions Sources/NotionSwift/NotionClient+Blocks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,27 @@ import Foundation

extension NotionClient {

public func blockChildren(blockId: Block.Identifier, completed: (Result<Block, Error>) -> Void) {

public func blockChildren(blockId: Block.Identifier, params: BaseQueryParams, completed: @escaping (Result<ListResponse<ReadBlock>, Network.Errors>) -> Void) {
networkClient.get(
urlBuilder.url(
path: "/v1/blocks/{identifier}/children",
identifier: blockId,
params: params.asParams
),
headers: headers(),
completed: completed
)
}

public func blockAppend(blockId: Block.Identifier, children: Any, completed: (Result<Block, Error>) -> Void) {

public func blockAppend(blockId: Block.Identifier, children: [WriteBlock], completed: @escaping (Result<ReadBlock, Network.Errors>) -> Void) {
networkClient.patch(
urlBuilder.url(
path: "/v1/blocks/{identifier}/children",
identifier: blockId
),
body: children,
headers: headers(),
completed: completed
)
}
}
36 changes: 12 additions & 24 deletions Sources/NotionSwift/NotionClient+Database.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,54 +9,43 @@ import Foundation
extension NotionClient {
public func database(databaseId: Database.Identifier, completed: @escaping (Result<Database, Network.Errors>) -> Void) {
networkClient.get(
URL(string: "/v1/databases/\(databaseId.rawValue)", relativeTo: Network.notionBaseURL )!,
urlBuilder.url(
path: "/v1/databases/{identifier}",
identifier: databaseId
),
headers: headers(),
completed: completed
)
}

public func databaseQuery(databaseId: Database.Identifier, params: DatabaseQueryParams = .init(), completed: @escaping (Result<ListResponse<Page>, Network.Errors>) -> Void) {
networkClient.post(
URL(string: "/v1/databases/\(databaseId.rawValue)/query", relativeTo: Network.notionBaseURL)!,
urlBuilder.url(
path: "/v1/databases/{identifier}/query",
identifier: databaseId
),
body: params,
headers: headers(),
completed: completed
)
}

public func databaseList(
params: DatabaseListParams = .init(),
params: BaseQueryParams = .init(),
completed: @escaping (Result<ListResponse<Database>, Network.Errors>) -> Void
) {

networkClient.get(
URL(string: "/v1/databases", relativeTo: Network.notionBaseURL )!,
urlBuilder.url(path: "/v1/databases"),
headers: headers(),
completed: completed
)
}
}

public struct DatabaseListParams: BaseQueryParams {
public let startCursor: String?
public let pageSize: Int32?

enum CodingKeys: String, CodingKey {
case startCursor = "start_cursor"
case pageSize = "page_size"
}

public init(startCursor: String? = nil, pageSize: Int32? = nil) {
self.startCursor = startCursor
self.pageSize = pageSize
}
}

public struct DatabaseQueryParams: BaseQueryParams {
public final class DatabaseQueryParams: BaseQueryParams {
public let filter: String?
public let sorts: [SortObject]?
public let startCursor: String?
public let pageSize: Int32?

enum CodingKeys: String, CodingKey {
case filter
Expand All @@ -68,8 +57,7 @@ public struct DatabaseQueryParams: BaseQueryParams {
public init(filter: String? = nil, sorts: [SortObject]? = nil, startCursor: String? = nil, pageSize: Int32? = nil) {
self.filter = filter
self.sorts = sorts
self.startCursor = startCursor
self.pageSize = pageSize
super.init(startCursor: startCursor, pageSize: pageSize)
}

}
53 changes: 35 additions & 18 deletions Sources/NotionSwift/NotionClient+Pages.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,38 @@ import Foundation

// MARK: - Pages

extension NotionClient {

public func page(pageId: Page.Identifier, completed: @escaping (Result<Page, Network.Errors>) -> Void) {
networkClient.get(
URL(string: "/v1/pages/\(pageId.rawValue)", relativeTo: Network.notionBaseURL )!,
headers: headers(),
completed: completed
)
}

public func pageCreate(request: Any, completed: (Result<Page, Network.Errors>) -> Void) {

}

public func pageUpdate(pageId: Page.Identifier, properties: Any, completed: (Result<Page, Network.Errors>) -> Void) {

}
}
// WIP
//extension NotionClient {
//
// public func page(pageId: Page.Identifier, completed: @escaping (Result<Page, Network.Errors>) -> Void) {
// networkClient.get(
// urlBuilder.url(path: "/v1/pages", identifier: pageId),
// headers: headers(),
// completed: completed
// )
// }
//
// public func pageCreate(request: PageCreateRequest, completed: @escaping (Result<Page, Network.Errors>) -> Void) {
// networkClient.post(
// urlBuilder.url(path: "/v1/pages"),
// body: request,
// headers: headers(),
// completed: completed
// )
// }
//
// public func pageUpdate(pageId: Page.Identifier, properties: PageUpdateParams, completed: @escaping (Result<Page, Network.Errors>) -> Void) {
// networkClient.patch(
// urlBuilder.url(path: "/v1/pages", identifier: pageId),
// body: properties,
// headers: headers(),
// completed: completed
// )
// }
//}
//
//#warning("TODO: PageCreateRequest")
//public struct PageCreateRequest: Encodable {}
//
//#warning("TODO: PageUpdateParams")
//public struct PageUpdateParams: Encodable {}
11 changes: 6 additions & 5 deletions Sources/NotionSwift/NotionClient+Search.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import Foundation

// MARK: - Search

extension NotionClient {
public func search(params: Any, completed: (Result<[Any], Error>) -> Void) {

}
}
// WIP
//extension NotionClient {
// public func search(params: Any, completed: @escaping (Result<[Any], Error>) -> Void) {
//
// }
//}
Loading

0 comments on commit 65d7576

Please sign in to comment.