Skip to content

Commit 37824e5

Browse files
committed
fix(rivetkit): remove drizzle-orm peer dep and add runtime version check
1 parent 89bbdd8 commit 37824e5

File tree

4 files changed

+135
-8
lines changed

4 files changed

+135
-8
lines changed

rivetkit-typescript/CLAUDE.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,18 @@ DEBUG perf user: dbMigrateMs durationMs=...
4242

4343
The log name matches the key in `ActorMetrics.startup`. Internal phases use `perf internal:`, user-code callbacks use `perf user:`. This convention keeps startup logs greppable and makes it easy to separate framework overhead from user-code time. When adding a new startup phase, always add a corresponding log with the appropriate prefix and update the `#userStartupKeys` set in `ActorInstance` if the phase runs user code.
4444

45+
## Drizzle Compatibility Testing
46+
47+
To test rivetkit's drizzle integration against multiple drizzle-orm versions:
48+
49+
```bash
50+
cd rivetkit-typescript/packages/rivetkit
51+
./scripts/test-drizzle-compat.sh # test all default versions
52+
./scripts/test-drizzle-compat.sh 0.44.2 0.45.1 # test specific versions
53+
```
54+
55+
The script installs each drizzle-orm version, runs the drizzle driver tests, and reports pass/fail per version. It restores the original package.json and lockfile on exit. Update the `DEFAULT_VERSIONS` array in the script and `SUPPORTED_DRIZZLE_RANGE` in `packages/rivetkit/src/db/drizzle/mod.ts` when adding support for new drizzle releases.
56+
4557
## Workflow Context Actor Access Guards
4658

4759
In `ActorWorkflowContext` (`packages/rivetkit/src/workflow/context.ts`), all side-effectful `#runCtx` access must be guarded by `#ensureActorAccess` so that side effects only run inside workflow steps and are not replayed outside of them. Read-only properties (e.g., `actorId`, `log`) do not need guards. When adding new methods or properties to the workflow context that delegate to `#runCtx`, apply the guard if the operation has side effects.

rivetkit-typescript/packages/rivetkit/package.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,6 @@
366366
"@e2b/code-interpreter": "^2.3.3",
367367
"dockerode": "^4.0.9",
368368
"drizzle-kit": "^0.31.2",
369-
"drizzle-orm": "^0.44.2",
370369
"eventsource": "^4.0.0",
371370
"ws": "^8.0.0"
372371
},
@@ -383,9 +382,6 @@
383382
"drizzle-kit": {
384383
"optional": true
385384
},
386-
"drizzle-orm": {
387-
"optional": true
388-
},
389385
"eventsource": {
390386
"optional": true
391387
},
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Tests rivetkit's drizzle integration against multiple drizzle-orm versions.
4+
#
5+
# Usage:
6+
# ./scripts/test-drizzle-compat.sh # test all versions
7+
# ./scripts/test-drizzle-compat.sh 0.44.2 0.45.1 # test specific versions
8+
#
9+
# Run from rivetkit-typescript/packages/rivetkit/.
10+
11+
set -euo pipefail
12+
13+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
14+
PKG_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
15+
ROOT_DIR="$(cd "$PKG_DIR/../../.." && pwd)"
16+
17+
# Default versions to test. Uses the latest patch of each minor release.
18+
# Add new minor versions here as drizzle releases them.
19+
DEFAULT_VERSIONS=("0.44" "0.45")
20+
21+
if [[ $# -gt 0 ]]; then
22+
VERSIONS=("$@")
23+
else
24+
VERSIONS=("${DEFAULT_VERSIONS[@]}")
25+
fi
26+
27+
cd "$ROOT_DIR"
28+
29+
# Back up files that pnpm add will modify.
30+
cp "$PKG_DIR/package.json" "$PKG_DIR/package.json.drizzle-compat-bak"
31+
cp "$ROOT_DIR/pnpm-lock.yaml" "$ROOT_DIR/pnpm-lock.yaml.drizzle-compat-bak"
32+
33+
cleanup() {
34+
echo ""
35+
echo "Restoring original package.json and lockfile..."
36+
mv "$PKG_DIR/package.json.drizzle-compat-bak" "$PKG_DIR/package.json"
37+
mv "$ROOT_DIR/pnpm-lock.yaml.drizzle-compat-bak" "$ROOT_DIR/pnpm-lock.yaml"
38+
cd "$ROOT_DIR" && pnpm install --frozen-lockfile 2>/dev/null || pnpm install
39+
}
40+
trap cleanup EXIT
41+
42+
declare -A RESULTS
43+
44+
for version in "${VERSIONS[@]}"; do
45+
echo ""
46+
echo "=========================================="
47+
echo " Testing drizzle-orm@$version"
48+
echo "=========================================="
49+
50+
# Install the target version into the rivetkit package.
51+
pnpm --filter rivetkit add -D "drizzle-orm@$version" 2>&1 | tail -3
52+
53+
# Run only the drizzle variant of the DB tests.
54+
TEST_LOG="/tmp/drizzle-compat-${version}.log"
55+
if cd "$PKG_DIR" && pnpm test driver-file-system -t "Actor Database \(drizzle\)" > "$TEST_LOG" 2>&1; then
56+
RESULTS["$version"]="PASS"
57+
echo " -> PASS"
58+
else
59+
RESULTS["$version"]="FAIL"
60+
echo " -> FAIL (see $TEST_LOG)"
61+
fi
62+
cd "$ROOT_DIR"
63+
done
64+
65+
echo ""
66+
echo "=========================================="
67+
echo " Drizzle Compatibility Results"
68+
echo "=========================================="
69+
for version in "${VERSIONS[@]}"; do
70+
printf " drizzle-orm@%-10s %s\n" "$version" "${RESULTS[$version]}"
71+
done

rivetkit-typescript/packages/rivetkit/src/db/drizzle/mod.ts

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { createRequire } from "node:module";
12
import type { IDatabase } from "@rivetkit/sqlite-vfs";
23
import {
34
drizzle as proxyDrizzle,
@@ -10,6 +11,54 @@ export * from "./sqlite-core";
1011

1112
import { type Config, defineConfig as originalDefineConfig } from "drizzle-kit";
1213

14+
/**
15+
* Supported drizzle-orm version bounds. Update these when testing confirms
16+
* compatibility with new releases. Run scripts/test-drizzle-compat.sh to
17+
* validate.
18+
*/
19+
const DRIZZLE_MIN = [0, 44, 0];
20+
const DRIZZLE_MAX = [0, 46, 0]; // exclusive
21+
22+
let drizzleVersionChecked = false;
23+
24+
function compareVersions(a: number[], b: number[]): number {
25+
for (let i = 0; i < Math.max(a.length, b.length); i++) {
26+
const diff = (a[i] ?? 0) - (b[i] ?? 0);
27+
if (diff !== 0) return diff;
28+
}
29+
return 0;
30+
}
31+
32+
function isSupported(version: string): boolean {
33+
// Strip prerelease suffix (e.g. "0.45.1-a7a15d0" -> "0.45.1")
34+
const v = version.replace(/-.*$/, "").split(".").map(Number);
35+
return (
36+
compareVersions(v, DRIZZLE_MIN) >= 0 &&
37+
compareVersions(v, DRIZZLE_MAX) < 0
38+
);
39+
}
40+
41+
function checkDrizzleVersion() {
42+
if (drizzleVersionChecked) return;
43+
drizzleVersionChecked = true;
44+
45+
try {
46+
const require = createRequire(import.meta.url);
47+
const { version } = require("drizzle-orm/package.json") as {
48+
version: string;
49+
};
50+
if (!isSupported(version)) {
51+
console.warn(
52+
`[rivetkit] drizzle-orm@${version} has not been tested with this version of rivetkit. ` +
53+
`Supported: >= ${DRIZZLE_MIN.join(".")} and < ${DRIZZLE_MAX.join(".")}. ` +
54+
`Things may still work, but please report issues at https://github.com/rivet-dev/rivet/issues`,
55+
);
56+
}
57+
} catch {
58+
// Cannot determine version, skip check.
59+
}
60+
}
61+
1362
export function defineConfig(
1463
config: Partial<Config & { driver: "durable-sqlite" }>,
1564
): Config {
@@ -141,6 +190,8 @@ export function db<
141190
>(
142191
config?: DatabaseFactoryConfig<TSchema>,
143192
): DatabaseProvider<SqliteRemoteDatabase<TSchema> & RawAccess> {
193+
checkDrizzleVersion();
194+
144195
// Map from drizzle client to the underlying @rivetkit/sqlite Database.
145196
// Uses WeakMap so entries are garbage-collected when the client is.
146197
// This replaces the previous shared `waDbInstance` variable which caused
@@ -271,10 +322,7 @@ export function db<
271322
clientToKvStore.get(client as object)?.clearPreload();
272323
const waDb = clientToRawDb.get(client as object);
273324
if (config?.migrations && waDb) {
274-
await runInlineMigrations(
275-
waDb,
276-
config.migrations,
277-
);
325+
await runInlineMigrations(waDb, config.migrations);
278326
}
279327
},
280328
onDestroy: async (client) => {

0 commit comments

Comments
 (0)