@reldens/storage Prisma Setup

How to install and use the optional Prisma driver of @reldens/storage in a project, and how to run the Prisma driver tests without touching the package files.

Prisma Is Optional

Knex is the default driver of @reldens/storage and the only one bundled with the package. Prisma is an optional driver, like Kysely, Drizzle, Objection JS and MikroORM:

  • The package package.json does not list prisma, @prisma/client or @prisma/adapter-mariadb, and no file under lib/ requires them.
  • The Prisma driver receives everything it needs through the prismaModules object, so Prisma only has to exist in the project that uses the driver, or in the storage repository when running the Prisma driver tests.
  • Unlike the other optional drivers, Prisma has no automatic loader: the prismaModules object is required, because the client is generated code that lives in the project.

Using Prisma in a Project

1. Install the Packages

npm install prisma @prisma/client @prisma/adapter-mariadb
  • Prisma 7 requires a driver adapter for MySQL / MariaDB connections. Any Prisma driver adapter works, @prisma/adapter-mariadb (class PrismaMariaDb) is the default used by the Reldens tooling.
  • When the Prisma driver is selected in the Reldens installer, it installs prisma, @prisma/client and the adapter package in the project.
  • When a @reldens/cms project is configured with the Prisma driver, the CMS CLI detects the missing Prisma packages and offers to install them.

2. Generate the Prisma Schema and Client

npx reldens-storage-prisma --host=localhost --port=3306 --user=dbuser --password=dbpass --database=dbname

The command:

  1. Writes prisma/schema.prisma with the prisma-client-js generator (output ./client) and a datasource block without url.
  2. Builds the connection URL and sets RELDENS_DB_URL.
  3. Writes prisma.config.js at the project root.
  4. Runs npx prisma db pull to introspect the database.
  5. Runs npx prisma generate, so the client lands in prisma/client by default.

Prisma 7 no longer accepts url inside the datasource block, the Prisma CLI reads it from the generated prisma.config.js:

try {
    process.loadEnvFile('.env');
} catch(error) {
    process.env.RELDENS_PRISMA_ENV_ERROR = error.message;
}
module.exports = { datasource: { url: process.env.RELDENS_DB_URL } };

Keep prisma.config.js at the project root: every npx prisma command needs it.

Schema generation options:

  • --host, --port, --user, --password, --database - connection data (required).
  • --client - database client: mysql or postgresql (default: mysql).
  • --debug - enable debug mode.
  • --dataProxy - enable the Prisma data proxy.
  • --checkInterval - schema generation check interval in ms (default: 1000).
  • --maxWaitTime - maximum wait time for the generation in ms (default: 30000).
  • --prismaSchemaPath - path to the Prisma schema directory (default: ./prisma).
  • --clientOutputPath - client output path.
  • --generateBinaryTargets - comma separated binary targets (default: native,debian-openssl-1.1.x).
  • --dbParams - database connection parameters, for example authPlugin=mysql_native_password.

For AWS RDS with SSL, pass the connection parameters through RELDENS_DB_PARAMS or --dbParams:

export RELDENS_DB_PARAMS="authPlugin=mysql_native_password&sslmode=require"
npx reldens-storage-prisma --host=your-rds-host.amazonaws.com --port=3306 --user=dbuser --password=dbpass --database=dbname

3. Generate the Entities

npx reldens-storage generateEntities --user=dbuser --pass=dbpass --database=dbname --driver=prisma

Prisma only options of the entities generator:

  • --prismaClientPath - path to the generated Prisma client (default: [path]/prisma/client).
  • --prismaAdapter - driver adapter package resolved from [path]/node_modules, or an absolute path (default: @prisma/adapter-mariadb).
  • --prismaAdapterClass - adapter class exported by that package (default: PrismaMariaDb).

The entities are generated in generated-entities/, with the Prisma models in models/prisma/. Switching drivers requires regenerating all the entities.

4. Pass the Prisma Classes to PrismaDataServer

const { PrismaDataServer } = require('@reldens/storage');
const { PrismaClient, Prisma } = require('./prisma/client');
const { PrismaMariaDb } = require('@prisma/adapter-mariadb');

let server = new PrismaDataServer({
    client: 'mysql',
    config: {
        user: 'reldens',
        password: 'reldens',
        database: 'reldens',
        host: 'localhost',
        port: 3306
    },
    rawEntities: yourEntities,
    prismaModules: {PrismaClient, Prisma, PrismaAdapter: PrismaMariaDb}
});

await server.connect();
let entities = server.generateEntities();

The prismaModules object:

  • PrismaClient - the class exported by the generated client (required unless client is passed).
  • Prisma - the namespace exported by the generated client, used for Prisma.DbNull (required).
  • PrismaAdapter - any Prisma driver adapter class, instantiated with the connection string (required unless adapter or client is passed).
  • adapter - an already instantiated Prisma driver adapter, used as is (optional, replaces PrismaAdapter).
  • client - an already instantiated Prisma client (optional, skips the client construction).

PrismaDataServer.connect() validates the object with PrismaModulesValidator and refuses to start when a required class or method is missing. A passed client must provide $connect, $disconnect, $queryRaw, $queryRawUnsafe, $executeRawUnsafe, $transaction and _runtimeDataModel. Without a client, the data server builds one from PrismaClient and the adapter resolved by PrismaClientLoader.resolveAdapter().

Loading the Client With PrismaClientLoader

PrismaClientLoader, exported by the package, loads the generated client for CLI tools and applications:

const { PrismaClientLoader } = require('@reldens/storage');
const { PrismaMariaDb } = require('@prisma/adapter-mariadb');
const { Logger } = require('@reldens/utils');

// Uses process.env.RELDENS_DB_URL for the connection
let prismaModules = PrismaClientLoader.load(process.cwd(), null, null, {PrismaAdapter: PrismaMariaDb});
if(!prismaModules){
    Logger.error('Failed to load Prisma client');
    process.exit(1);
}

Parameters of PrismaClientLoader.load(projectPath, customPath, connectionData, prismaModules):

  • projectPath - project root directory.
  • customPath - optional custom path to the generated client (null for projectPath/prisma/client).
  • connectionData - optional object with client, user, password, host, port and database; when null the adapter is created with process.env.RELDENS_DB_URL.
  • prismaModules - an object with the PrismaAdapter class or an adapter instance.

It returns the completed prismaModules object (PrismaClient, Prisma, the adapter and the instantiated client), ready to be passed to PrismaDataServer, or null on error.

Selecting Prisma in Reldens

In a Reldens project the driver is selected through environment variables:

  • RELDENS_STORAGE_DRIVER=prisma - the default is knex.
  • RELDENS_PRISMA_ADAPTER - adapter package (default: @prisma/adapter-mariadb).
  • RELDENS_PRISMA_ADAPTER_CLASS - adapter class exported by that package (default: PrismaMariaDb).
  • RELDENS_DB_PARAMS - extra connection parameters, format key1=value1&key2=value2.

Running the Prisma Driver Tests

The Prisma driver tests of the storage package can run without leaving any trace in package.json, package-lock.json or node_modules.

Install, Test, Uninstall Workflow

The local --no-save sequence is the reliable one (PowerShell):

npm install --no-save prisma@7.9.1 @prisma/client@7.9.1 @prisma/adapter-mariadb@7.9.1
$env:RELDENS_TEST_PRISMA_ENABLED = "1"
$env:RELDENS_LOG_LEVEL = "9"
npm run test
npm uninstall --no-save prisma @prisma/client @prisma/adapter-mariadb

Same sequence in Bash / Git Bash:

npm install --no-save prisma@7.9.1 @prisma/client@7.9.1 @prisma/adapter-mariadb@7.9.1
RELDENS_TEST_PRISMA_ENABLED=1 RELDENS_LOG_LEVEL=9 npm run test
npm uninstall --no-save prisma @prisma/client @prisma/adapter-mariadb

A later plain npm install removes the --no-save packages again, because they are not in the lock file. Re-run the install command when that happens.

Global Install

A global install alone does not work, because Node require() and require.resolve() never look into the global node_modules:

  • TestHelpers.isPrismaAvailable() resolves the three packages with require.resolve().
  • tests/utils/test-helpers.js and tests/utils/prisma-subprocess-worker.js require @prisma/adapter-mariadb.
  • The generated client at prisma/client requires @prisma/client-runtime-utils at runtime.

Only npx prisma finds a global CLI. The test helpers compensate: when the local resolution fails, TestHelpers.registerNpmGlobalPaths() runs npm root -g, appends that folder and its nested @prisma/client/node_modules to NODE_PATH, re-initializes the module paths and stores the root in RELDENS_TEST_NPM_GLOBAL_ROOT (inherited by the Prisma subprocess worker). No manual NODE_PATH is needed, but the packages must be under the folder npm root -g prints (PowerShell):

npm install -g prisma@7.9.1 @prisma/client@7.9.1 @prisma/adapter-mariadb@7.9.1
$env:RELDENS_TEST_PRISMA_ENABLED = "1"
$env:RELDENS_LOG_LEVEL = "9"
npm run test
npm uninstall -g prisma @prisma/client @prisma/adapter-mariadb

Only the --no-save sequence has been verified end to end with the Prisma driver passing. The global lookup resolution path is verified, but a full Prisma driver run from a global install is not. If the pre-flight check still says Prisma package not installed, the packages are not under the folder npm root -g prints.

Enabling the Prisma Driver

Two conditions must be true, checked by TestHelpers.isPrismaEnabled():

  1. RELDENS_TEST_PRISMA_ENABLED is exactly 1. It is disabled by default: tests/.env.test.example ships it as 0.
  2. prisma, @prisma/client and @prisma/adapter-mariadb resolve from the repository. The prisma CLI package is resolved through prisma/package.json, because its exports entry "." points to build/types.js, a file that is not shipped in 7.9.1, so require.resolve('prisma') throws even when the package is installed.

What happens in each case:

  • Flag not 1: the pre-flight package check does not list the Prisma packages and the drivers unit test does not include the Prisma driver, so Prisma is not mentioned in the output at all.
  • Either condition fails: the Prisma driver is left out of TestHelpers.activeDriverNames(), so DriverRegistry never sets it up and run-tests.js never runs it.
  • Flag set to 1 but packages missing: the pre-flight check reports the three packages as optional warnings instead of failing.

The flag can also be set in tests/.env.test:

RELDENS_TEST_PRISMA_ENABLED=1

run-tests.js loads tests/.env.test with process.loadEnvFile() only when RELDENS_TEST_DB_HOST is not already set, and loadEnvFile() never overrides variables already present in the environment, so a value set in the shell always wins over the file.

Running the Tests

Bash / Git Bash:

RELDENS_TEST_PRISMA_ENABLED=1 RELDENS_LOG_LEVEL=9 npm run test

Both variables reach node tests/run-tests.js: the Prisma driver is enabled and the Logger prints everything. Without RELDENS_LOG_LEVEL=9 the run prints only the npm header.

PowerShell does not accept the VAR=value command prefix, use:

$env:RELDENS_TEST_PRISMA_ENABLED = "1"
$env:RELDENS_LOG_LEVEL = "9"
npm run test

To run only the Prisma driver, pass the argument through npm run test (the test:driver script ends with an empty --driver=):

RELDENS_TEST_PRISMA_ENABLED=1 RELDENS_LOG_LEVEL=9 npm run test -- --driver=prisma

Expected pre-flight output:

  • Flag set and Prisma installed: Package prisma verified: 7.9.1, Package @prisma/client verified: 7.9.1 and Package @prisma/adapter-mariadb verified: 7.9.1.
  • Flag set and Prisma missing: three Optional package not installed warnings and the Prisma driver absent from the driver registry.
  • Flag unset: no Prisma line at all.

Verified results: 324 tests without the Prisma driver, 406 with it.

What the Prisma Driver Test Setup Does

TestHelpers.setupDriver('prisma'):

  1. Forks tests/utils/prisma-subprocess-worker.js, which writes prisma/schema.prisma and prisma.config.js in the repository root, runs npx prisma db pull and npx prisma generate, and disconnects.
  2. TestHelpers.loadPrismaModules() requires the generated client from prisma/client, requires @prisma/adapter-mariadb, instantiates the client with the adapter and returns {PrismaClient, Prisma, PrismaAdapter, client}. The tests use the MariaDB adapter, the driver accepts any.
  3. Passes that object as prismaModules to PrismaDataServer, whose connect() validates it with PrismaModulesValidator.

TestHelpers.cleanupGeneratedFiles() removes prisma/, prisma.config.js and generated-entities/ at the start and at the end of a run, unless --skip-cleanup is passed.

Related Documentation

Go Up