NotionSwift

非官方的 iOS 和 macOS 平台 Notion SDK。

这仍然是一个正在开发中的版本,模块接口可能会更改。

API 文档

这个库是官方 Notion API 的客户端。 更多详情和文档请查看 Notion 开发者门户

安装

CocoaPods

pod 'NotionSwift', '0.9.0'

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/chojnac/NotionSwift.git", .upToNextMajor(from: "0.9.0"))
]

用法

目前,该库仅支持“内部集成”授权模式。 有关授权的更多信息以及如何获取 NOTION_TOKEN 的说明,请查看 Notion 官方文档

重要提示: 集成被授予访问用户已与集成共享的资源(页面和数据库)的权限。 API 端点无法看到未与集成共享的资源。

创建 Notion 客户端

let notion = NotionClient(accessKeyProvider: StringAccessKeyProvider(accessKey: "{NOTION_TOKEN}"))

调整网络配置

要调整诸如网络超时之类的设置,您可以像下面这样向 NotionClient 提供自定义 URLSessionConfiguration

let sessionConfig = URLSessionConfiguration.default
sessionConfig.timeoutIntervalForRequest = 15
let notion = NotionClient(accessKeyProvider: StringAccessKeyProvider(accessKey: "{NOTION_TOKEN}"), sessionConfiguration: sessionConfig)

如果这不足以满足您的需求,您可以实现 NetworkClient 协议并将您的实现提供给 NotionClient

列出所有数据库

https://api.notion.com/v1/databases 已经弃用。 推荐的列出所有数据库的方法是使用 https://api.notion.com/v1/search 端点。 理论上,搜索允许按对象类型过滤结果。 然而,目前唯一允许的过滤器是 object,它将按对象类型(pagedatabase)进行过滤。 要缩小搜索结果范围,请使用下面的代码片段。

// fetch available databases
notion.search(request: .init(filter: .database)) { result in
    let databases = result.map { objects in
        objects.results.compactMap({ object -> Database? in
            if case .database(let db) = object {
                return db
            }
            return nil
        })
    }
    print(databases)
}

查询数据库

在此示例中,我们将获取数据库中的所有页面。 要缩小结果范围,请使用 params 参数。

let databaseId = Database.Identifier("{DATABASE UUIDv4}")

notion.databaseQuery(databaseId: databaseId) {
    print($0)
}

检索数据库

let databaseId = Database.Identifier("{DATABASE UUIDv4}")

notion.database(databaseId: databaseId) {
    print($0)
}

创建数据库

let parentPageId = Page.Identifier("e67db074-973a-4ddb-b397-66d3c75f9ec9")

let request = DatabaseCreateRequest(
    parent: .pageId(parentPageId),
    icon: .emoji("🤔"),
    cover: .external(url: "https://images.unsplash.com/photo-1606787366850-de6330128bfc"),
    title: [
        .init(string: "Created at: \(Date())")
    ],
    properties: [
        "Field 10": .richText
    ]
)

notion.databaseCreate(request: request) {
    print($0)
}

更新数据库

let id = Database.Identifier("{DATABASE UUIDv4}")

// update cover, icon & add a new field
let request = DatabaseUpdateRequest(
    title: nil,
    icon: .emoji("🤔"),
    cover: .external(url: "https://images.unsplash.com/photo-1606787366850-de6330128bfc"),
    properties: [
        "Field 10": .richText
    ]
)

notion.databaseUpdate(databaseId: id, request: request) {
    print($0)
}

创建数据库条目

Notion 数据库条目是页面,其属性符合父数据库的架构。

let databaseId = Database.Identifier("{DATABASE UUIDv4}")

let request = PageCreateRequest(
    parent: .database(databaseId),
    properties: [
        "title": .init(
            type: .title([
                .init(string: "Lorem ipsum \(Date())")
            ])
        ),
        "Field 10": .init(
            type: .richText([
                .init(string: "dolor sit amet")
            ])
        )
    ]
)

notion.pageCreate(request: request) {
    print($0)
}

检索页面

检索页面属性。

let pageId = Page.Identifier("{PAGE UUIDv4}")

notion.page(pageId: pageId) {
    print($0)
}

页面内容(例如文本)表示为一个块数组。 以下示例加载属性和页面内容。

let pageId = Page.Identifier("{PAGE UUIDv4}")

notion.page(pageId: pageId) { [notion] in
    print("---- Properties ----- ")
    print($0)
    switch $0 {
    case .success(let page):
        notion.blockChildren(blockId: page.id.toBlockIdentifier) {
            print("---- Children ----- ")
            print($0)
        }
    default:
        break
    }
}

注意: API 仅返回页面的直接子级。 如果块中嵌套了内容(例如嵌套列表),则需要其他调用。

创建页面

let parentPageId = Page.Identifier("{PAGE UUIDv4}")

let request = PageCreateRequest(
    parent: .page(parentPageId),
    properties: [
        "title": .init(
            type: .title([
                .init(string: "Lorem ipsum \(Date())")
            ])
        )
    ]
)

notion.pageCreate(request: request) {
    print($0)
}

更新页面属性

let pageId = Page.Identifier("{PAGE UUIDv4}")

// update title property
let request = PageUpdateRequest(
    properties: [
        .name("title"): .init(
            type: .title([
                .init(string: "Updated at: \(Date())")
            ])
        )
    ]
)

notion.pageUpdate(pageId: pageId, request: request) {
    print($0)
}

删除页面

let pageId = Page.Identifier("{PAGE UUIDv4}")

// Archive page (trash a page)
let request = PageUpdateRequest(archived: true)

notion.pageUpdate(pageId: pageId, request: request) {
    print($0)
}

检索块子级

注意:此端点仅返回第一级子级,因此,例如,嵌套列表项将不会返回。 在这种情况下,您需要使用父块的块 id 发出另一个请求。

let pageId = Block.Identifier("{PAGE UUIDv4}")

notion.blockChildren(blockId: pageId) {
    print($0)
}

追加块子级

let pageId = Block.Identifier("{PAGE UUIDv4}")

// append paragraph with styled text to a page.
let blocks: [WriteBlock] = [
    .heading1(["Heading 1"], color: .orange),
    .paragraph([
        "Lorem ipsum dolor sit amet, ",
        .init(string: "consectetur", annotations: .bold),
        " adipiscing elit."
    ]),
    .heading2(["Heading 2"], color: .orangeBackground),
    .columnList(columns: [
        .column([
            .paragraph(["Column 1"])
        ]),
        .column([
            .paragraph(["Column 2"])
        ])
    ]),
    try! .table(
        width: 2,
        headers: [
            ["Header 1"], ["Header 2"]
        ],
        rows: [
            .row(
                header: ["Row 1 header"],
                cells: [
                    ["Cell 1-1"], ["Cell 1-2"]
                ]
            ),
            .row(
                cells: [
                    ["Cell 2-1"], ["Cell 2-2"]
                ]
            )
        ]
    )
]
notion.blockAppend(blockId: pageId, children: blocks) {
    print($0)
}

更新块

let blockId = Block.Identifier("{BLOCK UUIDv4}")
let text: [RichText] = [
    "Current time: ",
    .init(string: Date().description, annotations: .bold)
]
let block = UpdateBlock(type: .paragraph(text: text))
notion.blockUpdate(blockId: blockId, value: block) {
    print("Updated: ", $0)
}

删除块

let blockId = Block.Identifier("{BLOCK UUIDv4}")

notion.blockDelete(blockId: block.id) {
    print("Delete: ", $0)
}

检索用户

let id = User.Identifier("{USER UUIDv4}")
notion.user(userId: id) {
    print($0)
}

列出所有用户

notion.usersList() {
    print($0)
}

搜索

搜索标题包含文本“Lorem”的页面和数据库

notion.search(
    request: .init(
        query: "Lorem"
    )
) {
    print($0)
}

搜索所有数据库并忽略页面。

notion.search(
    request: .init(
        filter: .database
    )
) {
    print($0)
}

获取所有页面和数据库

notion.search() {
    print($0)
}

日志记录和调试

NotionSwift 提供了一个内部的基本日志记录系统来跟踪 HTTP 流量。 要启用它,您需要设置一个内置或自定义的日志记录处理程序,并决定日志级别(默认为 .info)。 使用 .track 日志级别,您可以查看请求的所有内容。 这有助于跟踪库数据模型和 API 之间的映射问题。

日志记录配置示例

// This code should be in the ApplicationDelegate

NotionSwiftEnvironment.logHandler = NotionSwift.PrintLogHandler() // uses print command
NotionSwiftEnvironment.logLevel = .trace // show me everything

许可证

NotionSwift 在 MIT 许可证下可用。 有关更多信息,请参见 LICENSE 文件。