Skip to content

feat(integrations): add prisma adapter#210

Open
ineshbose wants to merge 3 commits into
unjs:mainfrom
ineshbose:prisma-adapter
Open

feat(integrations): add prisma adapter#210
ineshbose wants to merge 3 commits into
unjs:mainfrom
ineshbose:prisma-adapter

Conversation

@ineshbose

@ineshbose ineshbose commented Feb 5, 2026

Copy link
Copy Markdown

partly resolves #50 (for prisma)

sorry, I had this PR in works for a bit but didn't get time to raise it. the tests work, but maybe the exports in _utils will need usage with more usage and feedback

note: this shall only work based on the driverAdapter pattern in Prisma now

Summary by CodeRabbit

  • New Features

    • Added Prisma integration support for SQLite and PostgreSQL databases.
    • Prisma clients can now perform queries, mutations, and transactions through the database adapter.
    • Added support for converting common SQL values, including dates, numbers, booleans, bigints, and binary data.
  • Documentation

    • Added a complete Prisma setup example showing database initialization and client configuration.
  • Tests

    • Added integration coverage for Prisma operations with SQLite and PostgreSQL.

@ineshbose

Copy link
Copy Markdown
Author

The kysley integration got merged a few weeks ago. Any chance we can focus in on this in a brief and get both integrations for a new minor release?

# Conflicts:
#	package.json
#	pnpm-lock.yaml
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds Prisma driver-adapter support for DB0, including SQL type and argument conversion, transaction handling, SQLite and PostgreSQL integration tests, package configuration, a Prisma schema, and usage documentation.

Changes

Prisma integration

Layer / File(s) Summary
Prisma setup and schema
package.json, pnpm-workspace.yaml, test/integrations/prisma/schema.prisma
Adds Prisma packages and build permissions, plus a generated SQLite Prisma schema with a mapped User model.
SQL type and argument conversion
src/integrations/prisma/_utils.ts
Maps dialect column types to Prisma enums and converts query arguments for numeric, boolean, bigint, datetime, and byte values.
Prisma driver adapter
src/integrations/prisma/index.ts
Adds the prisma(db) factory with query, execution, disposal, connection, provider mapping, and mutex-protected transaction operations.
Integration tests and usage example
test/integrations/prisma/prisma.test.ts, docs/3.integrations/prisma.md
Tests Prisma operations against SQLite and PostgreSQL and documents Prisma client initialization with DB0.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PrismaClient
  participant prisma
  participant Database
  participant Mutex
  PrismaClient->>prisma: startTransaction(isolationLevel)
  prisma->>Mutex: acquire()
  prisma->>Database: execute BEGIN
  Database-->>prisma: transaction started
  prisma-->>PrismaClient: transaction handlers
  PrismaClient->>Database: execute queries
  PrismaClient->>prisma: commit or rollback
  prisma->>Mutex: release()
Loading

Suggested reviewers: igalklebanov

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding a Prisma adapter integration.
Linked Issues check ✅ Passed The PR implements the Prisma integration requested by issue #50 and leaves other tracker items untouched.
Out of Scope Changes check ✅ Passed All changes support the Prisma adapter, docs, tests, and package setup; no unrelated scope is evident.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/3.integrations/prisma.md`:
- Around line 18-26: Update the Prisma example imports and declarations: import
the generated PrismaClient, and alias the db0 adapter factory imported from
“db0/integrations/prisma” so it does not conflict with the exported prisma
client. Use the alias when creating the adapter, preserving the existing
database initialization flow.

In `@package.json`:
- Around line 49-55: Move async-mutex from devDependencies to the runtime
dependencies in package.json so published consumers can load the Prisma
integration successfully. Keep `@prisma/driver-adapter-utils` configured as the
existing optional peer dependency.

In `@src/integrations/prisma/_utils.ts`:
- Around line 210-259: Update getQueryArgs to accept an SQLDialect parameter and
apply the SQLite-specific decimal and boolean coercions only for the SQLite
dialect. Preserve PostgreSQL decimal strings and boolean values in their native
parameter forms, while keeping existing conversions for other argument types
unchanged.
- Around line 20-24: Update the type-mapping switch in the relevant utility so
NUMERIC returns ColumnTypeEnum.Numeric instead of ColumnTypeEnum.Double, while
DOUBLE, DOUBLE PRECISION, and REAL remain mapped to Double. Apply the same
NUMERIC correction in every other dialect branch that currently maps it to
Double.

In `@src/integrations/prisma/index.ts`:
- Around line 84-100: Update the transaction adapter’s commit and rollback
methods to execute and await the corresponding COMMIT or ROLLBACK SQL before
calling release(), and await the initial BEGIN execution before returning the
adapter. Ensure failures during BEGIN or transaction completion release the
mutex so it cannot remain permanently held.
- Around line 43-63: Update queryRaw and executeRaw to reuse the
argument-conversion utility from _utils.ts before binding Prisma scalar values,
and derive each queryRaw columnTypes entry from the actual result metadata
instead of hardcoding Text/7. Preserve the existing columnNames and rows mapping
while returning the real Prisma-compatible metadata and converted arguments.

In `@test/integrations/prisma/prisma.test.ts`:
- Around line 12-16: Add Prisma client generation before the suites in the test
file execute, or replace the conditional skip based on prismaClientGenerated
with an explicit failure when ./dist is missing. Update the setup around
prismaClientGenerated and describe.runIf so CI running pnpm vitest cannot
silently skip both Prisma integration suites.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 047affb3-886f-455b-8b11-3c10750479d9

📥 Commits

Reviewing files that changed from the base of the PR and between d2a0e70 and 542da87.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • docs/3.integrations/prisma.md
  • package.json
  • pnpm-workspace.yaml
  • src/integrations/prisma/_utils.ts
  • src/integrations/prisma/index.ts
  • test/integrations/prisma/prisma.test.ts
  • test/integrations/prisma/schema.prisma

Comment on lines +18 to +26
import { prisma } from "db0/integrations/prisma";
import * as schema from "./schema";

// Initialize DB instance with SQLite connector
const db0 = createDatabase(sqlite({ name: 'database.sqlite' }));

// Create Prisma Client with DB0 adapter
const adapter = prisma(db0);
export const prisma = new PrismaClient({ adapter });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make the documented example compile.

PrismaClient is undeclared, and the adapter factory import conflicts with export const prisma. Alias the factory and import the generated client.

Proposed fix
-import { prisma } from "db0/integrations/prisma";
+import { prisma as createPrismaAdapter } from "db0/integrations/prisma";
+import { PrismaClient } from "./generated/prisma/client";
@@
-const adapter = prisma(db0);
+const adapter = createPrismaAdapter(db0);
 export const prisma = new PrismaClient({ adapter });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { prisma } from "db0/integrations/prisma";
import * as schema from "./schema";
// Initialize DB instance with SQLite connector
const db0 = createDatabase(sqlite({ name: 'database.sqlite' }));
// Create Prisma Client with DB0 adapter
const adapter = prisma(db0);
export const prisma = new PrismaClient({ adapter });
import { prisma as createPrismaAdapter } from "db0/integrations/prisma";
import { PrismaClient } from "./generated/prisma/client";
import * as schema from "./schema";
// Initialize DB instance with SQLite connector
const db0 = createDatabase(sqlite({ name: 'database.sqlite' }));
// Create Prisma Client with DB0 adapter
const adapter = createPrismaAdapter(db0);
export const prisma = new PrismaClient({ adapter });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/3.integrations/prisma.md` around lines 18 - 26, Update the Prisma
example imports and declarations: import the generated PrismaClient, and alias
the db0 adapter factory imported from “db0/integrations/prisma” so it does not
conflict with the exported prisma client. Use the alias when creating the
adapter, preserving the existing database initialization flow.

Comment thread package.json
Comment on lines +49 to +55
"@prisma/client": "^7.2.0",
"@prisma/driver-adapter-utils": "^7.2.0",
"@types/better-sqlite3": "^7.6.13",
"@types/bun": "^1.3.14",
"@types/pg": "^8.20.0",
"@vitest/coverage-v8": "^4.1.10",
"async-mutex": "^0.5.0",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

jq '{dependencies, devDependencies, peerDependencies, peerDependenciesMeta}' package.json
rg -n -C2 'from "`@prisma/driver-adapter-utils`"|from "async-mutex"' src

Repository: unjs/db0

Length of output: 2775


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## package.json (relevant fields)\n'
jq '{name, type, main, module, exports, files, dependencies, devDependencies, peerDependencies, peerDependenciesMeta, scripts}' package.json

printf '\n## build/config files\n'
git ls-files | rg '^(package\.json|obuild\..*|tsup\..*|rollup\..*|vite\.config\..*|bun\.fig|tsconfig.*|src/integrations/prisma/)'

printf '\n## prisma integration source outline\n'
ast-grep outline src/integrations/prisma/index.ts --view expanded
printf '\n'
ast-grep outline src/integrations/prisma/_utils.ts --view expanded

Repository: unjs/db0

Length of output: 457


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## package.json (relevant fields)\n'
python3 - <<'PY'
import json
from pathlib import Path
p = json.loads(Path("package.json").read_text())
keys = ["name","type","main","module","exports","files","dependencies","devDependencies","peerDependencies","peerDependenciesMeta","scripts"]
print(json.dumps({k: p.get(k) for k in keys}, indent=2))
PY

printf '\n## build/config files\n'
git ls-files | rg '^(package\.json|obuild\..*|tsup\..*|rollup\..*|vite\.config\..*|bun\.fig|tsconfig.*|src/integrations/prisma/)'

printf '\n## prisma integration source outline\n'
ast-grep outline src/integrations/prisma/index.ts --view expanded
printf '\n'
ast-grep outline src/integrations/prisma/_utils.ts --view expanded

Repository: unjs/db0

Length of output: 3417


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## files mentioning prisma integration build/publish\n'
rg -n 'integrations/prisma|`@prisma/driver-adapter-utils`|async-mutex|external|bundle|publish|files|exports' package.json src .github -g '!**/node_modules/**'

printf '\n## source file sizes\n'
wc -l src/integrations/prisma/index.ts src/integrations/prisma/_utils.ts

printf '\n## package root file list\n'
git ls-files | sed -n '1,200p'

Repository: unjs/db0

Length of output: 4280


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import json
from pathlib import Path
p = json.loads(Path("package.json").read_text())
for k in ["name","type","main","module","exports","files","scripts","dependencies","devDependencies","peerDependencies","peerDependenciesMeta"]:
    print(f"\n## {k}")
    print(json.dumps(p.get(k), indent=2))
PY

printf '\n## build/config files\n'
git ls-files | rg '^(package\.json|obuild\..*|tsup\..*|rollup\..*|vite\.config\..*|bun\.fig|tsconfig.*|src/integrations/prisma/)'

printf '\n## prisma integration outlines\n'
ast-grep outline src/integrations/prisma/index.ts --view expanded
printf '\n'
ast-grep outline src/integrations/prisma/_utils.ts --view expanded

Repository: unjs/db0

Length of output: 3155


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import json
from pathlib import Path
p = json.loads(Path("package.json").read_text())
for k in ["main","module","exports","files","scripts"]:
    print(f"\n## {k}")
    print(json.dumps(p.get(k), indent=2))
PY

printf '\n## build-related files\n'
git ls-files | rg '(^|/)(obuild|tsup|rollup|vite|bun|tsconfig).*|^package\.json$|^src/integrations/prisma/'

printf '\n## references to runtime deps in prisma integration\n'
rg -n 'from "`@prisma/driver-adapter-utils`"|from "async-mutex"|external|bundle|publish|files' src package.json

Repository: unjs/db0

Length of output: 2046


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import json
from pathlib import Path
p = json.loads(Path("package.json").read_text())
for k in ["main","module","exports","files","scripts","dependencies","devDependencies","peerDependencies","peerDependenciesMeta"]:
    print(f"\n## {k}")
    v = p.get(k)
    if isinstance(v, dict):
        print(json.dumps(v, indent=2))
    else:
        print(v)
PY

printf '\n## package root files\n'
git ls-files | sed -n '1,200p'

Repository: unjs/db0

Length of output: 5866


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## package.json scripts/exports/files\n'
python3 - <<'PY'
import json
from pathlib import Path
p = json.loads(Path("package.json").read_text())
for k in ["scripts","exports","files","main","module","type"]:
    print(f"\n### {k}")
    print(json.dumps(p.get(k), indent=2))
PY

printf '\n## build/config candidates\n'
git ls-files | rg '(^|/)(obuild|tsup|rollup|vite|bun|tsconfig).*|^package\.json$|^src/integrations/prisma/'

Repository: unjs/db0

Length of output: 1479


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import json
from pathlib import Path
p = json.loads(Path("package.json").read_text())
for k in ["scripts","files","exports","main","module","type"]:
    print(f"\n### {k}")
    print(json.dumps(p.get(k), indent=2))
PY

printf '\n## build/config candidates\n'
git ls-files | rg '(^|/)(obuild|tsup|rollup|vite|bun|tsconfig).*|^package\.json$|^src/integrations/prisma/'

Repository: unjs/db0

Length of output: 1440


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## build.config.ts\n'
wc -l build.config.ts
cat -n build.config.ts

printf '\n## tsconfig.json\n'
wc -l tsconfig.json
cat -n tsconfig.json

Repository: unjs/db0

Length of output: 1453


🌐 Web query:

obuild transform entry preserves imports bundle external package manager dependency behavior

💡 Result:

In the obuild build system, the transform entry type is designed for transpilation-only workflows, as opposed to the bundle type which uses a bundler (specifically Rolldown) [1][2]. When using a transform entry, obuild utilizes oxc-transform to process files individually [1][2][3]. Unlike bundling, which resolves and inlines dependencies into a single output file, transform mode typically preserves the original structure and file-to-file import relationships of the source code [1][2]. Because it is a transpilation process rather than a bundling process, it does not rewrite or bundle external package manager dependencies into the output [1][2]. Key characteristics of transform entry behavior include: - Scope: It processes source files and outputs them to a target directory while maintaining their relative file paths and structure [1][2]. - Dependency Handling: It does not perform dependency resolution or bundling, meaning that import statements (e.g., import { x } from 'pkg') are preserved as they exist in the source code rather than being bundled with the external dependency [1][2]. - Configuration: You can further control the behavior of the transformation using plugins such as @obuild/plugin-oxc-transform [3] or use @obuild/plugin-tsc-dts if declaration file generation is required [4]. - Stub Mode: When stub: true is enabled, obuild will symlink the source directory to the destination directory instead of executing the actual build, providing a fast way to work with local sources during development [1][2]. In summary, transform entries in obuild preserve the existing import statements and do not include or modify external package manager dependencies, as they are intended for direct transpilation of individual files rather than bundling [1][2].

Citations:


Ship async-mutex as a runtime dependency. build.config.ts uses transform for src/integrations/, so the Prisma adapter keeps its import at publish time; async-mutex is only in devDependencies, so importing db0/integrations/prisma can fail in consumer installs that don’t happen to provide it. @prisma/driver-adapter-utils can stay as an optional peer for this integration.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` around lines 49 - 55, Move async-mutex from devDependencies to
the runtime dependencies in package.json so published consumers can load the
Prisma integration successfully. Keep `@prisma/driver-adapter-utils` configured as
the existing optional peer dependency.

Comment on lines +20 to +24
case 'DOUBLE':
case 'DOUBLE PRECISION':
case 'NUMERIC':
case 'REAL': {
return ColumnTypeEnum.Double

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the referenced file and nearby context
sed -n '1,340p' src/integrations/prisma/_utils.ts | cat -n

# Find all references to SQLDialect and numeric/decimal handling in the prisma integration
rg -n "SQLDialect|NUMERIC|DECIMAL|Double|Numeric|getQueryArgs|convertDialectColumnToEnum" src/integrations/prisma src -g '!**/dist/**'

Repository: unjs/db0

Length of output: 12050


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the specific file with line numbers, focusing on the relevant functions
nl -ba src/integrations/prisma/_utils.ts | sed -n '1,320p'

Repository: unjs/db0

Length of output: 186


Map NUMERIC to Numeric, not Double.
NUMERIC is exact here, so returning Double can round values; the same NUMERIC handling should be corrected in the other dialect branches too.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/integrations/prisma/_utils.ts` around lines 20 - 24, Update the
type-mapping switch in the relevant utility so NUMERIC returns
ColumnTypeEnum.Numeric instead of ColumnTypeEnum.Double, while DOUBLE, DOUBLE
PRECISION, and REAL remain mapped to Double. Apply the same NUMERIC correction
in every other dialect branch that currently maps it to Double.

Source: Coding guidelines

Comment on lines +210 to +259
export const getQueryArgs = (query: SqlQuery, options?: Record<string, unknown>): Array<bigint | Primitive | Buffer<ArrayBuffer>> => {
return ((query.args || []) as Primitive[]).map((arg: Primitive | Date, i) => {
const argType = query.argTypes[i]
if (arg === null) {
return null
}

if (typeof arg === 'string' && argType.scalarType === 'int') {
return Number.parseInt(arg)
}

if (typeof arg === 'string' && argType.scalarType === 'float') {
return Number.parseFloat(arg)
}

if (typeof arg === 'string' && argType.scalarType === 'decimal') {
// This can lose precision, but SQLite does not have a native decimal type.
// This is how we have historically handled it.
return Number.parseFloat(arg)
}

if (typeof arg === 'string' && argType.scalarType === 'bigint') {
return BigInt(arg)
}

if (typeof arg === 'boolean') {
return arg ? 1 : 0 // SQLite does not natively support booleans
}

if (typeof arg === 'string' && argType.scalarType === 'datetime') {
arg = new Date(arg)
}

if (arg instanceof Date) {
const format = options?.timestampFormat ?? 'iso8601'
switch (format) {
case 'unixepoch-ms': {
return arg.getTime()
}
case 'iso8601': {
return arg.toISOString().replace('Z', '+00:00')
}
default: {
throw new Error(`Unknown timestamp format: ${format}`)
}
}
}

if (typeof arg === 'string' && argType.scalarType === 'bytes') {
return Buffer.from(arg, 'base64')

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Make argument conversion dialect-aware.

This helper applies SQLite-only coercions to every backend: decimal strings are lossy-parsed as JavaScript numbers and booleans become 0/1. Accept SQLDialect and preserve PostgreSQL values in their native parameter forms.

As per coding guidelines, database dialect behavior must adjust per SQLDialect.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/integrations/prisma/_utils.ts` around lines 210 - 259, Update
getQueryArgs to accept an SQLDialect parameter and apply the SQLite-specific
decimal and boolean coercions only for the SQLite dialect. Preserve PostgreSQL
decimal strings and boolean values in their native parameter forms, while
keeping existing conversions for other argument types unchanged.

Source: Coding guidelines

Comment on lines +43 to +63
queryRaw: async function (params: SqlQuery): Promise<SqlResultSet> {
const stmt = db.prepare(params.sql);
const args = (params.args || []) as Primitive[];

return stmt.all(...args).then((result) => {
const columnNames = Object.keys((result as any)[0] || {});
const rows = (result as any[]).map((row) =>
columnNames.map((col) => row[col]),
);
const columnTypes = columnNames.map(() => 7 as const);
return { columnNames, columnTypes, rows };
});
},

executeRaw: async function (params: SqlQuery) {
const stmt = db.prepare(params.sql);
const args = (params.args || []) as Primitive[];

return stmt
.run(...args)
.then((res) => (res as any).changes || 0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

tmp_dir="$(mktemp -d)"
trap 'rm -rf "$tmp_dir"' EXIT

curl -fsSL "$(npm view `@prisma/driver-adapter-utils`@7.2.0 dist.tarball)" |
  tar -xz -C "$tmp_dir"

rg -n -C2 'Text:\s*7|ColumnTypeEnum' "$tmp_dir/package"

Repository: unjs/db0

Length of output: 4745


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## files\n'
git ls-files 'src/integrations/prisma/*' 'src/**/_utils.ts' 'src/**/*.ts' | sed -n '1,120p'

printf '\n## outline index.ts\n'
ast-grep outline src/integrations/prisma/index.ts --view expanded || true

printf '\n## outline helpers\n'
for f in $(git ls-files 'src/integrations/prisma/*_utils.ts' 'src/integrations/prisma/*.ts'); do
  [ -f "$f" ] || continue
  echo "--- $f"
  ast-grep outline "$f" --view expanded || true
done

printf '\n## search for Prisma adapter helpers/usages\n'
rg -n -C 2 'queryRaw|executeRaw|ColumnTypeEnum|convert|primitive|SqlQuery|SqlResultSet|prepare\(' src/integrations/prisma src -g '*.ts'

Repository: unjs/db0

Length of output: 30896


🏁 Script executed:

#!/bin/bash
set -euo pipefail

git ls-files 'src/integrations/prisma/*' 'src/**/_utils.ts' 'src/**/*.ts' | sed -n '1,120p'

echo '--- index.ts outline ---'
ast-grep outline src/integrations/prisma/index.ts --view expanded || true

echo '--- prisma helper outlines ---'
for f in $(git ls-files 'src/integrations/prisma/*_utils.ts' 'src/integrations/prisma/*.ts'); do
  [ -f "$f" ] || continue
  echo "--- $f"
  ast-grep outline "$f" --view expanded || true
done

echo '--- searches ---'
rg -n -C 2 'queryRaw|executeRaw|ColumnTypeEnum|convert|Primitive|SqlQuery|SqlResultSet|prepare\(' src/integrations/prisma src -g '*.ts'

Repository: unjs/db0

Length of output: 50364


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- src/integrations/prisma/index.ts ---'
cat -n src/integrations/prisma/index.ts

echo '--- src/integrations/prisma/_utils.ts ---'
cat -n src/integrations/prisma/_utils.ts

Repository: unjs/db0

Length of output: 12173


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- search for column metadata helpers ---\n'
rg -n -C 2 '\.columns\(|columns\(\)|column.*type|decltype|type.*column|pragma table_info|sqlite_master' src -g '*.ts'

printf '\n--- statement wrappers outline ---\n'
ast-grep outline src/connectors/_internal/statement.ts --view expanded || true

Repository: unjs/db0

Length of output: 237


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- db0 statement/result types in repo ---\n'
rg -n -C 2 'type SqlResultSet|interface SqlResultSet|ColumnTypeEnum|SqlQuery|argTypes|columnNames|columnTypes' src node_modules -g '*.ts' -g '*.d.ts' -g '*.mts' 2>/dev/null | sed -n '1,220p'

Repository: unjs/db0

Length of output: 237


🏁 Script executed:

#!/bin/bash
set -euo pipefail

tmp_dir="$(mktemp -d)"
trap 'rm -rf "$tmp_dir"' EXIT

curl -fsSL "$(npm view `@prisma/driver-adapter-utils`@7.2.0 dist.tarball)" |
  tar -xz -C "$tmp_dir"

echo '--- SqlResultSet type ---'
rg -n -C 3 'interface SqlResultSet|type SqlResultSet|columnTypes|columnNames' "$tmp_dir/package/dist" -g '*.d.ts' -g '*.mts' -g '*.ts'

echo '--- runtime columnTypes handling ---'
rg -n -C 3 'columnTypes' "$tmp_dir/package/dist" -g '*.js' -g '*.mjs' | sed -n '1,220p'

Repository: unjs/db0

Length of output: 3823


Return real Prisma metadata and converted arguments here.
src/integrations/prisma/index.ts:43-63 hardcodes every result column as ColumnTypeEnum.Text, and it bypasses src/integrations/prisma/_utils.ts when binding params. That will mis-handle non-text result types and Prisma scalar inputs like dates, booleans, bigints, and bytes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/integrations/prisma/index.ts` around lines 43 - 63, Update queryRaw and
executeRaw to reuse the argument-conversion utility from _utils.ts before
binding Prisma scalar values, and derive each queryRaw columnTypes entry from
the actual result metadata instead of hardcoding Text/7. Preserve the existing
columnNames and rows mapping while returning the real Prisma-compatible metadata
and converted arguments.

Source: Coding guidelines

Comment on lines +84 to +100
const release = await mutex.acquire();
const options = { usePhantomQuery: false };

db.exec("BEGIN");

return {
...adapter,
options,

commit: async function () {
release();
return;
},
rollback: async function () {
release();
return;
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🔴 Critical | ⚡ Quick win

Execute COMMIT and ROLLBACK before releasing the lock.

BEGIN is not awaited, and neither transaction completion method sends SQL. Prisma can report a committed or rolled-back transaction while the database session remains inside it; a failed BEGIN also permanently retains the mutex.

Proposed fix
           const release = await mutex.acquire();
           const options = { usePhantomQuery: false };

-          db.exec("BEGIN");
+          try {
+            await db.exec("BEGIN");
+          } catch (error) {
+            release();
+            throw error;
+          }

           return {
             ...adapter,
             options,

             commit: async function () {
-              release();
-              return;
+              try {
+                await db.exec("COMMIT");
+              } finally {
+                release();
+              }
             },
             rollback: async function () {
-              release();
-              return;
+              try {
+                await db.exec("ROLLBACK");
+              } finally {
+                release();
+              }
             },
           };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const release = await mutex.acquire();
const options = { usePhantomQuery: false };
db.exec("BEGIN");
return {
...adapter,
options,
commit: async function () {
release();
return;
},
rollback: async function () {
release();
return;
},
const release = await mutex.acquire();
const options = { usePhantomQuery: false };
try {
await db.exec("BEGIN");
} catch (error) {
release();
throw error;
}
return {
...adapter,
options,
commit: async function () {
try {
await db.exec("COMMIT");
} finally {
release();
}
},
rollback: async function () {
try {
await db.exec("ROLLBACK");
} finally {
release();
}
},
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/integrations/prisma/index.ts` around lines 84 - 100, Update the
transaction adapter’s commit and rollback methods to execute and await the
corresponding COMMIT or ROLLBACK SQL before calling release(), and await the
initial BEGIN execution before returning the adapter. Ensure failures during
BEGIN or transaction completion release the mutex so it cannot remain
permanently held.

Comment on lines +12 to +16
const outputDir = resolve(import.meta.dirname, "./dist");

const prismaClientGenerated = existsSync(outputDir);

describe.runIf(prismaClientGenerated)(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

jq '.scripts' package.json
rg -n -g 'package.json' -g '*.yml' -g '*.yaml' -g '*.json' \
  'prisma generate|prisma\.test|vitest' .

Repository: unjs/db0

Length of output: 4190


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the Prisma integration test and CI/workflow files first.
git ls-files 'test/integrations/prisma/prisma.test.ts' '.github/**/*' 'package.json' 'pnpm-workspace.yaml' | sed 's#^`#FILE` #'

printf '\n--- prisma test outline ---\n'
ast-grep outline test/integrations/prisma/prisma.test.ts --view expanded

printf '\n--- prisma test file ---\n'
cat -n test/integrations/prisma/prisma.test.ts

printf '\n--- workflow/test references ---\n'
rg -n -S 'pnpm test|vitest run|prisma generate|gen-connectors|dist' .github package.json test

Repository: unjs/db0

Length of output: 5319


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check whether the Prisma test file skips suites when dist is absent,
# and whether any setup script creates that directory beforehand.
python3 - <<'PY'
from pathlib import Path
p = Path('test/integrations/prisma/prisma.test.ts')
print(p.read_text())
PY

Repository: unjs/db0

Length of output: 2851


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -S 'outputDir|prismaClientGenerated|existsSync\(outputDir\)|resolve\(import\.meta\.dirname, "\./dist"\)|prisma generate|gen-connectors' test src scripts .github package.json

Repository: unjs/db0

Length of output: 843


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- ci workflow ---'
cat -n .github/workflows/ci.yml

printf '\n%s\n' '--- prisma dist tracked by git ---'
git ls-files 'test/integrations/prisma/dist/**' 'test/integrations/prisma/dist'

Repository: unjs/db0

Length of output: 769


Add Prisma generation before Vitesttest/integrations/prisma/prisma.test.ts:12-16 skips both suites when ./dist is missing, and the CI workflow runs pnpm build/pnpm vitest without a Prisma generate step. Add the generation step or make the missing client fail loudly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/integrations/prisma/prisma.test.ts` around lines 12 - 16, Add Prisma
client generation before the suites in the test file execute, or replace the
conditional skip based on prismaClientGenerated with an explicit failure when
./dist is missing. Update the setup around prismaClientGenerated and
describe.runIf so CI running pnpm vitest cannot silently skip both Prisma
integration suites.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Integration support tracker

2 participants