Coder Social home page Coder Social logo

konglong2021 / notion-sdk-jvm Goto Github PK

View Code? Open in Web Editor NEW

This project forked from seratch/notion-sdk-jvm

0.0 0.0 0.0 554 KB

A Notion SDK for Any JVM Language

Home Page: https://developers.notion.com/

License: MIT License

Shell 0.67% Java 2.49% Kotlin 96.84%

notion-sdk-jvm's Introduction

Notion SDK for Any JVM Language

A simple and easy to use client for the Notion API


Maven Central CI Build

Here is a Notion API SDK for any JVM language users ๐Ÿ‘‹

This project aims to provide a Notion API client for any JVM language developers without hurdles. To realize the goal, its code is written in Kotlin with a nice consideration for Java compatibility.

This SDK works on Android runtime and any distributions based on OpenJDK. With regard to programming languages, this project provides out-of-the-box supports for Java (of course!) and Kotlin. We don't have nice wrappers for some other JVM languages such as Scala, Groovy, and Clojure, but your code using this library should work in the languages too.

Getting Started

You can start using this library just by adding notion-sdk-jvm-core dependency to your project.

For Gradle users:

ext.notionSdkVersion = "1.11.0"
dependencies {
  // This dependency is at least required
  implementation("com.github.seratch:notion-sdk-jvm-core:${notionSdkVersion}")
}

For Maven users:

<properties>
  <notion-sdk.version>1.11.0</notion-sdk.version>
</properties>

<dependencies>
  <dependency>
    <groupId>com.github.seratch</groupId>
    <artifactId>notion-sdk-jvm-core</artifactId>
    <version>${notion-sdk.version}</version>
  </dependency>
</dependencies>

As this library is in Kotlin, using in the same language is the smoothest :) Let's start with the following code, which manipulates Notion pages ๐Ÿ‘‹

import notion.api.v1.NotionClient
import notion.api.v1.model.common.ObjectType
import notion.api.v1.model.pages.PageParent
import notion.api.v1.request.search.SearchRequest
import notion.api.v1.model.pages.PageProperty

fun main() {
  NotionClient(token = System.getenv("NOTION_TOKEN")).use { client ->
    // Find the "Test Database" from the list
    val database = client
      .search(
        query = "Test Database",
        filter = SearchRequest.SearchFilter("database", property = "object")
      )
      .results
      .find { it.asDatabase().properties.containsKey("Severity") }
      ?.asDatabase()
      ?: error("Create a database named 'Test Database' and invite this app's user!")
    // Alternatively if you know the UUID of the Database, use `val database = client.retrieveDatabase("...")`.

    // All the options for "Severity" property (select type)
    val severityOptions = database.properties["Severity"]!!.select!!.options!!
    // All the options for "Tags" property (multi_select type)
    val tagOptions = database.properties["Tags"]!!.multiSelect!!.options!!
    // A user object for "Assignee" property (people type)
    val assignee = client.listUsers().results.first() // Just picking a random user.

    // Create a new page in the database
    val newPage = client.createPage(
      // Use the "Test Database" as this page's parent
      parent = PageParent.database(database.id),
      // Set values to the page's properties
      // (Values of referenced options, people, and relations must be pre-defined before this API call!)
      properties = mapOf(
        "Title" to PageProperty(title = "Fix a bug".asRichText()),
        "Severity" to PageProperty(select = severityOptions.single { it.name == "High" }),
        "Tags" to PageProperty(multiSelect = listOf("Tag1", "Tag2").map { tag -> tagOptions.single { it.name == tag } }),
        "Due" to PageProperty(date = PageProperty.Date(start = "2021-05-13", end = "2021-12-31")),
        "Velocity Points" to PageProperty(number = 3),
        "Assignee" to PageProperty(people = listOf(assignee)),
        "Done" to PageProperty(checkbox = true),
        "Link" to PageProperty(url = "https://www.example.com"),
        "Contact" to PageProperty(email = "[email protected]"),
      )
    )
    
    // Properties can be addressed by their ID too.
    val severityId = newPage.properties["Severity"]!!.id

    // Update properties in the page
    val updatedPage = client.updatePage(
        pageId = newPage.id,
        // Update only "Severity" property
        properties = mapOf(
          severityId to PageProperty(select = severityOptions.single { it.name == "Medium" }),
        )
      )

    // Fetch the latest data of the page
    val retrievedPage = client.retrievePage(newPage.id)
  }
}

private fun String.asRichText(): List<PageProperty.RichText> =
  listOf(PageProperty.RichText(text = PageProperty.RichText.Text(content = this)))

Using in Java

Even when you use this SDK in Java and other languages, all the classes/methods should be accessible. If you find issues, please let us know the issue in this project's issue tracker.

package integration_tests;

import notion.api.v1.NotionClient;
import notion.api.v1.model.search.SearchResults;
import org.junit.Assert;

public class Readme {
  public static void main(String[] args) {
    NotionClient client = new NotionClient(System.getenv("NOTION_TOKEN"));
    try {
      SearchResults results = client.search("Test Database");
      Assert.assertNotNull(results);
    } finally {
      client.close();
    }
  }
}

OAuth Support

The Notion app installation via the OAuth flow is also supported. To learn how to implement it, please check an example app built with Ktor web framework in the core library project.

Plugins

By default, the NotionClient utilizes only JDK's java.net.HttpURLConnection and Gson library for JSON serialization.

For HTTP communications and logging, you can easily switch to other implementations.

Pluggable HTTP Client

As some may know, java.net.HttpURLConnection does not support PATCH request method ๐Ÿ˜ข. Thus, the default httpClient has to make an "illegal reflective access" to overcome the limitation for perfoming PATCH method requests (see this class for details).

The PATCH method workaround does not work with OpenJDK 19 or newer. Thus, if you use PATCH method API calls such as PATCH https://api.notion.com/v1/pages/{page_id}, we recommend other httpClient implementations listed below. If you don't use PATCH method APIs at all and don't want to add any extra dependencies, the default httpClient works fine for you.

// Add this if you use java.net.http.HttpClient in JDK 11+
// Please note that this module does not work on Android runtime
implementation("com.github.seratch:notion-sdk-jvm-httpclient:${notionSdkVersion}")

// Add this if you use OkHttp 5.x (still alpha)
// If you have other dependencies relying on okhttp 5.x (e.g., Retrofit)
implementation("com.github.seratch:notion-sdk-jvm-okhttp5:${notionSdkVersion}")

// Add this if you use OkHttp 4.x
// Although the package name is `okhttp3`, the latest version is 4.x
implementation("com.github.seratch:notion-sdk-jvm-okhttp4:${notionSdkVersion}")

// Add this if you use OkHttp 3.x
// If you have other dependencies relying on okhttp 3.x (e.g., Retrofit)
implementation("com.github.seratch:notion-sdk-jvm-okhttp3:${notionSdkVersion}")

You can switch the httpClient in either of the following ways:

import notion.api.v1.NotionClient
import notion.api.v1.http.JavaNetHttpClient

val client = NotionClient(
    token = System.getenv("NOTION_TOKEN"),
    httpClient = JavaNetHttpClient(),
)

or

import notion.api.v1.NotionClient
import notion.api.v1.http.OkHttp3Client

val client = NotionClient(token = System.getenv("NOTION_TOKEN"))
client.httpClient = OkHttp3Client()

Pluggable Logging

You can change the logger property of a NotionClient instances Currently, this library supports its own stdout logger (default), java.util.logging, and slf4j-api based ones. Here are the steps to switch to an slf4j-api logger. Add the following optional module along with your favorite implementation (e.g., logback-classic, slf4j-simple).

implementation("com.github.seratch:notion-sdk-jvm-slf4j:${notionSdkVersion}") // slf4j-api 1.7
implementation("org.slf4j:slf4j-simple:1.7.36")

Now you can switch to your slf4j logger. As with the httpClient example, you can use the setter method too.

import notion.api.v1.NotionClient
import notion.api.v1.http.JavaNetHttpClient
import notion.api.v1.logging.Slf4jLogger

// for slf4j-simple
System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "debug")

val client = NotionClient(
    token = System.getenv("NOTION_TOKEN"),
    httpClient = JavaNetHttpClient(),
    logger = Slf4jLogger(),
)

If you desire to use slf4j-api v2 instead, you can use the module for the major version as below:

implementation("com.github.seratch:notion-sdk-jvm-slf4j2:${notionSdkVersion}") // slf4j-api 2.0
implementation("org.slf4j:slf4j-simple:2.0.0")

Why isn't JSON serialization pluggable?

We don't support other JSON libraries yet. There are two reasons:

Necessity of polymorphic serializers for list objects

In the early development stage of this SDK, we started with kotlinx.serialization. It worked well except for the Search API responses. The results returned by the API requires polymorphic serializers for properties: List<DatabaseProperty | PageProperty> (this is a pseudo-code illustrating the property is a list of union type). We could not find a way to handle the pattern with the library at that time.

Easily enabling camelCased property names

We know a few novel Kotlin libraries do not support the conversions between snake_cased keys and camelCased keys. Although we do respect the opinion and see the benefit, we still prefer consistent field naming in the Java world. This is another major reason why we did not go with either of kotlinx.serialization and Moshi.

Supported Java Runtimes

  • OpenJDK 8 or higher
  • All Android runtime versions supported by Kotlin 1.x

As notion-sdk-jvm-httpclient utilizes java.net.http.HttpClient, the module works with JDK 11 and higher versions.

License

The MIT License

notion-sdk-jvm's People

Contributors

seratch avatar dependabot[bot] avatar scordio avatar j-mr-t avatar looorent avatar mrvik avatar sillycoon avatar eblanchette avatar landicefu avatar twisterrob avatar software-atelier avatar whatasame avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.