diff --git a/.gitignore b/.gitignore
index bfb1e5e86..1aefe2118 100644
--- a/.gitignore
+++ b/.gitignore
@@ -184,3 +184,5 @@ Cargo.lock
**/.wrangler
**/.DS_Store
.aider*
+
+packages/**/tsup.config.bundled_*.mjs
\ No newline at end of file
diff --git a/examples/drizzle/drizzle/0000_wonderful_iron_patriot.sql b/examples/drizzle/drizzle/0000_moaning_tomorrow_man.sql
similarity index 100%
rename from examples/drizzle/drizzle/0000_wonderful_iron_patriot.sql
rename to examples/drizzle/drizzle/0000_moaning_tomorrow_man.sql
diff --git a/examples/drizzle/drizzle/meta/0000_snapshot.json b/examples/drizzle/drizzle/meta/0000_snapshot.json
index c6434f1d6..c1a874381 100644
--- a/examples/drizzle/drizzle/meta/0000_snapshot.json
+++ b/examples/drizzle/drizzle/meta/0000_snapshot.json
@@ -1,7 +1,7 @@
{
"version": "6",
"dialect": "sqlite",
- "id": "22f3d49c-97d5-46ca-b0f1-99950c3efec7",
+ "id": "5175c351-75eb-4f1d-9211-7ee520f0b9c2",
"prevId": "00000000-0000-0000-0000-000000000000",
"tables": {
"users_table": {
diff --git a/examples/drizzle/drizzle/meta/_journal.json b/examples/drizzle/drizzle/meta/_journal.json
index 5e0783723..31667078b 100644
--- a/examples/drizzle/drizzle/meta/_journal.json
+++ b/examples/drizzle/drizzle/meta/_journal.json
@@ -5,15 +5,8 @@
{
"idx": 0,
"version": "6",
- "when": 1750711614205,
- "tag": "0000_wonderful_iron_patriot",
- "breakpoints": true
- },
- {
- "idx": 1,
- "version": "6",
- "when": 1750716663518,
- "tag": "0001_rich_susan_delgado",
+ "when": 1750976447195,
+ "tag": "0000_moaning_tomorrow_man",
"breakpoints": true
}
]
diff --git a/examples/drizzle/drizzle/migrations.js b/examples/drizzle/drizzle/migrations.js
index 33f0f927c..a7ebc8ab1 100644
--- a/examples/drizzle/drizzle/migrations.js
+++ b/examples/drizzle/drizzle/migrations.js
@@ -1,10 +1,10 @@
import journal from './meta/_journal.json';
-import m0000 from './0000_wonderful_iron_patriot.sql';
+import m0000 from './0000_moaning_tomorrow_man.sql';
export default {
journal,
migrations: {
- m0000,
+ m0000
}
}
\ No newline at end of file
diff --git a/examples/drizzle/hooks.js b/examples/drizzle/hooks.js
deleted file mode 100644
index cc7bce84f..000000000
--- a/examples/drizzle/hooks.js
+++ /dev/null
@@ -1,10 +0,0 @@
-export async function load(url, context, nextLoad) {
- if(url.endsWith('.sql')) {
- return {
- shortCircuit: true,
- format: 'module',
- source: `export default 'SQL file loaded from ${url}';`
- }
- }
- return nextLoad(url, context)
-}
\ No newline at end of file
diff --git a/examples/drizzle/package.json b/examples/drizzle/package.json
index f2b525c14..f110ac9b6 100644
--- a/examples/drizzle/package.json
+++ b/examples/drizzle/package.json
@@ -4,17 +4,19 @@
"private": true,
"type": "module",
"scripts": {
- "dev": "tsx --watch src/server.ts",
+ "dev": "tsx --loader @rivetkit/sql-loader --watch src/server.ts",
"check-types": "tsc --noEmit"
},
"devDependencies": {
+ "@rivetkit/actor": "workspace:*",
+ "@rivetkit/sql-loader": "workspace:*",
"@types/node": "^22.13.9",
- "rivetkit": "workspace:*",
"tsx": "^3.12.7",
"typescript": "^5.5.2"
},
"dependencies": {
"@rivetkit/db": "workspace:0.9.0-rc.1",
+ "better-sqlite3": "^12.1.1",
"drizzle-kit": "^0.31.2",
"drizzle-orm": "^0.44.2"
},
diff --git a/examples/drizzle/register.js b/examples/drizzle/register.js
deleted file mode 100644
index 31ef20696..000000000
--- a/examples/drizzle/register.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import {register} from "node:module";
-import { pathToFileURL } from 'node:url';
-
-
-register("./hooks.js", pathToFileURL(__filename))
-
-
-// registerHooks({
-// resolve(specifier, context, nextResolve) {
-// console.log({specifier, context});
-// },
-// load(url, context, nextLoad) {
-// console.log({url, context});
-// },
-// });
\ No newline at end of file
diff --git a/examples/drizzle/scripts/connect.ts b/examples/drizzle/scripts/connect.ts
new file mode 100644
index 000000000..3462c1994
--- /dev/null
+++ b/examples/drizzle/scripts/connect.ts
@@ -0,0 +1,30 @@
+///
+import { createClient } from "@rivetkit/actor/client";
+import type { Registry } from "../src/registry";
+
+async function main() {
+ const client = createClient(
+ process.env.ENDPOINT ?? "http://127.0.0.1:8080",
+ );
+
+ const contacts = client.contacts.getOrCreate();
+
+ // counter.on("newCount", (count: number) => console.log("Event:", count));
+
+ for (let i = 0; i < 5; i++) {
+ const out = await contacts.insert({
+ name: `User ${i}`,
+ age: 20 + i,
+ email: `example+${i}@example.com`,
+ });
+ console.log("Inserted:", out);
+ }
+
+ console.log("Reading all users:");
+ const users = await contacts.read();
+ console.log(users);
+
+ // await counter.dispose();
+}
+
+main();
diff --git a/examples/drizzle/src/db/schema.ts b/examples/drizzle/src/db/schema.ts
index f24058ac8..eb07503d6 100644
--- a/examples/drizzle/src/db/schema.ts
+++ b/examples/drizzle/src/db/schema.ts
@@ -1,9 +1,8 @@
-// import { int, sqliteTable, text } from "@rivetkit/db/drizzle";
+import { int, sqliteTable, text } from "@rivetkit/db/drizzle";
-// export const usersTable = sqliteTable("users_table", {
-// id: int().primaryKey({ autoIncrement: true }),
-// name: text().notNull(),
-// age: int().notNull(),
-// email: text().notNull().unique(),
-// email2: text().notNull().unique(),
-// });
+export const usersTable = sqliteTable("users_table", {
+ id: int().primaryKey({ autoIncrement: true }),
+ name: text().notNull(),
+ age: int().notNull(),
+ email: text().notNull().unique(),
+});
diff --git a/examples/drizzle/src/registry.ts b/examples/drizzle/src/registry.ts
index 98a14f9cc..2d598a3eb 100644
--- a/examples/drizzle/src/registry.ts
+++ b/examples/drizzle/src/registry.ts
@@ -1,27 +1,34 @@
-// import { actor, setup } from "rivetkit";
-// import { db } from "@rivetkit/db/drizzle";
-// import * as schema from "./db/schema";
-// import migrations from "../drizzle/migrations";
+import { actor, setup } from "@rivetkit/actor";
+import { db } from "@rivetkit/db/drizzle";
+import * as schema from "./db/schema";
+import migrations from "../drizzle/migrations";
-// export const counter = actor({
-// db: db({ schema, migrations }),
-// state: {
-// count: 0,
-// },
-// onAuth: () => {
-// // Configure auth here
-// },
-// actions: {
-// increment: (c, x: number) => {
-// // createState or state fix fix fix
-// c.db.c.state.count += x;
-// return c.state.count;
-// },
-// },
-// });
+export const contacts = actor({
+ db: db({ schema, migrations }),
+ onAuth: async (c) => {},
+ actions: {
+ insert: async (c, record: { name: string; age: number; email: string }) => {
+ // Example of using the DB
+ const result = await c.db.insert(schema.usersTable).values(record);
+ return result;
+ },
+ read: async (c) => {
+ // Example of reading from the DB
+ const users = await c.db.query.usersTable.findMany();
+ return users;
+ },
+ search: async (c, query: string) => {
+ // Example of searching in the DB
+ const users = await c.db.query.usersTable.findMany({
+ where: (table, { ilike }) => ilike(table.name, `%${query}%`),
+ });
+ return users;
+ },
+ },
+});
-// export const registry = setup({
-// use: { counter },
-// });
+export const registry = setup({
+ use: { contacts },
+});
-// export type Registry = typeof registry;
+export type Registry = typeof registry;
diff --git a/examples/drizzle/src/server.ts b/examples/drizzle/src/server.ts
index 5be165d64..fee7051e9 100644
--- a/examples/drizzle/src/server.ts
+++ b/examples/drizzle/src/server.ts
@@ -1,7 +1,3 @@
-// import { registry } from "./registry";
-// import { createMemoryDriver } from "@rivetkit/memory";
-// import { serve } from "@rivetkit/nodejs";
+import { registry } from "./registry";
-// serve(registry, {
-// driver: createMemoryDriver(),
-// });
+await registry.runServer();
diff --git a/packages/core/package.json b/packages/core/package.json
index 68c882412..d6ae35834 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -135,6 +135,16 @@
"types": "./dist/test/mod.d.cts",
"default": "./dist/test/mod.cjs"
}
+ },
+ "./db": {
+ "import": {
+ "types": "./dist/db/mod.d.ts",
+ "default": "./dist/db/mod.js"
+ },
+ "require": {
+ "types": "./dist/db/mod.d.cts",
+ "default": "./dist/bd/mod.cjs"
+ }
}
},
"engines": {
@@ -143,7 +153,7 @@
"sideEffects": false,
"scripts": {
"dev": "pnpm build --watch",
- "build": "tsup src/mod.ts src/client/mod.ts src/common/log.ts src/common/websocket.ts src/actor/errors.ts src/topologies/coordinate/mod.ts src/topologies/partition/mod.ts src/utils.ts src/drivers/rivet/mod.ts src/driver-helpers/mod.ts src/driver-test-suite/mod.ts src/test/mod.ts",
+ "build": "tsup src/mod.ts src/client/mod.ts src/common/log.ts src/common/websocket.ts src/actor/errors.ts src/topologies/coordinate/mod.ts src/topologies/partition/mod.ts src/utils.ts src/drivers/rivet/mod.ts src/driver-helpers/mod.ts src/driver-test-suite/mod.ts src/test/mod.ts src/db/mod.ts",
"check-types": "tsc --noEmit",
"boop": "tsc --outDir dist/test -d",
"test": "vitest run",
diff --git a/packages/core/src/actor/action.ts b/packages/core/src/actor/action.ts
index 6c6f86f64..1ccd16e1a 100644
--- a/packages/core/src/actor/action.ts
+++ b/packages/core/src/actor/action.ts
@@ -5,15 +5,16 @@ import type { ConnId } from "./connection";
import type { ActorContext } from "./context";
import type { SaveStateOptions } from "./instance";
import type { Schedule } from "./schedule";
-import { Registry } from "@/registry/mod";
-import { Client } from "@/client/client";
+import type { Registry } from "@/registry/mod";
+import type { Client } from "@/client/client";
+import type { AnyDatabaseClient, DatabaseProviderOf } from "@/db/mod";
/**
* Context for a remote procedure call.
*
* @typeParam A Actor this action belongs to
*/
-export class ActionContext {
+export class ActionContext {
#actorContext: ActorContext;
/**
@@ -24,7 +25,7 @@ export class ActionContext {
*/
constructor(
actorContext: ActorContext,
- public readonly conn: Conn,
+ public readonly conn: Conn>,
) {
this.#actorContext = actorContext;
}
@@ -95,7 +96,7 @@ export class ActionContext {
/**
* Gets the map of connections.
*/
- get conns(): Map> {
+ get conns(): Map>> {
return this.#actorContext.conns;
}
diff --git a/packages/core/src/actor/config.ts b/packages/core/src/actor/config.ts
index 17d42b5df..9fb01d329 100644
--- a/packages/core/src/actor/config.ts
+++ b/packages/core/src/actor/config.ts
@@ -2,6 +2,12 @@ import { z } from "zod";
import type { ActionContext } from "./action";
import type { Conn } from "./connection";
import type { ActorContext } from "./context";
+import type {
+ AnyDatabaseClient,
+ AnyDatabaseProvider,
+ DatabaseClientOf,
+ DatabaseProviderOf,
+} from "@/db/mod";
// This schema is used to validate the input at runtime. The generic types are defined below in `ActorConfig`.
//
@@ -32,6 +38,7 @@ export const ActorConfigSchema = z
.object({
createVarsTimeout: z.number().positive().default(5000),
createConnStateTimeout: z.number().positive().default(5000),
+ migrationTimeout: z.number().positive().default(10000),
onConnectTimeout: z.number().positive().default(5000),
})
.strict()
@@ -110,7 +117,7 @@ type CreateState =
undefined,
undefined,
undefined,
- undefined
+ AnyDatabaseClient
>,
opts: CreateStateOptions,
) => S | Promise;
@@ -133,7 +140,7 @@ type CreateConnState =
undefined,
undefined,
undefined,
- undefined
+ AnyDatabaseClient
>,
opts: OnConnectOptions,
) => CS | Promise;
@@ -165,14 +172,14 @@ type CreateVars =
undefined,
undefined,
undefined,
- undefined
+ AnyDatabaseClient
>,
driverCtx: unknown,
) => V | Promise;
}
| Record;
-export interface Actions {
+export interface Actions {
[Action: string]: (
c: ActionContext,
...args: any[]
@@ -205,8 +212,8 @@ interface BaseActorConfig<
V,
I,
AD,
- DB,
- R extends Actions,
+ DB extends AnyDatabaseProvider,
+ R extends Actions>,
> {
/**
* Called on the HTTP server before clients can interact with the actor.
@@ -242,7 +249,7 @@ interface BaseActorConfig<
* This is called before any other lifecycle hooks.
*/
onCreate?: (
- c: ActorContext,
+ c: ActorContext>,
opts: OnCreateOptions,
) => void | Promise;
@@ -254,7 +261,9 @@ interface BaseActorConfig<
*
* @returns Void or a Promise that resolves when startup is complete
*/
- onStart?: (c: ActorContext) => void | Promise;
+ onStart?: (
+ c: ActorContext>,
+ ) => void | Promise;
/**
* Called when the actor's state changes.
@@ -265,7 +274,7 @@ interface BaseActorConfig<
* @param newState The updated state
*/
onStateChange?: (
- c: ActorContext,
+ c: ActorContext>,
newState: S,
) => void;
@@ -290,7 +299,7 @@ interface BaseActorConfig<
* @throws Throw an error to reject the connection
*/
onBeforeConnect?: (
- c: ActorContext,
+ c: ActorContext>,
opts: OnConnectOptions,
) => void | Promise;
@@ -304,7 +313,7 @@ interface BaseActorConfig<
* @returns Void or a Promise that resolves when connection handling is complete
*/
onConnect?: (
- c: ActorContext,
+ c: ActorContext>,
conn: Conn,
) => void | Promise;
@@ -318,7 +327,7 @@ interface BaseActorConfig<
* @returns Void or a Promise that resolves when disconnect handling is complete
*/
onDisconnect?: (
- c: ActorContext,
+ c: ActorContext>,
conn: Conn,
) => void | Promise;
@@ -335,7 +344,7 @@ interface BaseActorConfig<
* @returns The modified output to send to the client
*/
onBeforeActionResponse?: (
- c: ActorContext,
+ c: ActorContext>,
name: string,
args: unknown[],
output: Out,
@@ -344,32 +353,27 @@ interface BaseActorConfig<
actions: R;
}
-export type DatabaseFactory = (ctx: {
- createDatabase: () => Promise;
-}) => Promise<{
- /**
- * @experimental
- */
- db?: DB;
- /**
- * @experimental
- */
- onMigrate?: () => void | Promise;
-}>;
-
-type ActorDatabaseConfig =
+type ActorDatabase =
| {
/**
* @experimental
*/
- db: DatabaseFactory;
+ db: DB;
}
| Record;
// 1. Infer schema
// 2. Omit keys that we'll manually define (because of generics)
// 3. Define our own types that have generic constraints
-export type ActorConfig = Omit<
+export type ActorConfig<
+ S,
+ CP,
+ CS,
+ V,
+ I,
+ AD,
+ DB extends AnyDatabaseProvider,
+> = Omit<
z.infer,
| "actions"
| "onAuth"
@@ -388,11 +392,20 @@ export type ActorConfig = Omit<
| "createVars"
| "db"
> &
- BaseActorConfig> &
- CreateState &
- CreateConnState &
- CreateVars &
- ActorDatabaseConfig;
+ BaseActorConfig<
+ S,
+ CP,
+ CS,
+ V,
+ I,
+ AD,
+ DB,
+ Actions>
+ > &
+ CreateState> &
+ CreateConnState> &
+ CreateVars> &
+ ActorDatabase>;
// See description on `ActorConfig`
export type ActorConfigInput<
@@ -402,8 +415,8 @@ export type ActorConfigInput<
V,
I,
AD,
- DB,
- R extends Actions,
+ DB extends AnyDatabaseProvider,
+ R extends Actions>,
> = Omit<
z.input,
| "actions"
@@ -427,7 +440,7 @@ export type ActorConfigInput<
CreateState &
CreateConnState &
CreateVars &
- ActorDatabaseConfig;
+ ActorDatabase;
// For testing type definitions:
export function test<
@@ -437,8 +450,8 @@ export function test<
V,
I,
AD,
- DB,
- R extends Actions,
+ DB extends AnyDatabaseProvider,
+ R extends Actions>,
>(
input: ActorConfigInput,
): ActorConfig {
diff --git a/packages/core/src/actor/connection.ts b/packages/core/src/actor/connection.ts
index d4dde5695..f5f54fa9d 100644
--- a/packages/core/src/actor/connection.ts
+++ b/packages/core/src/actor/connection.ts
@@ -6,6 +6,7 @@ import type { ActorInstance } from "./instance";
import type { PersistedConn } from "./persisted";
import { CachedSerializer } from "./protocol/serde";
import { generateSecureToken } from "./utils";
+import type { AnyDatabaseProvider } from "@/db/mod";
export function generateConnId(): string {
return crypto.randomUUID();
@@ -26,7 +27,7 @@ export type AnyConn = Conn;
*
* @see {@link https://rivet.gg/docs/connections|Connection Documentation}
*/
-export class Conn {
+export class Conn {
subscriptions: Set = new Set();
#stateEnabled: boolean;
@@ -52,8 +53,8 @@ export class Conn {
return this.__persist.p;
}
- public get auth(): unknown {
- return this.__persist.a;
+ public get auth(): AD {
+ return this.__persist.a as AD;
}
public get _stateEnabled() {
diff --git a/packages/core/src/actor/context.ts b/packages/core/src/actor/context.ts
index 1e1a51670..76a265789 100644
--- a/packages/core/src/actor/context.ts
+++ b/packages/core/src/actor/context.ts
@@ -3,16 +3,19 @@ import type { Logger } from "@/common/log";
import type { Conn, ConnId } from "./connection";
import type { ActorInstance, SaveStateOptions } from "./instance";
import type { Schedule } from "./schedule";
-import { Client } from "@/client/client";
-import { Registry } from "@/registry/mod";
+import type { Client } from "@/client/client";
+import type { Registry } from "@/registry/mod";
+import type { AnyDatabaseClient, DatabaseProviderOf } from "@/db/mod";
/**
* ActorContext class that provides access to actor methods and state
*/
-export class ActorContext {
- #actor: ActorInstance;
+export class ActorContext {
+ #actor: ActorInstance>;
- constructor(actor: ActorInstance) {
+ constructor(
+ actor: ActorInstance>,
+ ) {
this.#actor = actor;
}
@@ -85,7 +88,7 @@ export class ActorContext {
/**
* Gets the map of connections.
*/
- get conns(): Map> {
+ get conns(): Map>> {
return this.#actor.conns;
}
diff --git a/packages/core/src/actor/definition.ts b/packages/core/src/actor/definition.ts
index c4426772f..9d1925b18 100644
--- a/packages/core/src/actor/definition.ts
+++ b/packages/core/src/actor/definition.ts
@@ -1,3 +1,4 @@
+import type { AnyDatabaseProvider, DatabaseClientOf } from "@/db/mod";
import type { ActionContext } from "./action";
import type { Actions, ActorConfig } from "./config";
import type { ActorContext } from "./context";
@@ -28,7 +29,7 @@ export type ActorContextOf =
infer DB,
any
>
- ? ActorContext
+ ? ActorContext>
: never;
/**
@@ -45,7 +46,7 @@ export type ActionContextOf =
infer DB,
any
>
- ? ActionContext
+ ? ActionContext>
: never;
export class ActorDefinition<
@@ -55,8 +56,8 @@ export class ActorDefinition<
V,
I,
AD,
- DB,
- R extends Actions,
+ DB extends AnyDatabaseProvider,
+ R extends Actions>,
> {
#config: ActorConfig;
diff --git a/packages/core/src/actor/driver.ts b/packages/core/src/actor/driver.ts
index 364cd1592..198b7a41b 100644
--- a/packages/core/src/actor/driver.ts
+++ b/packages/core/src/actor/driver.ts
@@ -2,6 +2,7 @@ import type * as messageToClient from "@/actor/protocol/message/to-client";
import type { CachedSerializer } from "@/actor/protocol/serde";
import type { AnyConn } from "./connection";
import type { AnyActorInstance } from "./instance";
+import type { ActorDatabaseConnectionDetails } from "@/db/mod";
export type ConnDrivers = Record;
@@ -22,7 +23,7 @@ export interface ActorDriver {
* @experimental
* This is an experimental API that may change in the future.
*/
- getDatabase(actorId: string): Promise;
+ getDatabase?(actorId: string): Promise;
// TODO:
//destroy(): Promise;
diff --git a/packages/core/src/actor/instance.ts b/packages/core/src/actor/instance.ts
index a0f4190de..123e07ede 100644
--- a/packages/core/src/actor/instance.ts
+++ b/packages/core/src/actor/instance.ts
@@ -24,6 +24,11 @@ import { processMessage } from "./protocol/message/mod";
import { CachedSerializer } from "./protocol/serde";
import { Schedule } from "./schedule";
import { DeadlineError, Lock, deadline } from "./utils";
+import type {
+ AnyDatabaseClient,
+ AnyDatabaseProvider,
+ DatabaseClientOf,
+} from "@/db/mod";
/**
* Options for the `_saveState` method.
@@ -110,9 +115,17 @@ export type ExtractActorConnState =
? ConnState
: never;
-export class ActorInstance {
+export class ActorInstance<
+ S,
+ CP,
+ CS,
+ V,
+ I,
+ AD,
+ DB extends AnyDatabaseProvider,
+> {
// Shared actor context for this instance
- actorContext: ActorContext;
+ actorContext: ActorContext>;
isStopping = false;
#persistChanged = false;
@@ -151,7 +164,7 @@ export class ActorInstance {
#schedule!: Schedule;
// inspector!: ActorInspector;
- #db!: DB;
+ #db!: DatabaseClientOf;
get id() {
return this.#actorId;
@@ -209,7 +222,7 @@ export class ActorInstance {
undefined,
undefined,
undefined,
- undefined
+ AnyDatabaseClient
>,
this.#actorDriver.getContext(this.#actorId),
);
@@ -240,13 +253,16 @@ export class ActorInstance {
// Setup Database
if ("db" in this.#config) {
- const db = await this.#config.db({
- createDatabase: () => actorDriver.getDatabase(this.#actorId),
- });
+ const getDatabase = this.#actorDriver.getDatabase;
+ invariant(getDatabase, "Chosen actor driver does not support databases");
+ const actorDatabase = await this.#config.db.setup({
+ setupDatabase: () => getDatabase(this.#actorId),
+ });
logger().info("database migration starting");
- await db.onMigrate?.();
+ await actorDatabase.onMigrate();
logger().info("database migration complete");
+ this.#db = actorDatabase.client as DatabaseClientOf;
}
// Set alarm for next scheduled event if any exist after finishing initiation sequence
@@ -565,7 +581,7 @@ export class ActorInstance {
undefined,
undefined,
undefined,
- undefined
+ AnyDatabaseClient
>,
{ input },
);
@@ -679,7 +695,7 @@ export class ActorInstance {
undefined,
undefined,
undefined,
- undefined
+ AnyDatabaseClient
>,
onBeforeConnectOpts,
);
@@ -901,11 +917,11 @@ export class ActorInstance {
* @internal
*/
async executeAction(
- ctx: ActionContext,
+ ctx: ActionContext>,
actionName: string,
args: unknown[],
): Promise {
- invariant(this.#ready, "exucuting action before ready");
+ invariant(this.#ready, "executing action before ready");
// Prevent calling private or reserved methods
if (!(actionName in this.#config.actions)) {
@@ -1063,7 +1079,7 @@ export class ActorInstance {
* @experimental
* @throws {DatabaseNotEnabled} If the database is not enabled.
*/
- get db(): DB {
+ get db(): DatabaseClientOf {
if (!this.#db) {
throw new errors.DatabaseNotEnabled();
}
diff --git a/packages/core/src/actor/mod.ts b/packages/core/src/actor/mod.ts
index e4d7f30c4..000a4bdde 100644
--- a/packages/core/src/actor/mod.ts
+++ b/packages/core/src/actor/mod.ts
@@ -1,3 +1,4 @@
+import type { AnyDatabaseProvider, DatabaseClientOf } from "@/db/mod";
import {
type Actions,
type ActorConfig,
@@ -26,8 +27,8 @@ export function actor<
V,
I,
AD,
- DB,
- R extends Actions,
+ DB extends AnyDatabaseProvider,
+ R extends Actions>,
>(
input: ActorConfigInput,
): ActorDefinition {
diff --git a/packages/core/src/actor/protocol/message/mod.ts b/packages/core/src/actor/protocol/message/mod.ts
index 3cfcb35c1..d1c0a3620 100644
--- a/packages/core/src/actor/protocol/message/mod.ts
+++ b/packages/core/src/actor/protocol/message/mod.ts
@@ -14,6 +14,11 @@ import * as errors from "../../errors";
import type { ActorInstance } from "../../instance";
import { logger } from "../../log";
import { assertUnreachable } from "../../utils";
+import type {
+ AnyDatabaseClient,
+ AnyDatabaseProvider,
+ DatabaseClientOf,
+} from "@/db/mod";
export const TransportSchema = z.enum(["websocket", "sse"]);
@@ -67,9 +72,17 @@ export async function parseMessage(
return message;
}
-export interface ProcessMessageHandler {
+export interface ProcessMessageHandler<
+ S,
+ CP,
+ CS,
+ V,
+ I,
+ AD,
+ DB extends AnyDatabaseProvider,
+> {
onExecuteAction?: (
- ctx: ActionContext,
+ ctx: ActionContext>,
name: string,
args: unknown[],
) => Promise;
@@ -83,7 +96,15 @@ export interface ProcessMessageHandler {
) => Promise;
}
-export async function processMessage(
+export async function processMessage<
+ S,
+ CP,
+ CS,
+ V,
+ I,
+ AD,
+ DB extends AnyDatabaseProvider,
+>(
message: wsToServer.ToServer,
actor: ActorInstance,
conn: Conn,
@@ -111,7 +132,7 @@ export async function processMessage(
argsCount: args.length,
});
- const ctx = new ActionContext(
+ const ctx = new ActionContext>(
actor.actorContext,
conn,
);
diff --git a/packages/core/src/db/mod.ts b/packages/core/src/db/mod.ts
new file mode 100644
index 000000000..0fb263ac5
--- /dev/null
+++ b/packages/core/src/db/mod.ts
@@ -0,0 +1,27 @@
+export interface DatabaseSetupResult {
+ client: DB;
+ onMigrate: () => Promise;
+}
+
+export type ActorDatabaseConnectionDetails =
+ | { url: string }
+ | { exec: (...args: any[]) => void }
+ | unknown;
+export interface DatabaseSetupContext {
+ /**
+ * Sets up the database for the actor.
+ * @returns A promise that resolves to the database URL, database instance
+ */
+ setupDatabase: () => Promise;
+}
+
+export type DatabaseSetupFunction = (
+ ctx: DatabaseSetupContext,
+) => Promise>;
+
+export type AnyDatabaseProvider = DatabaseProviderOf;
+export type DatabaseProviderOf = { setup: DatabaseSetupFunction };
+export type DatabaseClientOf = DB extends DatabaseProviderOf
+ ? C
+ : never;
+export type AnyDatabaseClient = DatabaseClientOf;
diff --git a/packages/core/src/drivers/memory/actor.ts b/packages/core/src/drivers/memory/actor.ts
index 5f4032f00..6fa10711a 100644
--- a/packages/core/src/drivers/memory/actor.ts
+++ b/packages/core/src/drivers/memory/actor.ts
@@ -1,5 +1,6 @@
import type { ActorDriver, AnyActorInstance } from "@/driver-helpers/mod";
import type { MemoryGlobalState } from "./global-state";
+import type { ActorDatabaseConnectionDetails } from "@/db/mod";
export type ActorDriverContext = Record;
@@ -33,7 +34,7 @@ export class MemoryActorDriver implements ActorDriver {
}, delay);
}
- getDatabase(actorId: string): Promise {
- return Promise.resolve(undefined);
+ async getDatabase(actorId: string): Promise {
+ return { url: ":memory:" };
}
}
diff --git a/packages/core/src/utils.ts b/packages/core/src/utils.ts
index 7db7488ac..12a180d9a 100644
--- a/packages/core/src/utils.ts
+++ b/packages/core/src/utils.ts
@@ -39,7 +39,6 @@ export type UpgradeWebSocket = (
*/
export function createDefaultDriver(): DriverConfig {
const driver = getEnvUniversal("RIVETKIT_DRIVER");
- console.log("driver", driver);
if (!driver || driver === "memory") {
logger().info("using default memory driver");
return createMemoryDriver();
diff --git a/packages/core/tests/actor-types.test.ts b/packages/core/tests/actor-types.test.ts
index b7a8be8f8..defb0fc71 100644
--- a/packages/core/tests/actor-types.test.ts
+++ b/packages/core/tests/actor-types.test.ts
@@ -1,5 +1,6 @@
import type { ActorContext } from "@/actor/context";
import type { ActorContextOf, ActorDefinition } from "@/actor/definition";
+import { DatabaseSetupFunction } from "@/db/mod";
import { describe, expectTypeOf, it } from "vitest";
describe("ActorDefinition", () => {
@@ -30,10 +31,10 @@ describe("ActorDefinition", () => {
baz: string;
}
- interface TestDatabase {
- onMigrate: () => void;
- client: object;
- }
+ type TestDatabase = DatabaseSetupFunction<{
+ client: any; // Replace with actual database client type if needed
+ onMigrate: () => Promise | void;
+ }>;
// For testing type utilities, we don't need a real actor instance
// We just need a properly typed ActorDefinition to check against
diff --git a/packages/db/package.json b/packages/db/package.json
index 0077d44e0..e9d58c19f 100644
--- a/packages/db/package.json
+++ b/packages/db/package.json
@@ -37,7 +37,8 @@
"peerDependencies": {
"drizzle-kit": "^0.31.2",
"drizzle-orm": "^0.44.2",
- "rivetkit": "*"
+ "better-sqlite3": "^11.10.0",
+ "@rivetkit/core": "*"
},
"peerDependenciesMeta": {
"drizzle-orm": {
@@ -45,19 +46,19 @@
},
"drizzle-kit": {
"optional": true
+ },
+ "better-sqlite3": {
+ "optional": true
}
},
"devDependencies": {
"@types/better-sqlite3": "^7.6.13",
"@types/node": "^24.0.4",
"drizzle-orm": "^0.44.2",
- "rivetkit": "workspace:*",
+ "@rivetkit/core": "workspace:*",
"tsup": "^8.3.6",
"typescript": "^5.5.2",
"vitest": "^3.1.1"
},
- "stableVersion": "0.8.0",
- "dependencies": {
- "better-sqlite3": "^11.10.0"
- }
+ "stableVersion": "0.8.0"
}
diff --git a/packages/db/src/config.ts b/packages/db/src/config.ts
deleted file mode 100644
index 988e82142..000000000
--- a/packages/db/src/config.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-export interface DatabaseConfig {
- client: DB;
- onMigrate: () => void;
-}
-
-export interface DatabaseFactoryContext {
- createDatabase: () => Promise;
-}
-
-export type DatabaseFactory = (
- ctx: DatabaseFactoryContext,
-) => Promise>;
diff --git a/packages/db/src/drizzle/mod.ts b/packages/db/src/drizzle/mod.ts
index d7fe198d3..772886095 100644
--- a/packages/db/src/drizzle/mod.ts
+++ b/packages/db/src/drizzle/mod.ts
@@ -2,13 +2,14 @@ import {
type BetterSQLite3Database,
drizzle as sqliteDrizzle,
} from "drizzle-orm/better-sqlite3";
+import type {
+ DatabaseProviderOf,
+ DatabaseSetupFunction,
+} from "@rivetkit/core/db";
-import { migrate as sqliteMigrate } from "drizzle-orm/durable-sqlite/migrator";
import { drizzle as durableDrizzle } from "drizzle-orm/durable-sqlite";
import { migrate as durableMigrate } from "drizzle-orm/durable-sqlite/migrator";
-import * as Database from "better-sqlite3";
-import type { DatabaseFactory } from "@/config";
-
+import Database from "better-sqlite3";
export * from "drizzle-orm/sqlite-core";
import { defineConfig as originalDefineConfig, type Config } from "drizzle-kit";
@@ -16,8 +17,7 @@ import { defineConfig as originalDefineConfig, type Config } from "drizzle-kit";
export function defineConfig(
config: Partial,
): Config {
- // This is a workaround to avoid the "drizzle-kit" import issue in the examples.
- // It allows us to use the same defineConfig function in both the main package and the examples.
+ // Pre-configures the defineConfig function to use the durable-sqlite driver, for convenience.
return originalDefineConfig({
dialect: "sqlite",
driver: "durable-sqlite",
@@ -32,45 +32,62 @@ interface DatabaseFactoryConfig<
* The database schema.
*/
schema?: TSchema;
- migrations?: any;
+ migrations?: Parameters[1];
}
export function db<
TSchema extends Record = Record,
>(
config?: DatabaseFactoryConfig,
-): DatabaseFactory> {
- return async (ctx) => {
- const conn = await ctx.createDatabase();
+): { setup: DatabaseSetupFunction> } {
+ return {
+ setup: async (ctx) => {
+ const conn = await ctx.setupDatabase();
+
+ if (!conn) {
+ throw new Error(
+ "Cannot create database connection, or database feature is not enabled.",
+ );
+ }
+
+ if (
+ typeof conn === "object" &&
+ conn &&
+ "url" in conn &&
+ typeof conn.url === "string"
+ ) {
+ const client = sqliteDrizzle({
+ client: new Database(conn.url),
+ ...config,
+ });
- if (!conn) {
- throw new Error(
- "Cannot create database connection, or database feature is not enabled.",
- );
- }
+ return {
+ client,
+ onMigrate: async () => {
+ if (config?.migrations) {
+ await durableMigrate(client, config.migrations);
+ }
+ },
+ };
+ }
+
+ if (typeof conn !== "object" || !("exec" in conn)) {
+ throw new Error(
+ "Invalid database connection. Expected an object with an 'exec' method.",
+ );
+ }
- if (typeof conn === "object" && conn && "exec" in conn) {
// If the connection is already an object with exec method, return it
// i.e. in serverless environments (Cloudflare Workers)
const client = durableDrizzle(conn, config);
return {
client,
onMigrate: async () => {
- await durableMigrate(client, config?.migrations);
+ if (config?.migrations) {
+ await durableMigrate(client, config.migrations);
+ }
},
};
- }
-
- const client = sqliteDrizzle({
- client: new Database(conn as string),
- ...config,
- });
-
- return {
- client,
- onMigrate: async () => {
- await sqliteMigrate(client, config?.migrations);
- },
- };
- };
+ },
+ } satisfies DatabaseProviderOf>;
}
diff --git a/packages/db/src/mod.ts b/packages/db/src/mod.ts
index 47e0172d5..1e23c9b5a 100644
--- a/packages/db/src/mod.ts
+++ b/packages/db/src/mod.ts
@@ -1,5 +1,8 @@
+import type {
+ DatabaseProviderOf,
+ DatabaseSetupFunction,
+} from "@rivetkit/core/db";
import * as SQLite from "better-sqlite3";
-import type { DatabaseFactory } from "./config";
/**
* On serverless environments, we use a shim, as not all methods are available.
@@ -12,35 +15,49 @@ interface DatabaseFactoryConfig {
onMigrate?: (db: SQLiteShim) => void;
}
-export function db({
- onMigrate,
-}: DatabaseFactoryConfig = {}): DatabaseFactory {
- return async (ctx) => {
- const conn = await ctx.createDatabase();
+export function db({ onMigrate }: DatabaseFactoryConfig = {}): {
+ setup: DatabaseSetupFunction;
+} {
+ // @ts-ignore
+ return {
+ setup: async (ctx) => {
+ const conn = await ctx.setupDatabase();
- if (!conn) {
- throw new Error(
- "Cannot create database connection, or database feature is not enabled.",
- );
- }
+ if (!conn) {
+ throw new Error(
+ "Cannot create database connection, or database feature is not enabled.",
+ );
+ }
+
+ if (
+ typeof conn === "object" &&
+ conn &&
+ "url" in conn &&
+ typeof conn.url === "string"
+ ) {
+ // if the connection is already an object with exec method, return it
+ // i.e. in serverless environments (cloudflare)
+ const client = new SQLite(conn.url);
+ return {
+ client,
+ onMigrate: () => {
+ return onMigrate?.(client) || Promise.resolve();
+ },
+ };
+ }
+
+ if (typeof conn !== "object" || !("exec" in conn)) {
+ throw new Error(
+ "Invalid database connection. Expected an object with an 'exec' method.",
+ );
+ }
- if (typeof conn === "object" && conn && "exec" in conn) {
- // if the connection is already an object with exec method, return it
- // i.e. in serverless environments (cloudflare)
return {
client: conn as SQLiteShim,
onMigrate: () => {
- onMigrate?.(client);
+ return onMigrate?.(conn as SQLiteShim) || Promise.resolve();
},
};
- }
-
- const client = new SQLite(conn as string);
- return {
- client,
- onMigrate: () => {
- onMigrate?.(client);
- },
- };
- };
+ },
+ } satisfies DatabaseProviderOf;
}
diff --git a/packages/misc/sql-loader/package.json b/packages/misc/sql-loader/package.json
new file mode 100644
index 000000000..824e3ea14
--- /dev/null
+++ b/packages/misc/sql-loader/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "@rivetkit/sql-loader",
+ "version": "0.0.1",
+ "license": "MIT",
+ "main": "./dist/register.js",
+ "type": "commonjs",
+ "files": [
+ "dist/**/*.js"
+ ],
+ "scripts": {
+ "build": "tsc -p tsconfig.json",
+ "dev": "tsc -p tsconfig.json --watch",
+ "test": "echo \"No tests specified\" && exit 0"
+ },
+ "devDependencies": {
+ "@types/node": "^20.4.3",
+ "typescript": "^5.8.3"
+ }
+}
\ No newline at end of file
diff --git a/packages/misc/sql-loader/src/hook.ts b/packages/misc/sql-loader/src/hook.ts
new file mode 100644
index 000000000..93b6f9a92
--- /dev/null
+++ b/packages/misc/sql-loader/src/hook.ts
@@ -0,0 +1,14 @@
+import type { LoadHook } from "node:module";
+import { readFile } from "node:fs/promises";
+import { fileURLToPath } from "node:url";
+
+export const load: LoadHook = async (url, context, nextLoad) => {
+ if (url.endsWith(".sql")) {
+ return {
+ shortCircuit: true,
+ format: "module",
+ source: `export default \`${(await readFile(fileURLToPath(url), "utf8")).replace(/`/gm, "\\`")}\`;`,
+ };
+ }
+ return nextLoad(url, context);
+};
diff --git a/packages/misc/sql-loader/src/register.ts b/packages/misc/sql-loader/src/register.ts
new file mode 100644
index 000000000..89385d2e5
--- /dev/null
+++ b/packages/misc/sql-loader/src/register.ts
@@ -0,0 +1,4 @@
+import { register } from "node:module";
+import { pathToFileURL } from "node:url";
+
+register("./hook.js", pathToFileURL(__filename));
diff --git a/packages/misc/sql-loader/tsconfig.json b/packages/misc/sql-loader/tsconfig.json
new file mode 100644
index 000000000..ed77ac4cc
--- /dev/null
+++ b/packages/misc/sql-loader/tsconfig.json
@@ -0,0 +1,16 @@
+{
+ "paths": ["src/**"],
+ "compilerOptions": {
+ "target": "es2017" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
+ "module": "commonjs" /* Specify what module code is generated. */,
+ "sourceMap": true /* Create source map files for emitted JavaScript files. */,
+ "outDir": "./dist" /* Specify an output folder for all emitted files. */,
+ "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */,
+ "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
+ "strict": true /* Enable all strict type-checking options. */,
+ "skipLibCheck": true /* Skip type checking all .d.ts files. */,
+ "types": [
+ "node"
+ ] /* Specify type package names to be included without being referenced in a source file. */
+ }
+}
diff --git a/packages/misc/sql-loader/turbo.json b/packages/misc/sql-loader/turbo.json
new file mode 100644
index 000000000..95960709b
--- /dev/null
+++ b/packages/misc/sql-loader/turbo.json
@@ -0,0 +1,4 @@
+{
+ "$schema": "https://turbo.build/schema.json",
+ "extends": ["//"]
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8e760b11f..8af02503d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -173,19 +173,25 @@ importers:
'@rivetkit/db':
specifier: workspace:0.9.0-rc.1
version: link:../../packages/db
+ better-sqlite3:
+ specifier: ^12.1.1
+ version: 12.1.1
drizzle-kit:
specifier: ^0.31.2
version: 0.31.2
drizzle-orm:
specifier: ^0.44.2
- version: 0.44.2(@cloudflare/workers-types@4.20250619.0)(@types/better-sqlite3@7.6.13)(better-sqlite3@11.10.0)(kysely@0.28.2)
+ version: 0.44.2(@cloudflare/workers-types@4.20250619.0)(@types/better-sqlite3@7.6.13)(better-sqlite3@12.1.1)(kysely@0.28.2)
devDependencies:
+ '@rivetkit/actor':
+ specifier: workspace:*
+ version: link:../../packages/actor
+ '@rivetkit/sql-loader':
+ specifier: workspace:*
+ version: link:../../packages/misc/sql-loader
'@types/node':
specifier: ^22.13.9
version: 22.15.32
- rivetkit:
- specifier: workspace:*
- version: link:../../packages/rivetkit
tsx:
specifier: ^3.12.7
version: 3.14.0
@@ -496,6 +502,9 @@ importers:
specifier: ^0.31.2
version: 0.31.2
devDependencies:
+ '@rivetkit/core':
+ specifier: workspace:*
+ version: link:../core
'@types/better-sqlite3':
specifier: ^7.6.13
version: 7.6.13
@@ -505,9 +514,6 @@ importers:
drizzle-orm:
specifier: ^0.44.2
version: 0.44.2(@cloudflare/workers-types@4.20250619.0)(@types/better-sqlite3@7.6.13)(better-sqlite3@11.10.0)(kysely@0.28.2)
- rivetkit:
- specifier: workspace:*
- version: link:../rivetkit
tsup:
specifier: ^8.3.6
version: 8.5.0(@microsoft/api-extractor@7.52.8(@types/node@24.0.4))(postcss@8.5.6)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.0)
@@ -658,6 +664,15 @@ importers:
specifier: ^3.101.0
version: 3.114.9(@cloudflare/workers-types@4.20250619.0)
+ packages/misc/sql-loader:
+ devDependencies:
+ '@types/node':
+ specifier: ^20.4.3
+ version: 20.19.1
+ typescript:
+ specifier: ^5.8.3
+ version: 5.8.3
+
packages/platforms/cloudflare-workers:
dependencies:
hono:
@@ -2023,6 +2038,9 @@ packages:
'@types/node@18.19.112':
resolution: {integrity: sha512-i+Vukt9POdS/MBI7YrrkkI5fMfwFtOjphSmt4WXYLfwqsfr6z/HdCx7LqT9M7JktGob8WNgj8nFB4TbGNE4Cog==}
+ '@types/node@20.19.1':
+ resolution: {integrity: sha512-jJD50LtlD2dodAEO653i3YF04NWak6jN3ky+Ri3Em3mGR39/glWiboM/IePaRbgwSfqM1TpGXfAg8ohn/4dTgA==}
+
'@types/node@22.15.32':
resolution: {integrity: sha512-3jigKqgSjsH6gYZv2nEsqdXfZqIFGAV36XYYjf9KGZ3PSG+IhLecqPnI310RvjutyMwifE2hhhNEklOUrvx/wA==}
@@ -2127,9 +2145,15 @@ packages:
'@volar/language-core@2.4.14':
resolution: {integrity: sha512-X6beusV0DvuVseaOEy7GoagS4rYHgDHnTrdOj5jeUb49fW5ceQyP9Ej5rBhqgz2wJggl+2fDbbojq1XKaxDi6w==}
+ '@volar/language-core@2.4.15':
+ resolution: {integrity: sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==}
+
'@volar/source-map@2.4.14':
resolution: {integrity: sha512-5TeKKMh7Sfxo8021cJfmBzcjfY1SsXsPMMjMvjY7ivesdnybqqS+GxGAoXHAOUawQTwtdUxgP65Im+dEmvWtYQ==}
+ '@volar/source-map@2.4.15':
+ resolution: {integrity: sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==}
+
'@volar/typescript@2.4.14':
resolution: {integrity: sha512-p8Z6f/bZM3/HyCdRNFZOEEzts51uV8WHeN8Tnfnm2EBv6FDB2TQLzfVx7aJvnl8ofKAOnS64B2O8bImBFaauRw==}
@@ -2244,6 +2268,10 @@ packages:
better-sqlite3@11.10.0:
resolution: {integrity: sha512-EwhOpyXiOEL/lKzHz9AW1msWFNzGc/z+LzeB3/jnFJpxu+th2yqvzsSWas1v9jgs9+xiXJcD5A8CJxAG2TaghQ==}
+ better-sqlite3@12.1.1:
+ resolution: {integrity: sha512-xjl/TjWLy/6yLa5wkbQSjTgIgSiaEJy3XzjF5TAdiWaAsu/v0OCkYOc6tos+PkM/k4qURN2pFKTsbcG3gk29Uw==}
+ engines: {node: 20.x || 22.x || 23.x || 24.x}
+
bindings@1.5.0:
resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==}
@@ -5331,6 +5359,10 @@ snapshots:
dependencies:
undici-types: 5.26.5
+ '@types/node@20.19.1':
+ dependencies:
+ undici-types: 6.21.0
+
'@types/node@22.15.32':
dependencies:
undici-types: 6.21.0
@@ -5412,14 +5444,6 @@ snapshots:
chai: 5.2.0
tinyrainbow: 2.0.0
- '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@22.15.32)(tsx@3.14.0)(yaml@2.8.0))':
- dependencies:
- '@vitest/spy': 3.2.4
- estree-walker: 3.0.3
- magic-string: 0.30.17
- optionalDependencies:
- vite: 6.3.5(@types/node@22.15.32)(tsx@3.14.0)(yaml@2.8.0)
-
'@vitest/mocker@3.2.4(vite@6.3.5(@types/node@24.0.4)(tsx@4.20.3)(yaml@2.8.0))':
dependencies:
'@vitest/spy': 3.2.4
@@ -5479,8 +5503,14 @@ snapshots:
dependencies:
'@volar/source-map': 2.4.14
+ '@volar/language-core@2.4.15':
+ dependencies:
+ '@volar/source-map': 2.4.15
+
'@volar/source-map@2.4.14': {}
+ '@volar/source-map@2.4.15': {}
+
'@volar/typescript@2.4.14':
dependencies:
'@volar/language-core': 2.4.14
@@ -5507,7 +5537,7 @@ snapshots:
'@vue/language-core@2.2.0(typescript@5.8.3)':
dependencies:
- '@volar/language-core': 2.4.14
+ '@volar/language-core': 2.4.15
'@vue/compiler-dom': 3.5.17
'@vue/compiler-vue2': 2.7.16
'@vue/shared': 3.5.17
@@ -5614,6 +5644,11 @@ snapshots:
bindings: 1.5.0
prebuild-install: 7.1.3
+ better-sqlite3@12.1.1:
+ dependencies:
+ bindings: 1.5.0
+ prebuild-install: 7.1.3
+
bindings@1.5.0:
dependencies:
file-uri-to-path: 1.0.0
@@ -5863,6 +5898,13 @@ snapshots:
better-sqlite3: 11.10.0
kysely: 0.28.2
+ drizzle-orm@0.44.2(@cloudflare/workers-types@4.20250619.0)(@types/better-sqlite3@7.6.13)(better-sqlite3@12.1.1)(kysely@0.28.2):
+ optionalDependencies:
+ '@cloudflare/workers-types': 4.20250619.0
+ '@types/better-sqlite3': 7.6.13
+ better-sqlite3: 12.1.1
+ kysely: 0.28.2
+
dunder-proto@1.0.1:
dependencies:
call-bind-apply-helpers: 1.0.2
@@ -7559,7 +7601,7 @@ snapshots:
dependencies:
'@types/chai': 5.2.2
'@vitest/expect': 3.2.4
- '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@22.15.32)(tsx@3.14.0)(yaml@2.8.0))
+ '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@24.0.4)(tsx@4.20.3)(yaml@2.8.0))
'@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.2.4
'@vitest/snapshot': 3.2.4
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 01d48480c..b9a0f309c 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -1,9 +1,8 @@
packages:
- - 'packages/*'
- - 'packages/platforms/*'
- - 'packages/drivers/*'
- - 'packages/components/*'
- - 'packages/misc/*'
- - 'packages/frameworks/*'
- - 'examples/*'
-
+ - packages/*
+ - packages/platforms/*
+ - packages/drivers/*
+ - packages/components/*
+ - packages/misc/*
+ - packages/frameworks/*
+ - examples/*