Руководство по созданию приложения со списком задач с использованием Next.js и Turso, базы данных Edge на основе SQLite.

Создание простого списка дел всегда является эффективным способом начать работу с новыми технологиями. В этой статье мы увидим, как создать приложение со списком дел, используя Turso, базу данных, созданную командой разработчиков libSQL, которая предлагает возможности разработчиков SQLite at the Edge, и популярный интерфейсный фреймворк Next.js.

В процессе мы увидим, насколько легко Turso можно интегрировать с Next.js для создания приложений.

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

Начиная

Turso в настоящее время доступен в закрытой бета-версии, и вы можете зарегистрироваться здесь, если вы еще этого не сделали. Получив доступ к закрытой бета-версии, вы сможете использовать ее для создания проекта.

Чтобы следовать руководству, вот репозиторий GitHub проекта. Вы можете клонировать репо и следовать следующим инструкциям.

Установка Турсо

Для начала выполните следующую команду в своем терминале, чтобы загрузить CLI Turso.

# On macOS or Linux with Homebrew
brew install chiselstrike/tap/turso

# Manual scripted installation
curl -sSfL https://get.tur.so/install.sh | bash

После установки вам необходимо войти в Turso CLI.

$ turso auth login

При первой настройке вам будет предложено разрешить Turso использовать вашу учетную запись GitHub.

Далее вы будете перенаправлены на страницу аутентификации Github. Войдите в свою учетную запись GitHub.

Настройка базы данных

Создайте базу данных с именем «todo» и используйте оболочку Turso для отправки запросов в базу данных.

# Create the database
$ turso db create todo

# Open the database on the Turso shell
$ turso db shell todo

Создайте таблицу в базе данных
Теперь, когда у нас запущена оболочка, давайте создадим таблицу для хранения задач. Следующий запрос SQL создаст таблицу с именем todosс двумя столбцами, id и text.

Скопируйте и выполните следующую инструкцию в оболочке.

CREATE TABLE IF NOT EXISTS todos (
  id integer primary key,
  text text not null
);

Выйти из оболочки

.quit

Получите уникальный URL-адрес базы данных Turso с помощью следующей команды и сохраните его для последующего использования.

turso db show --url todo

Настройка проекта

После того, как вы клонировали репозиторий выше, ваш проект будет выглядеть локально так.

├── README.md
├── next.config.js
├── node_modules
├── package.json
├── yarn-error.log
├── yarn.lock
└──src 
|── pages
│   ├── _app.js
│   ├── _document.js
│   ├── api
│   │   ├── turso.js
│   │   └── todos
│   │       ├── add.js
│   │       ├── delete.js
│   │       └── index.js
│   └── index.js
├── styles
│   ├── Home.module.css
│   └── global.css
└── utils
    └── index.js

Переименуйте .env_sapmle в .env и назначьте URL-адрес базы данных, который мы получили ранее, переменной окружения NEXT_PUBLIC_DB_URL.

NEXT_PUBLIC_DB_URL={Turso Database URL}

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

В файле src/pages/api/turso.js мы экспортируем новый экземпляр клиента базы данных db и импортируем его всякий раз, когда нам нужно выполнять транзакции базы данных.

import { createClient } from "@libsql/client";

const config = {
  url: process.env.NEXT_PUBLIC_DB_URL,
};

const db = createClient(config);

module.exports = {
  db
};

Добавлять и удалять задачи todo

Внутри файла src/pages/api/todos/add.js давайте реализуем логику, которая добавляет задачу в список задач, обеспечивая при этом проверку пустых представлений.

import { db } from '../turso'

export default async function handler(req, res) {
  
  if (req.method !== "POST") {
    res.status(403).json({
      message: "Only supports POST method!",
    });
    return;
  }

  const { text } = req.body;

  if (!text) {
    res.status(400).json({
      message: "Fields cannot be empty",
    });
    return;
  }

  // Inserting tasks into ‘todos’ table
  try {
    // Perform the query
    await db.execute("INSERT INTO todos (text) VALUES (?)", [text]);

    // Handle valid query result
    res.status(201).send("todo created successfully");
  } catch (err) {
    // Handle query error
    console.error(err);
    res.status(500).send("Internal Server Error");
  }
}

В файле src/pages/api/todos/delete.js напишите следующий SQL-запрос, чтобы удалить задачу из базы данных.

import { db } from '../turso'

export default async function handler(req, res) {

 const { id } = req.body;

 if (req.method !== "POST") {
  res.status(403).json({
   message: "Only supports POST method!",
  });
  return;
 }
 const todo = await db.execute(`SELECT * FROM todos WHERE id=?`, [
  id,
 ]);

 if (todo.rows?.length === 0) {
  res.status(400).json({ 
   message: "Unable to find todo" 
  });
  return;
 }

 try {
  // Perform the query
  await db.execute(
   `
   DELETE FROM todos WHERE id=?
   `,
   [id]
  );
  // Handle valid query result
  res.status(201).send('todo deleted successfully');
 } catch (err) {
  // Handle query error
  res.status(500).send("Internal server error");
 };
}

Получение задач

В файле src/pages/api/todos/index.js мы разрешаем только HTTP-запросы GET от внешнего интерфейса для получения данных списка задач, запрошенных из базы данных.

import { serializeData } from "../../../utils";
import { db } from '../turso'

export default async function handler(req, res) {

 if (req.method !== "GET") {
  res.status(403).json({
   message: "Only supports GET method!"
  });
 }

 // Fetching tasks from ‘todos’ table
 try {
  const todos = await db.execute(
   `select * from todos`
  );
  const result = serializeData(todos);
  res.status(200).json({
   data: result ? result : [],
  });
 } catch (err) {

  // Handle query error
  console.error(err);
  res.status(500).send('Internal Server Error');
 };
}

serializeData(todos) — это функция, которую мы создали для преобразования запрошенного объекта данных в массив объектов, где каждый объект в массиве представляет строку данных.

Выполнение запросов API от клиента

У нас есть готовый список задач, но он бесполезен, если веб-приложение ничего не отображает, верно? Таким образом, мы будем использовать Axios для выполнения HTTP-запросов от клиента к серверу, чтобы мы могли отображать список задач в нашем веб-приложении.

В файле src/pages/index.js мы будем делать базовые CRUD-запросы, используя Axios.

import axios from 'axios';

//Add a todo task
const addTodo = async (todo) => {
 if(!todo) {
   alert("Input is empty")
  return
 }
 await axios.post("/api/todos/add", {
  text: todo
 })
}

//Submit a todo task
const handleSubmit = async (e) => {
  e.preventDefault()

  await addTodo(userInput)
  await getTodos()
  setUserInput('')
}

//Delete a todo task
const handleDelete = async (id) => {
   await axios.post(`/api/todos/delete`, {
    id: id
  })
   await getTodos()
}

Поздравляем, теперь у вас есть полнофункциональное приложение, созданное на Next.js и Turso. Кроме того, вы можете попробовать добавить дополнительные функции или изучить функциональность базы данных.

Для приоритета снова добавляю ссылку на GitHub repo проекта. Вы можете использовать тот же код или создать новый проект, используя эту статью и исходный код для справки.

Turso в настоящее время доступен в закрытой бета-версии, и вы можете зарегистрироваться здесь, если вы еще этого не сделали.
И, пожалуйста, дайте нам знать в Discord и Twitter, если вы создадите что-то классное с Turso!