Начало работы с Notion API и его SDK для JavaScript

После создания учетной записи и входа в систему Программирование и разработка

Notion — это многофункциональное приложение для организации любого контента, от заметок до календарей и напоминаний. Оно недавно запустила собственный API, и в этой статье мы будем использовать этот API для создания небольшого интерфейса, который будет подключать Notion к нашей собственной базе данных.

Notion представила миру свой API в виде открытой бета-версии. У него отличная документация, к нему действительно легко получить доступ, и, что более важно для нас, разработчиков JavaScript, он также предлагает SDK для JavaScript. 🎉

Хотя для работы с этой статьей не требуется никаких предварительных знаний (я предоставлю все необходимые шаги), мы будем иметь дело с клиентским и внутренним кодом, поскольку здесь задействована небольшая часть установки Node.js и Express.

Установка

Наша установка будет разделена на две части. Первый будет охватывать шаги, которые нам нужно выполнить в отношении программного обеспечения и API Notion. Во втором мы получим код, инициализировав папку, добавив зависимость Notion и создав начальную index.jsи отредактировав, package.jsonчтобы все работало.

Чтобы продолжить, вам понадобится учетная запись Notion, а также последняя копия.

Идея установки

Если у вас еще нет учетной записи Notion, создайте ее, перейдя по этой ссылке. У него очень щедрый уровень бесплатного пользования, и вам не нужно добавлять информацию об оплате!

После создания учетной записи и входа в систему создайте новую страницу, выбрав » Добавить страницу» и дайте ей имя. Для этого урока мы выберем Tableбазу данных. Это даст нам пустую таблицу, а это именно то, что мы хотим!

После создания учетной записи и входа в систему

Следующий шаг — создать несколько столбцов на нашем сайте databaseи заполнить их фиктивными данными. Для этого урока мы будем работать только с Nameи Roleполей, как будто мы работаем с базой данных сотрудников в компании.

Теперь перейдем на сайт документации

Теперь перейдем на сайт документации. В верхнем углу вы увидите ссылку » Мои интеграции«. Если вы нажмете на нее, вы попадете на экран с надписью «Мои интеграции», и ваш, конечно же, будет пустым.

Нажмите Создать новую интеграцию, введите свой заголовок

Нажмите Создать новую интеграцию, введите свой заголовок и обязательно выберите свой Associated workspace(он будет выбран по умолчанию, но убедитесь в этом). Нажмите » Отправить», и вы будете перенаправлены на новую страницу с Internal Integration Token(мы будем использовать это в нашем коде) и с двумя полями для выбора того, где вы хотите использовать свою интеграцию. Вам не нужно ничего делать на этой странице, кроме копирования tokenи нажатия Сохранить изменения.

Нажмите Создать новую интеграцию, введите свой заголовок и обязательно

Нажмите Создать новую интеграцию, введите свой заголовок и обязательно

Теперь вернитесь в рабочее пространство Notion. В нашей недавно созданной базе данных мы хотим нажать » Поделиться», а затем » Пригласить». Затем вы сможете выбрать свою недавно созданную интеграцию. Выберите его и нажмите » Пригласить «, и настройка Notion завершена. Отличная работа! 🙌

Выберите его и нажмите Пригласить , и настройка Notion завершена

Настройка кода

Теперь давайте напишем код. Откройте свой терминал и сделайте mkdir notion-api-test(это создаст папку с именем notion-api-test) в выбранном вами месте, а затем войдите в свою папку с помощью cd notion-api-testи сделайте npm init -y(эта команда создаст файл package.jsonс некоторыми базовыми настройками, а -yфлаг автоматически отвечает на некоторые запросы, чтобы вы не не надо с ними возиться).

Как я упоминал ранее, мы собираемся использовать notion-sdk-js, и для этого нам нужно установить его как зависимость, так что мы и сделаем npm install @notionhq/client.
Теперь откройте notion-api-testв вашем редакторе кода и создать начальную index.jsна rootи отредактировать package.json scripts, заменив то, что там со следующими:

"scripts": {
    "start": "node index"
},

Давайте также создадим.gitignoreфайл и еще один с именем.env. Это.gitignoreпозволяет вам помещать внутри разные имена файлов / папок, а это означает, что эти файлы / папки не будут добавлены в ваше репо, когда вы нажмете код. Это очень важно, потому что наш integration token(помните?) Будет внутри.envфайла, например:

NOTION_API_KEY = YOUR_TOKEN_HERE

Это означает, что внутри.gitignoreвы должны добавить это в первую строку:

.env

Теперь, когда у нас есть.envфайл, мы также должны добавить новую зависимость dotenv, чтобы вы могли загрузить свою NOTION_API_KEYпеременную. Вы можете сделать это, делая npm install dotenv.

Настройка кода завершена, и ваша папка должна выглядеть примерно так, как показано ниже. 🎉

Настройка кода завершена, и ваша папка должна выглядеть примерно так

Получение данных из Notion API

Теперь, когда скучная часть закончилась, перейдем к хорошему! Нашим index.jsфайлом будет файл Node.js, а следующий блок кода показывает наш начальный код и то, что именно делает каждая строка!

// this will allow us to import our variable
require("dotenv").config();
// the following lines are required to initialize a Notion client
const { Client } = require("@notionhq/client");
// this line initializes the Notion Client using our key
const notion = new Client({ auth: process.env.NOTION_API_KEY });

Здесь нам также понадобится дополнительная вещь, а именно идентификатор базы данных, которую мы создали в нашей рабочей области Notion. Его можно получить из адресной строки браузера. Он идет после имени вашей рабочей области (если она у вас есть), косой черты ( myworkspace/) и перед вопросительным знаком ( ?). Идентификатор состоит из 32 символов и состоит из букв и цифр.

https://www.notion.so/myworkspace/a8aec43384f447ed84390e8e42c2e089?v=...
                                  |--------- Database ID --------|

В целях безопасности вы также должны вставить этот идентификатор в свой.envфайл, чтобы он выглядел примерно так:

NOTION_API_KEY = YOUR_TOKEN_HERE
NOTION_API_DATABASE = YOUR_DATABASE_ID_HERE

Затем мы импортируем его в наш index.jsс помощью этого:

const databaseId = process.env.NOTION_API_DATABASE;

Теперь, чтобы убедиться, что наш API работает, давайте создадим функцию, которая обращается к нашей базе данных. Для этого мы создадим async function:

const getDatabase = async () => {
  const response = await notion.databases.query({ database_id: databaseId });

  console.log(response);
};

getDatabase();

Если вы теперь запустите npm startсвой терминал, вы должны увидеть журнал objectсо resultsсвойством, имеющим массив. Этот массив содержит записи в вашей базе данных. Чтобы изучить их, мы можем сделать следующее:

const getDatabase = async () => {
  const response = await notion.databases.query({ database_id: databaseId });

  const responseResults = response.results.map((page) => {
    return {
      id: page.id,
      name: page.properties.Name.title[0]?.plain_text,
      role: page.properties.Role.rich_text[0]?.plain_text,
    };
  });

  // this console.log is just so you can see what we're getting here
  console.log(responseResults);
  return responseResults;
};

Приведенный выше код сопоставляется с нашим results(сопоставлением записей в нашей базе данных), и мы сопоставляем пути для различных свойств с именами, которые мы выбираем (в данном случае id, nameи role). Обратите внимание, насколько конкретен путь к объекту. Я использовал необязательную цепочку для учета пустых строк в базе данных или строк, в которых одно или другое из этих полей не заполнено.

В любом случае, не стесняйтесь экспериментировать с различными свойствами и помните, что это вопрос проб и ошибок, и что каждый API ведет себя и организует информацию по-разному. Здесь важно просмотреть каждое свойство, пока мы не дойдем до искомой информации.

Если console.log()вам не нравится изучать каждое свойство и использовать его, вы всегда можете использовать Postman для проверки ответа. К сожалению, это выходит за рамки данного руководства, но вы можете проверить публикацию » Как освоить рабочий процесс API с помощью Postman «, чтобы попробовать!

Еще одно важное замечание: обратите внимание на notion.databases.queryто, что мы использовали. Если вы посмотрите документацию по API Notion, вы увидите, что мы используем POST | Query a database. Мы могли бы использовать просто GET | Retrieve a database, но здесь я хотел бы попросить вас прочитать документацию и попытаться отсортировать список по-другому!

Прежде чем мы завершим эту часть, давайте изменим нашу getDatabaseфункцию, чтобы мы могли правильно импортировать ее в другой файл, который мы создадим. Должно получиться так:

exports.getDatabase = async function () {
  const response = await notion.databases.query({ database_id: databaseId });

  const responseResults = response.results.map((page) => {
    return {
      id: page.id,
      name: page.properties.Name.title[0]?.plain_text,
      role: page.properties.Role.rich_text[0]?.plain_text,
    };
  });

  return responseResults;
};

Настройка экспресс-сервера

Сделав предыдущий шаг, мы теперь можем успешно получить наши результаты. Но чтобы иметь возможность использовать их должным образом, нам нужно создать сервер, и самый простой способ сделать это — поскольку мы используем Node.js — использовать Express. Итак, мы начнем с запуска npm install expressи создания нового файла в корне с именем server.js.

Если expressвас смущает, не волнуйтесь. Мы будем использовать его, чтобы облегчить нашу работу и создать быструю внутреннюю часть и сервер для нашего приложения. Без него мы не смогли бы правильно получить наши данные, поскольку мы инициализируем наш клиент Notion в нашем коде.

В нашем server.jsфайле мы начнем с импорта expressмодуля, в котором у нас есть наш код ( index.js), наша getDatabaseфункция, номер порта и переменная для инициализации нашей expressфункции:

const express = require("express");
// our module
const moduleToFetch = require("./index");
// our function
const getDatabase = moduleToFetch.getDatabase;

const port = 8000;
const app = express();

// this last command will log a message on your terminal when you do `npm start`
app.listen(port, console.log(`Server started on ${port}`));

Поскольку теперь мы импортируем наш код в новый файл, server.jsмы должны изменить нашу startкоманду на package.jsonпоиск server, чтобы она выглядела так:

"scripts": {
    "start": "node server"
},

Если вы сейчас запустите npm start, вы увидите Server started on 8000сообщение, которое означает, что наша установка работает должным образом! Отличная работа!

Теперь, когда наше expressприложение работает, нам нужно заставить нашу базу данных работать с ним, и мы можем сделать это с помощью app.get(). Этому методу нужен путь (в нашем случае это не имеет значения) и функция обратного вызова (которая вызовет нашу getDatabaseфункцию):

app.get("/users", async (req, res) => {
  const users = await getDatabase();
  res.json(users);
});

В приведенном выше коде используется упомянутый app.getметод, и внутри нашей функции обратного вызова мы получаем результаты от нашей функции, и мы используем.json()функцию промежуточного программного обеспечения Express, которая анализирует запрос на читаемые и рабочие данные. (Вы можете узнать об этом немного больше в официальной документации.)

Это означает, что теперь мы успешно получаем доступ к нашим данным и создали маршрут для их «выборки». В качестве последнего шага мы должны добавить app.use(express.static(«public»));в наш server.jsфайл, чтобы конечный результат выглядел примерно так:

const express = require("express");
// our module
const moduleToFetch = require("./index");
// our function
const getDatabase = moduleToFetch.getDatabase;

const port = 8000;
const app = express();

// the code line we just added
app.use(express.static("public"));

app.get("/users", async (req, res) => {
  const users = await getDatabase();
  res.json(users);
});

app.listen(port, console.log(`Server started on ${port}`));

Этот последний фрагмент кода сообщает нашему бэкэнду useо конкретной папке, в которой мы создадим наш интерфейсный код, которым будет publicпапка. Здесь мы будем работать с нашими HTML, CSS и JavaScript, чтобы получить доступ к этому /usersмаршруту, который мы создали на нашем сервере. Давайте приступим к делу!

Отображение данных из Notion API

Мы начнем с создания в корне нашего проекта папки с именем public. Здесь будет жить наш интерфейсный код.

Части HTML и CSS просты, поэтому я в основном просто оставлю здесь код и сосредоточусь на части JavaScript, поскольку это то, для чего мы все здесь!

Наш HTML ( /public/index.html) будет выглядеть так:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Notion API Test</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <div id="banner">Notion API Database Test</div>
    <div id="wrapper">
      <div id="container"></div>
    </div>

    <script type="module" src="./main.js"></script>
  </body>
</html>

И наш CSS ( /public/style.css) будет выглядеть так:

body,
html {
  padding: 0;
  margin: 0;

  height: 100vh;
  width: 100vw;
  font-family: Arial, Helvetica, sans-serif;

  position: relative;
}

#banner {
  height: 50px;

  display: flex;
  justify-content: center;
  align-items: center;

  background-color: #ef4444;
  color: white;
  font-weight: bold;
}

#wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
  height: calc(100vh - 50px);
}

#container {
  width: 80vw;
  margin: auto;

  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  grid-auto-rows: 200px;
  gap: 20px;
}

.userContainer {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;

  box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px;
  border-radius: 10px;
}

Если вы сейчас запустите npm startсвой проект и посетите http: // localhost: 8000, вы должны увидеть свой интерфейсный код.

Если вы сейчас запустите npm startсвой проект и посетите http

Теперь о нашем public/main.jsфайле! Нашим первым шагом будет запрос к маршруту, который мы создали на бэкэнде ( /users/), что позволит нам получить информацию о нашей базе данных:

const getDataFromBackend = async () => {
  const rest = await fetch("http://localhost:8000/users");
  const data = await rest.json();

  return data;
};

// Note that top-level await is only available in modern browsers
// https://caniuse.com/mdn-javascript_operators_await_top_level
const res = await getDataFromBackend();
console.log(res);

Когда вы регистрируете возвращаемое значение этой функции, вы увидите в своих инструментах разработчика ту же информацию, которую мы раньше могли видеть только в терминале, а это означает, что теперь мы можем использовать наши данные во внешнем интерфейсе! Молодец! 🎉

Давайте теперь покажем эти данные внутри нашего

Давайте теперь покажем эти данные внутри нашего <div id=»container»></div>, что будет очень легко. Мы начнем с выполнения a, getElementById чтобы получить нужный элемент, а затем создадим функцию, которая будет запускаться getDataFromBackend()и перебирать каждый объект внутри нашего dataмассива и помещать это содержимое в наш HTML. Вот мой подход к этому:

// Add data to HTML
const addData = async () => {
  const data = await getDataFromBackend();

  data.forEach((value) => {
    const div = document.createElement("div");
    div.classList.add("userContainer");
    div.innerHTML = `
        <h3>${value.name}</h3>
        <p>${value.role}</p>
    `;

    container.append(div);
  });
};

addData();

Итак, еще раз, наша dataпеременная (внутри addDataфункции) — это та же информация, которую мы могли видеть в журнале (массив объектов), и мы перебираем ее, создавая

с классом userContainer, а внутри у нас есть nameи roleдля каждая из наших записей в базе данных.

Если вы сейчас запустите свой код, вы должны увидеть что-то вроде того, что изображено ниже!

Если вы сейчас запустите свой код, вы должны увидеть что-то вроде того

Запись данных в нашу базу данных понятий

Это было бы отличной точкой остановки для наших экспериментов с Notion API, но мы можем сделать даже больше! Давайте теперь добавим новые записи в нашу базу данных с помощью Create Pageзапроса POST (который можно найти здесь ), чтобы у нас было полностью функционирующее и работающее приложение, использующее практически все возможности API Notion.

Итак, наша идея состоит в том, чтобы добавить форму в наш интерфейс, которая при заполнении и отправке будет отправлять новые данные в нашу базу данных, которые затем будут отображаться в нашем интерфейсе!

Начнем с добавления новой функции в наш файл index.jsnamed newEntryToDatabase. Учитывая документацию, мы теперь должны это сделать const response = await notion.pages.create(), и мы должны передать объект, который соответствует текущей базе данных, над которой мы работаем. У него также будет два аргумента nameи role, которые для этого проекта будут выглядеть так:

exports.newEntryToDatabase = async function (name, role) {
  const response = await notion.pages.create({
    parent: {
      database_id: process.env.NOTION_API_DATABASE,
    },
    properties: {
      Name: {
        title: [
          {
            text: {
              content: name,
            },
          },
        ],
      },
      Role: {
        rich_text: [
          {
            text: {
              content: role,
            },
          },
        ],
      },
    },
  });

  return response;
};

Обратите внимание, что мы делаем с этим объектом. По сути, мы делаем то же самое, что и getDatabaseс нашей responseResultsпеременной, просматривая каждое свойство, пока не дойдем до свойства, с которым действительно хотим работать. Здесь мы используем наши аргументы как значения свойств. Если это выглядит сбивающим с толку, это абсолютно нормально; просмотрите связанную документацию в этом разделе, чтобы увидеть больше примеров!

Теперь, перейдя к нашему server.js, давайте не забудем импортировать нашу новую функцию с помощью const newEntryToDatabase = moduleToFetch.newEntryToDatabase;в верхней части файла. Мы также сделаем POSTзапрос, используя app.post(). Здесь нам также нужен маршрут (он будет /submit-form), и наша функция обратного вызова должна получать nameи roleиз запроса (наши заполненные поля формы) и вызывать newEntryToDatabaseс этими двумя аргументами. Затем мы завершаем нашу функцию перенаправлением на наш базовый маршрут, /а также завершаем наш запрос.

Нашему server.jsфайлу также потребуется немного кода внутри app.use()функции, которой является расширение express.urlencoded. Это промежуточное ПО для Express, поэтому мы можем использовать POSTзапрос, поскольку на самом деле мы отправляем данные:

const express = require("express");
const moduleToFetch = require("./index");
const getDatabase = moduleToFetch.getDatabase;
// importing our function
const newEntryToDatabase = moduleToFetch.newEntryToDatabase;
const port = 8000;

const app = express();

app.use(express.static("public"));
app.use(
  express.urlencoded({
    extended: true,
  })
);

app.get("/users", async (req, res) => {
  const users = await getDatabase();
  res.json(users);
});

// our newly added bit of code
app.post("/submit-form", async (req, res) => {
  const name = req.body.name;
  const role = req.body.role;
  await newEntryToDatabase(name, role);
  res.redirect("/");
  res.end();
});

app.listen(port, console.log(`Server started on ${port}`));

Теперь наш бэкэнд готов, и нам нужно поработать над нашим клиентским кодом. На этом этапе вам следует перезапустить сервер Express, чтобы он распознал изменения.

Честно говоря, единственное, что вам нужно во внешнем коде, — это <form> HTML -код с method=»POST»и action=»/submit-form». Это в основном сообщает нашему коду, какой это должен быть тип формы, а также связывает его с route ( /submit-form), который мы создали для обработки запросов.

Так что чего-то вроде следующего было бы более чем достаточно:
<form method="POST" action="/submit-form">
  <input type="text" name="name" placeholder="Insert user name" required />
  <input type="text" name="role" placeholder="Insert user role" required />
  <input type="submit" />
</form>
Если мы заполним поля, отправим нашу форму и перезагрузим страницу, мы увидим новую запись, а если мы войдем в нашу рабочую область Notion, мы увидим запись там. Функционал полный. Отличная работа! 🎉

Но для улучшения нашего интерфейса идея заключается в том, что у нас buttonбудет модальное окно, при нажатии на которое будет открываться модальное окно form(также с возможностью его закрытия без заполнения), поэтому вот мой HTML-код:

<!-- The rest of the code above -->
<div id="wrapper">
  <div id="container"></div>
</div>

<div id="addUserFormContainer">
  <button id="closeFormButton">Close</button>
  <form method="POST" action="/submit-form" id="addUserForm">
    <h1 id="formTitle">Add a new user to your database</h1>
    <input
      type="text"
      name="name"
      placeholder="Insert user name"
      class="inputField"
      required
    />
    <input
      type="text"
      name="role"
      placeholder="Insert user role"
      class="inputField"
      required
    />
    <input type="submit" id="submitFormInput" />
  </form>
</div>

<button id="newUserButton">Add a new user</button>

<script type="module" src="./main.js"></script>
<!-- The rest of the code below -->

И вот CSS, который должен сопровождать его:

/* The rest of the code above */
#newUserButton {
  position: absolute;
  bottom: 10px;
  right: 10px;

  padding: 10px 20px;

  background-color: #ef4444;
  color: white;
  font-weight: bold;

  border: none;
  border-radius: 4px;
}

#addUserFormContainer {
  position: absolute;
  top: 0;
  left: 0;

  height: 100vh;
  width: 100vw;

  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;

  background: rgba(255, 255, 255, 0.4);
  backdrop-filter: blur(20px);
}

#closeFormButton {
  position: absolute;
  top: 10px;
  right: 10px;

  padding: 10px 20px;

  background-color: black;
  color: white;
  font-weight: bold;

  border: none;
  border-radius: 4px;
}

#formTitle {
  margin-bottom: 40px;
}

#addUserForm {
  padding: 50px 100px;
  width: 300px;

  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;

  background: white;

  box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px;
}

#addUserForm input {
  width: 100%;
  box-sizing: border-box;
}

.inputField {
  margin-bottom: 20px;
  padding: 10px 20px;

  border: 1px solid #b3b3b3;
  border-radius: 4px;
}

#submitFormInput {
  padding: 10px 20px;
  margin-bottom: none;

  background-color: #ef4444;
  color: white;
  font-weight: bold;

  border: 1px solid #ef4444;
  border-radius: 4px;
}

Если вы сейчас посетите свою страницу, вы увидите только красную кнопку без реальной полезности, так что теперь нам нужно поработать над нашим JavaScript. Поэтому давайте перейдем к нашему /public/main.jsфайлу!

Здесь мы начнем с того, что возьмем #newUserButton, #closeFormButtonи #addUserFormContainer:

const container = document.getElementById("container");
// the new variables
const openFormButton = document.getElementById("newUserButton");
const closeFormButton = document.getElementById("closeFormButton");
const addUserFormContainer = document.getElementById("addUserFormContainer");

Теперь openFormButtonмы добавим clickпрослушиватель событий, который будет стилизовать наш addUserFormContainerс помощью display: flex:

openFormButton.addEventListener("click", () => {
  addUserFormContainer.style.display = "flex";
});

Теперь, если вы нажмете кнопку » Добавить нового пользователя», откроется форма.

Чтобы закрыть formмодальное окно, нам просто нужно удалить то, flexчто мы добавляем, нажав клавишу closeFormButton, чтобы он выглядел так:

closeFormButton.addEventListener("click", () => {
  addUserFormContainer.style.display = "none";
});

И… готово! Теперь, когда вы вводите имя и роль в форму, они будут добавлены в вашу базу данных Notion и появятся во внешнем интерфейсе приложения.

Мы только что создали полностью функционирующий веб-сайт, который получает базу данных, обрабатывает данные, отображает их, а также позволяет добавлять в них! Разве это не невероятно?

Продолжая

Хотя эта демонстрация демонстрирует некоторые из важных применений API-интерфейса Notion, в нашем приложении все еще есть возможности для улучшения. Например, было бы целесообразно реализовать некоторую обработку ошибок или счетчик загрузки, показывающий, когда приложение взаимодействует с Notion (и, следовательно, не отвечает). Кроме того, вместо того, чтобы всегда запрашивать API для получения данных, вы можете легко превратить это в одностраничное приложение, которое запрашивает API один раз, а затем сохраняет данные, с которыми мы работаем, в состоянии.

Вывод

В этом проекте мы исследовали почти всю функциональность Notion API, и я думаю, что совершенно ясно, насколько это может быть потрясающе!

Читайте также:  Как подключить и выполнить SQL-запросы к базе данных PostgreSQL из Python?
Оцените статью
bestprogrammer.ru
Добавить комментарий