Настройка Prisma 7 с PostgreSQL в проекте на TypeScript и Node.js
Исправьте распространённые ошибки настройки Prisma 7 в TypeScript: от проблем с строковыми или неопределёнными URL до ошибок, связанных с параметром rootDir, а также подключите PostgreSQL с помощью адаптера драйвера pg.
Источники: 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 содержит подробную информацию, специфичную для этой фреймворк-среды.