feat(integrations): add prisma adapter#210
Conversation
|
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
📝 WalkthroughWalkthroughAdds 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. ChangesPrisma integration
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()
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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
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. Comment |
There was a problem hiding this comment.
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
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (7)
docs/3.integrations/prisma.mdpackage.jsonpnpm-workspace.yamlsrc/integrations/prisma/_utils.tssrc/integrations/prisma/index.tstest/integrations/prisma/prisma.test.tstest/integrations/prisma/schema.prisma
| 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 }); |
There was a problem hiding this comment.
🎯 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.
| 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.
| "@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", |
There was a problem hiding this comment.
🩺 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"' srcRepository: 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 expandedRepository: 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 expandedRepository: 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 expandedRepository: 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.jsonRepository: 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.jsonRepository: 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:
- 1: https://github.com/unjs/obuild
- 2: https://registry.npmjs.org/obuild
- 3: https://registry.npmjs.org/%40obuild%2Fplugin-oxc-transform
- 4: https://registry.npmjs.org/%40obuild%2Fplugin-tsc-dts
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.
| case 'DOUBLE': | ||
| case 'DOUBLE PRECISION': | ||
| case 'NUMERIC': | ||
| case 'REAL': { | ||
| return ColumnTypeEnum.Double |
There was a problem hiding this comment.
🗄️ 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
| 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') |
There was a problem hiding this comment.
🗄️ 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
| 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); |
There was a problem hiding this comment.
🗄️ 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.tsRepository: 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 || trueRepository: 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
| 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; | ||
| }, |
There was a problem hiding this comment.
🗄️ 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.
| 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.
| const outputDir = resolve(import.meta.dirname, "./dist"); | ||
|
|
||
| const prismaClientGenerated = existsSync(outputDir); | ||
|
|
||
| describe.runIf(prismaClientGenerated)( |
There was a problem hiding this comment.
📐 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 testRepository: 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())
PYRepository: 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.jsonRepository: 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 Vitest — test/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.
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
_utilswill need usage with more usage and feedbacknote: this shall only work based on the driverAdapter pattern in Prisma now
Summary by CodeRabbit
New Features
Documentation
Tests