Главная / Статьи

Настройка Prisma 7 с PostgreSQL в проекте на TypeScript и Node.js

Исправьте распространённые ошибки настройки Prisma 7 в TypeScript: от проблем с строковыми или неопределёнными URL до ошибок, связанных с параметром rootDir, а также подключите PostgreSQL с помощью адаптера драйвера pg.

Издатель: REACTAPP.TOP7 мин чтения1666 слов

Источники: I Wasted 4 Hours Setting Up Prisma — Here’s How You Should Set Up Prisma v7

Попытка использования гайда по быстрому старту Prisma в обычном проекте на TypeScript и Node.js часто заканчивается множеством ошибок компилятора ещё до того, как будет выполнен хотя бы один запрос. Проблема не в самих моделях; она связана с тем, как компилятор TypeScript, новый файл конфигурации Prisma и генерируемый клиент взаимодействуют с традиционной структурой папок src/dist. В этом руководстве объясняются три наиболее часто встречающиеся ошибки, причины их возникновения, а также пошаговая настройка с PostgreSQL, которая позволяет без проблем выполнять компиляцию. Prisma 7 изменил несколько стандартных настроек, поэтому обязательно ознакомьтесь с актуальной документацией Prisma на предмет возможных изменений с момента написания этого руководства.

Три ошибки, которые мешают правильной настройке

Адрес подключения введён как строка или имеет значение undefined

В файле prisma.config.ts URL базы данных обычно считывается с помощью process.env.DATABASE_URL. TypeScript задаёт тип каждой переменной окружения как string | undefined, поскольку ничто не гарантирует её установку во время выполнения. В настройках ожидается обычный тип string, поэтому компилятор отклоняет это присваивание.

prisma.config.ts вне корневого каталога

В типичном проекте TypeScript значение rootDir устанавливается в src, а значение outDir — в dist. Prisma создает файл prisma.config.ts в корне проекта, и по умолчанию компилятор включает все найденные файлы с расширением .ts. Затем он выдает ошибку, указывая на то, что файл, находящийся вне rootDir, является частью программы. Перемещение конфигурации в папку src может устранить ошибку, но это неверное решение: папка src предназначена для кода приложения, такого как маршруты, контроллеры и механизмы доступа к данным, а не для конфигурации инструментов.

Генерируемый клиент вне корневой директории

То же самое происходит с генерируемым клиентом. Если Prisma сохраняет его в папку generated/prisma в корне проекта, компилятор снова находит файлы TypeScript за пределами rootDir. Размещение генерируемого кода в папке src также является плохим решением, поскольку это результат сборки команды prisma generate, а не исходный код, который вы поддерживаете.

Если эти проблемы остаются нерешенными, они мешают запуску проекта. Еще один неприятный эффект заключается в том, что скомпилированный JavaScript для файла prisma.config.ts может оказаться вне папки dist, что засоряет репозиторий. Исправление ошибок по одной часто приводит к появлению новых, поэтому целесообразно исправить всю структуру проекта целиком.

Шаг 1: создание проекта и установка зависимостей

Начните с пустого проекта TypeScript. Установите компилятор, tsx для прямой работы с TypeScript, а также типовые определения Node, затем сгенерируйте файл tsconfig.json:

npm init
npm install typescript tsx @types/node --save-dev
npx tsc --init

Далее установите Prisma. CLI и типовые определения pg являются зависимостями разработки; клиент, адаптер драйвера PostgreSQL, драйвер pg и dotenv — зависимостями времени выполнения:

npm install prisma @types/pg --save-dev
npm install @prisma/client @prisma/adapter-pg pg dotenv

Здесь важен пакет @prisma/adapter-pg. В Prisma 7 клиент взаимодействует с базой данных через адаптер драйвера JavaScript, поэтому ему передается настроенное соединение с pg, а не просто URL, указанный в схеме.

Шаг 2: настройка ES-модулей и структуры компилятора

Отметьте пакет как ES-модуль в файле package.json:

{
  "type": "module"
}

Затем укажите каталоги исходного кода и результатов в файле tsconfig.json, а также создайте папку src:

"rootDir": "./src",
"outDir": "./dist",

Шаг 3: инициализация Prisma

Запустите CLI один раз (это просто выводит доступные команды и подтверждает, что установка работает):

npx prisma

Затем инициализируйте Prisma для PostgreSQL:

npx prisma init --datasource-provider postgresql --output ../generated/prisma

Это создает файл prisma.config.ts, папку prisma, в которой находится файл schema.prisma, и файл .env с адресом базы данных. Параметр --output определяет место генерации клиента; на шаге 4 будет рассмотрен этот выбор. Именно после этого шага появляются описанные выше ошибки.

Шаг 4: исправление конфигурации

Три целенаправленных изменения устраняют все три ошибки.

Чтение адреса с помощью инструмента env от Prisma

Замените содержимое prisma.config.ts на приведённое ниже. Этот файл написан на TypeScript, хотя в примере указано иное.

import "dotenv/config";
import type { PrismaConfig } from "prisma";
import { env } from "prisma/config";

export default {
  schema: "prisma/schema.prisma",
  migrations: {
    path: "prisma/migrations",
    seed: "tsx prisma/seed.ts",
  },
  datasource: {
    url: env("DATABASE_URL"),
  },
} satisfies PrismaConfig;

Что стоит обратить внимание:

  • import "dotenv/config" загружает файл .env до того, как что-либо его прочитает. В Prisma 7 он больше не загружается автоматически в такой конфигурации.
  • env("DATABASE_URL") из модуля prisma/config возвращает значение типа string, и при отсутствии переменной возникает явная ошибка, что устраняет возможность ошибки типа string | undefined.
  • Функция satisfies PrismaConfig проверяет тип объекта без его расширения.
  • В конфигурации также указывается, где находятся схемы и миграции, а также какая команда заполняет базу данных.

Ограничьте содержимое, которое включает компилятор

Добавьте запись include в конец файла tsconfig.json:

"include": ["src"],

Это указывает компилятору собирать только файлы, находящиеся в папке src. Инструмент Prisma CLI по-прежнему считывает файл prisma.config.ts самостоятельно, но tsc перестаёт рассматривать его как часть вашей программы, поэтому ошибка rootDir исчезает, и никакой лишний JavaScript не выводится за пределы папки dist.

Сгенерировать клиентскую часть в node_modules

Наконец, отредактируйте файл schema.prisma, чтобы у генератора не было специального пути вывода:

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"

Без параметра output генератор prisma-client-js сохраняет клиентскую библиотеку в папке node_modules, поэтому ничего не остается в корне проекта, и ошибка rootDir исчезает. Фрагмент кода заканчивается после настройки provider для источника данных; закройте блок скобкой. В Prisma 7 адрес подключения хранится в файле prisma.config.ts, а не в схеме.

Имейте в виду, что это компромисс. Более новый генератор Prisma — prisma-client — разработан с учётом явного указания каталога вывода, тогда как prisma-client-js является более старым генератором. Если вы переходите на новый вариант, сохраняйте результат его работы за пределами папки src и исключайте эту папку из обработки tsc с помощью параметра include, как описано выше.

Шаг 5: добавление адреса базы данных и миграция

Поместите строку подключения в файл .env. Указанное ниже значение является местохождением; используйте собственную базу данных и никогда не сохраняйте реальные значения:

DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"

Определите свои модели в файле schema.prisma, затем создайте и примените первую миграцию:

npx prisma migrate dev --name init

Шаг 6: генерация клиента

Сгенерируйте типизированный клиент на основе схемы:

npx prisma generate

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

Шаг 7: создание общего экземпляра Prisma

Создайте файл src/lib/prisma.ts, в котором будет храниться один клиент для всего приложения. В этом файле формируется адаптер к PostgreSQL на основе строки подключения, который затем передается в PrismaClient. Этот код также написан на TypeScript:

import "dotenv/config";
import { PrismaPg } from "@prisma/adapter-pg";
import { PrismaClient } from "../../node_modules/@prisma/client/index.js";

const connectionString = `${process.env.DATABASE_URL}`;

const adapter = new PrismaPg({ connectionString });
const prisma = new PrismaClient({ adapter });

export default prisma;

Клиент импортируется через явный относительный путь из папки node_modules:

import { PrismaClient } from "../../node_modules/@prisma/client/index.js";

Этот путь работает потому, что клиент был сгенерирован в каталоге node_modules на шаге 4. В большинстве конфигураций указатель @prisma/client разрешается к тому же пакету, поэтому сначала стоит попробовать именно его; обращаться к явному пути следует только в том случае, если настройки разрешения модулей этого требуют.

Одна из подводных камней в этом фрагменте кода: оборачивание значения process.env.DATABASE_URL в строку-шаблон превращает отсутствующее значение в текст "undefined", что позже приводит к непонятной ошибке подключения. Краткая проверка, выбрасывающая исключение при отсутствии переменной, делает сбои очевидными.

Теперь импортируйте этот экземпляр там, где вам нужен доступ к базе данных, например, в контроллерах или сервисах, и выполняйте через него операции CRUD. Использование одного общего клиента позволяет избежать создания нового пула соединений для каждого файла.

Основные выводы

  • Большинство ошибок настройки Prisma 7 в TypeScript возникают из-за правил rootDir компилятора, а не из-за самого Prisma.
  • Используйте функцию env() из модуля prisma/config вместе с dotenv/config, чтобы URL базы данных загружался правильно с указанием типов.
  • Ограничьте действие инструмента tsc с помощью параметра "include": ["src"], чтобы файлы инструментов и генерируемый код не попадали в процесс сборки.
  • Храните генерируемые клиенты не в папке src, а либо в node_modules
  • , либо в отдельной папке, исключенной из сборки.
  • Создайте один общий объект PrismaClient с адаптером PrismaPg и проверяйте строку подключения при запуске.

Если вы используете Next.js вместо обычного сервиса Node.js, наш гид по настройке Prisma 7 в проекте Next.js 16 на TypeScript содержит подробную информацию, специфичную для этой фреймворк-среды.