From 6950311aa04c61bce3715492557e479ba61cf4c9 Mon Sep 17 00:00:00 2001 From: Nathan Flurry Date: Fri, 27 Jun 2025 04:18:11 +0000 Subject: [PATCH] chore(example): add better-auth-external-sql example --- examples/better-auth-external-db/.gitignore | 31 +++++++++ .../README.md | 27 ++++++-- .../package.json | 9 ++- .../rivet.json | 0 .../scripts/setup-db.ts | 66 +++++++++++++++++++ .../src/backend/auth.ts | 10 +++ .../src/backend/registry.ts | 37 ++++++++--- .../src/backend/server.ts | 6 +- .../src/frontend/App.tsx | 0 .../src/frontend/auth-client.ts | 0 .../src/frontend/components/AuthForm.tsx | 0 .../src/frontend/components/ChatRoom.tsx | 2 +- .../src/frontend/index.html | 0 .../src/frontend/main.tsx | 0 .../tsconfig.json | 0 .../turbo.json | 0 .../vite.config.ts | 0 examples/better-auth/src/backend/auth.ts | 17 ----- examples/hono-react/src/frontend/App.tsx | 2 +- examples/react/src/frontend/App.tsx | 2 +- packages/core/src/actor/errors.ts | 16 ++++- packages/core/src/actor/mod.ts | 2 +- pnpm-lock.yaml | 40 ++++++----- pnpm-workspace.yaml | 23 ++++--- 24 files changed, 224 insertions(+), 66 deletions(-) create mode 100644 examples/better-auth-external-db/.gitignore rename examples/{better-auth => better-auth-external-db}/README.md (63%) rename examples/{better-auth => better-auth-external-db}/package.json (81%) rename examples/{better-auth => better-auth-external-db}/rivet.json (100%) create mode 100644 examples/better-auth-external-db/scripts/setup-db.ts create mode 100644 examples/better-auth-external-db/src/backend/auth.ts rename examples/{better-auth => better-auth-external-db}/src/backend/registry.ts (64%) rename examples/{better-auth => better-auth-external-db}/src/backend/server.ts (69%) rename examples/{better-auth => better-auth-external-db}/src/frontend/App.tsx (100%) rename examples/{better-auth => better-auth-external-db}/src/frontend/auth-client.ts (100%) rename examples/{better-auth => better-auth-external-db}/src/frontend/components/AuthForm.tsx (100%) rename examples/{better-auth => better-auth-external-db}/src/frontend/components/ChatRoom.tsx (99%) rename examples/{better-auth => better-auth-external-db}/src/frontend/index.html (100%) rename examples/{better-auth => better-auth-external-db}/src/frontend/main.tsx (100%) rename examples/{better-auth => better-auth-external-db}/tsconfig.json (100%) rename examples/{better-auth => better-auth-external-db}/turbo.json (100%) rename examples/{better-auth => better-auth-external-db}/vite.config.ts (100%) delete mode 100644 examples/better-auth/src/backend/auth.ts diff --git a/examples/better-auth-external-db/.gitignore b/examples/better-auth-external-db/.gitignore new file mode 100644 index 000000000..959e16e69 --- /dev/null +++ b/examples/better-auth-external-db/.gitignore @@ -0,0 +1,31 @@ +# Dependencies +node_modules +.pnpm-debug.log* + +# Build outputs +dist +.turbo + +# Environment variables +.env +.env.local +.env.production.local +.env.development.local + +# Database +*.sqlite +*.db + +# IDE +.vscode +.idea + +# OS +.DS_Store +Thumbs.db + +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* \ No newline at end of file diff --git a/examples/better-auth/README.md b/examples/better-auth-external-db/README.md similarity index 63% rename from examples/better-auth/README.md rename to examples/better-auth-external-db/README.md index beef4719a..936e59286 100644 --- a/examples/better-auth/README.md +++ b/examples/better-auth-external-db/README.md @@ -1,6 +1,6 @@ -# Better Auth Integration for RivetKit +# Better Auth with External Database for RivetKit -Example project demonstrating authentication integration with [RivetKit](https://rivetkit.org) using Better Auth. +Example project demonstrating authentication integration with [RivetKit](https://rivetkit.org) using Better Auth and SQLite database. [Learn More →](https://github.com/rivet-gg/rivetkit) @@ -17,10 +17,20 @@ Example project demonstrating authentication integration with [RivetKit](https:/ ```sh git clone https://github.com/rivet-gg/rivetkit -cd rivetkit/examples/better-auth +cd rivetkit/examples/better-auth-external-db npm install ``` +### Database Setup + +Initialize the SQLite database with Better Auth tables: + +```sh +npm run db:setup +``` + +This will create the `auth.sqlite` database file with the required tables for user authentication. + ### Development ```sh @@ -34,21 +44,26 @@ Open your browser to `http://localhost:5173` to see the frontend and the backend - **Authentication**: Email/password authentication using Better Auth - **Protected Actors**: RivetKit actors with authentication via `onAuth` hook - **Real-time Chat**: Authenticated chat room with real-time messaging -- **SQLite Database**: Persistent user data and session storage +- **External Database**: Shows how to configure Better Auth with external database (SQLite example) ## How It Works -1. **Better Auth Setup**: Configured with SQLite adapter for user storage +1. **Better Auth Setup**: Configured with SQLite database for persistent user storage 2. **Protected Actor**: The `chatRoom` actor uses the `onAuth` hook to verify user sessions 3. **Frontend Integration**: React components handle authentication flow and chat interface 4. **Session Management**: Better Auth handles session creation, validation, and cleanup +## Database Commands + +- `npm run db:setup` - Initialize SQLite database with Better Auth tables + ## Key Files -- `src/backend/auth.ts` - Better Auth configuration with SQLite +- `src/backend/auth.ts` - Better Auth configuration with SQLite database - `src/backend/registry.ts` - RivetKit actor with authentication - `src/frontend/components/AuthForm.tsx` - Login/signup form - `src/frontend/components/ChatRoom.tsx` - Authenticated chat interface +- `auth.sqlite` - SQLite database file (auto-created) ## License diff --git a/examples/better-auth/package.json b/examples/better-auth-external-db/package.json similarity index 81% rename from examples/better-auth/package.json rename to examples/better-auth-external-db/package.json index ef3051e8a..5c4cc3ab1 100644 --- a/examples/better-auth/package.json +++ b/examples/better-auth-external-db/package.json @@ -1,5 +1,5 @@ { - "name": "example-better-auth", + "name": "example-better-auth-external-db", "version": "0.9.0-rc.1", "private": true, "type": "module", @@ -9,15 +9,16 @@ "dev:frontend": "vite", "build": "vite build", "check-types": "tsc --noEmit", - "test": "vitest run" + "test": "vitest run", + "db:setup": "tsx scripts/setup-db.ts" }, "devDependencies": { + "@rivetkit/actor": "workspace:*", "@types/node": "^22.13.9", "@types/react": "^18.2.0", "@types/react-dom": "^18.2.0", "@vitejs/plugin-react": "^4.2.0", "concurrently": "^8.2.2", - "@rivetkit/actor": "workspace:*", "tsx": "^3.12.7", "typescript": "^5.5.2", "vite": "^5.0.0", @@ -25,7 +26,9 @@ }, "dependencies": { "@rivetkit/react": "workspace:*", + "@types/better-sqlite3": "^7.6.13", "better-auth": "^1.0.1", + "better-sqlite3": "^11.10.0", "hono": "^4.7.0", "react": "^18.2.0", "react-dom": "^18.2.0" diff --git a/examples/better-auth/rivet.json b/examples/better-auth-external-db/rivet.json similarity index 100% rename from examples/better-auth/rivet.json rename to examples/better-auth-external-db/rivet.json diff --git a/examples/better-auth-external-db/scripts/setup-db.ts b/examples/better-auth-external-db/scripts/setup-db.ts new file mode 100644 index 000000000..48b99b0eb --- /dev/null +++ b/examples/better-auth-external-db/scripts/setup-db.ts @@ -0,0 +1,66 @@ +import Database from "better-sqlite3"; + +// Create SQLite database and tables for Better Auth +const db = new Database("/tmp/auth.sqlite"); + +// Create user table +db.exec(` + CREATE TABLE IF NOT EXISTS user ( + id TEXT PRIMARY KEY, + email TEXT UNIQUE NOT NULL, + emailVerified BOOLEAN NOT NULL DEFAULT FALSE, + name TEXT NOT NULL, + createdAt INTEGER NOT NULL, + updatedAt INTEGER NOT NULL + ); +`); + +// Create session table +db.exec(` + CREATE TABLE IF NOT EXISTS session ( + id TEXT PRIMARY KEY, + userId TEXT NOT NULL, + expiresAt INTEGER NOT NULL, + token TEXT UNIQUE NOT NULL, + createdAt INTEGER NOT NULL, + updatedAt INTEGER NOT NULL, + ipAddress TEXT, + userAgent TEXT, + FOREIGN KEY (userId) REFERENCES user(id) ON DELETE CASCADE + ); +`); + +// Create account table +db.exec(` + CREATE TABLE IF NOT EXISTS account ( + id TEXT PRIMARY KEY, + userId TEXT NOT NULL, + accountId TEXT NOT NULL, + providerId TEXT NOT NULL, + accessToken TEXT, + refreshToken TEXT, + idToken TEXT, + accessTokenExpiresAt INTEGER, + refreshTokenExpiresAt INTEGER, + scope TEXT, + password TEXT, + createdAt INTEGER NOT NULL, + updatedAt INTEGER NOT NULL, + FOREIGN KEY (userId) REFERENCES user(id) ON DELETE CASCADE + ); +`); + +// Create verification table +db.exec(` + CREATE TABLE IF NOT EXISTS verification ( + id TEXT PRIMARY KEY, + identifier TEXT NOT NULL, + value TEXT NOT NULL, + expiresAt INTEGER NOT NULL, + createdAt INTEGER NOT NULL, + updatedAt INTEGER NOT NULL + ); +`); + +console.log("Database tables created successfully!"); +db.close(); diff --git a/examples/better-auth-external-db/src/backend/auth.ts b/examples/better-auth-external-db/src/backend/auth.ts new file mode 100644 index 000000000..8711420d9 --- /dev/null +++ b/examples/better-auth-external-db/src/backend/auth.ts @@ -0,0 +1,10 @@ +import { betterAuth } from "better-auth"; +import Database from "better-sqlite3"; + +export const auth = betterAuth({ + database: new Database("/tmp/auth.sqlite"), + trustedOrigins: ["http://localhost:5173"], + emailAndPassword: { + enabled: true, + }, +}); diff --git a/examples/better-auth/src/backend/registry.ts b/examples/better-auth-external-db/src/backend/registry.ts similarity index 64% rename from examples/better-auth/src/backend/registry.ts rename to examples/better-auth-external-db/src/backend/registry.ts index d0b117964..a071d6f51 100644 --- a/examples/better-auth/src/backend/registry.ts +++ b/examples/better-auth-external-db/src/backend/registry.ts @@ -1,4 +1,5 @@ -import { actor, OnAuthOptions, setup, UserError } from "@rivetkit/actor"; +import { actor, setup, type OnAuthOptions } from "@rivetkit/actor"; +import { Unauthorized } from "@rivetkit/actor/errors"; import { auth } from "./auth"; interface State { @@ -13,17 +14,25 @@ interface Message { timestamp: number; } + + + + + + + + + export const chatRoom = actor({ + // onAuth runs on the server & before connecting to the actor onAuth: async (c: OnAuthOptions) => { + // ✨ NEW ✨ Access Better Auth session const authResult = await auth.api.getSession({ headers: c.req.headers, }); - console.log("auth result", authResult); - - if (!authResult?.session || !authResult?.user) { - throw new UserError("Unauthorized"); - } + if (!authResult) throw new Unauthorized(); + // Passes auth data to the actor (c.conn.auth) return { user: authResult.user, session: authResult.session, @@ -34,10 +43,11 @@ export const chatRoom = actor({ } as State, actions: { sendMessage: (c, message: string) => { + // ✨ NEW ✨ — Access Better Auth with c.conn.auth const newMessage = { id: crypto.randomUUID(), - userId: "TODO", - username: c.conn.auth.user.email || "Unknown", + userId: c.conn.auth.user.id, + username: c.conn.auth.user.name, message, timestamp: Date.now(), }; @@ -53,6 +63,17 @@ export const chatRoom = actor({ }, }); + + + + + + + + + + + export const registry = setup({ use: { chatRoom }, }); diff --git a/examples/better-auth/src/backend/server.ts b/examples/better-auth-external-db/src/backend/server.ts similarity index 69% rename from examples/better-auth/src/backend/server.ts rename to examples/better-auth-external-db/src/backend/server.ts index 25ee05782..3364950d1 100644 --- a/examples/better-auth/src/backend/server.ts +++ b/examples/better-auth-external-db/src/backend/server.ts @@ -2,9 +2,10 @@ import { registry } from "./registry"; import { auth } from "./auth"; import { Hono } from "hono"; import { cors } from "hono/cors"; +import { ALLOWED_PUBLIC_HEADERS } from "@rivetkit/actor"; // Start RivetKit -const { client, hono, serve } = registry.createServer(); +const { serve } = registry.createServer(); // Setup router const app = new Hono(); @@ -13,7 +14,8 @@ app.use( "*", cors({ origin: ["http://localhost:5173"], - allowHeaders: ["Content-Type", "Authorization"], + // Need to allow custom headers used in RivetKit + allowHeaders: ["Authorization", ...ALLOWED_PUBLIC_HEADERS], allowMethods: ["POST", "GET", "OPTIONS"], exposeHeaders: ["Content-Length"], maxAge: 600, diff --git a/examples/better-auth/src/frontend/App.tsx b/examples/better-auth-external-db/src/frontend/App.tsx similarity index 100% rename from examples/better-auth/src/frontend/App.tsx rename to examples/better-auth-external-db/src/frontend/App.tsx diff --git a/examples/better-auth/src/frontend/auth-client.ts b/examples/better-auth-external-db/src/frontend/auth-client.ts similarity index 100% rename from examples/better-auth/src/frontend/auth-client.ts rename to examples/better-auth-external-db/src/frontend/auth-client.ts diff --git a/examples/better-auth/src/frontend/components/AuthForm.tsx b/examples/better-auth-external-db/src/frontend/components/AuthForm.tsx similarity index 100% rename from examples/better-auth/src/frontend/components/AuthForm.tsx rename to examples/better-auth-external-db/src/frontend/components/AuthForm.tsx diff --git a/examples/better-auth/src/frontend/components/ChatRoom.tsx b/examples/better-auth-external-db/src/frontend/components/ChatRoom.tsx similarity index 99% rename from examples/better-auth/src/frontend/components/ChatRoom.tsx rename to examples/better-auth-external-db/src/frontend/components/ChatRoom.tsx index b97113737..58e99b680 100644 --- a/examples/better-auth/src/frontend/components/ChatRoom.tsx +++ b/examples/better-auth-external-db/src/frontend/components/ChatRoom.tsx @@ -3,7 +3,7 @@ import { createClient, createRivetKit } from "@rivetkit/react"; import { authClient } from "../auth-client"; import type { registry } from "../../backend/registry"; -const client = createClient("http://localhost:8080/registry"); +const client = createClient("http://localhost:8080"); const { useActor } = createRivetKit(client); diff --git a/examples/better-auth/src/frontend/index.html b/examples/better-auth-external-db/src/frontend/index.html similarity index 100% rename from examples/better-auth/src/frontend/index.html rename to examples/better-auth-external-db/src/frontend/index.html diff --git a/examples/better-auth/src/frontend/main.tsx b/examples/better-auth-external-db/src/frontend/main.tsx similarity index 100% rename from examples/better-auth/src/frontend/main.tsx rename to examples/better-auth-external-db/src/frontend/main.tsx diff --git a/examples/better-auth/tsconfig.json b/examples/better-auth-external-db/tsconfig.json similarity index 100% rename from examples/better-auth/tsconfig.json rename to examples/better-auth-external-db/tsconfig.json diff --git a/examples/better-auth/turbo.json b/examples/better-auth-external-db/turbo.json similarity index 100% rename from examples/better-auth/turbo.json rename to examples/better-auth-external-db/turbo.json diff --git a/examples/better-auth/vite.config.ts b/examples/better-auth-external-db/vite.config.ts similarity index 100% rename from examples/better-auth/vite.config.ts rename to examples/better-auth-external-db/vite.config.ts diff --git a/examples/better-auth/src/backend/auth.ts b/examples/better-auth/src/backend/auth.ts deleted file mode 100644 index 1599dc4cf..000000000 --- a/examples/better-auth/src/backend/auth.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { betterAuth } from "better-auth"; - -export const auth = betterAuth({ - // IMPORTANT: Connect a real database for productoin use cases - // - // https://www.better-auth.com/docs/installation#create-database-tables - // database: memoryAdapter({ - // user: [], - // account: [], - // session: [], - // verifcation: [], - // }), - trustedOrigins: ["http://localhost:5173"], - emailAndPassword: { - enabled: true, - }, -}); diff --git a/examples/hono-react/src/frontend/App.tsx b/examples/hono-react/src/frontend/App.tsx index 1be67de1b..edc4d3d58 100644 --- a/examples/hono-react/src/frontend/App.tsx +++ b/examples/hono-react/src/frontend/App.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; import { createClient, createRivetKit } from "@rivetkit/react"; import type { registry } from "../backend/registry"; -const client = createClient("http://localhost:8080/registry"); +const client = createClient("http://localhost:8080"); const { useActor } = createRivetKit(client); function App() { diff --git a/examples/react/src/frontend/App.tsx b/examples/react/src/frontend/App.tsx index c5d451724..64fb3eccc 100644 --- a/examples/react/src/frontend/App.tsx +++ b/examples/react/src/frontend/App.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; import { createClient, createRivetKit } from "@rivetkit/react"; import type { registry } from "../backend/registry"; -const client = createClient(`http://localhost:8080/registry`); +const client = createClient(`http://localhost:8080`); const { useActor } = createRivetKit(client); function App() { diff --git a/packages/core/src/actor/errors.ts b/packages/core/src/actor/errors.ts index 7503ab1f7..63442c633 100644 --- a/packages/core/src/actor/errors.ts +++ b/packages/core/src/actor/errors.ts @@ -182,7 +182,8 @@ export class InvalidStateType extends ActorError { } else { msg += "Attempted to set invalid state."; } - msg += " State must be CBOR serializable. Valid types include: null, undefined, boolean, string, number, BigInt, Date, RegExp, Error, typed arrays (Uint8Array, Int8Array, Float32Array, etc.), Map, Set, Array, and plain objects."; + msg += + " State must be CBOR serializable. Valid types include: null, undefined, boolean, string, number, BigInt, Date, RegExp, Error, typed arrays (Uint8Array, Int8Array, Float32Array, etc.), Map, Set, Array, and plain objects."; super("invalid_state_type", msg); } } @@ -289,9 +290,20 @@ export class InvalidParams extends ActorError { } } +export class Unauthorized extends ActorError { + constructor(message?: string) { + super("unauthorized", message ?? "Unauthorized. Access denied.", { + public: true, + }); + this.statusCode = 401; + } +} + export class Forbidden extends ActorError { constructor(message?: string) { - super("forbidden", message ?? "Access denied", { public: true }); + super("forbidden", message ?? "Forbidden. Access denied.", { + public: true, + }); this.statusCode = 403; } } diff --git a/packages/core/src/actor/mod.ts b/packages/core/src/actor/mod.ts index 3b5fb213e..22a9f7e46 100644 --- a/packages/core/src/actor/mod.ts +++ b/packages/core/src/actor/mod.ts @@ -42,4 +42,4 @@ export type { ActorContextOf, ActionContextOf, } from "./definition"; -export { ALLOWED_PUBLIC_HEADERS} from "./router-endpoints"; +export { ALLOWED_PUBLIC_HEADERS } from "./router-endpoints"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 36b1918d6..7d6b14daf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -49,17 +49,20 @@ importers: specifier: ^8.3.2 version: 8.5.5 - examples/better-auth: + examples/better-auth-external-db: dependencies: '@rivetkit/react': specifier: workspace:* version: link:../../packages/frameworks/react + '@types/better-sqlite3': + specifier: ^7.6.13 + version: 7.6.13 better-auth: specifier: ^1.0.1 version: 1.2.10 better-sqlite3: - specifier: ^9.4.3 - version: 9.6.0 + specifier: ^11.10.0 + version: 11.10.0 hono: specifier: ^4.7.0 version: 4.8.0 @@ -73,9 +76,6 @@ importers: '@rivetkit/actor': specifier: workspace:* version: link:../../packages/actor - '@types/better-sqlite3': - specifier: ^7.6.9 - version: 7.6.13 '@types/node': specifier: ^22.13.9 version: 22.15.32 @@ -2237,9 +2237,6 @@ packages: better-sqlite3@11.10.0: resolution: {integrity: sha512-EwhOpyXiOEL/lKzHz9AW1msWFNzGc/z+LzeB3/jnFJpxu+th2yqvzsSWas1v9jgs9+xiXJcD5A8CJxAG2TaghQ==} - better-sqlite3@9.6.0: - resolution: {integrity: sha512-yR5HATnqeYNVnkaUTf4bOP2dJSnyhP4puJN/QPRyx4YkBEEUxib422n2XzPqDEHjQQqazoYoADdAm5vE15+dAQ==} - bindings@1.5.0: resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} @@ -5412,6 +5409,22 @@ snapshots: 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@22.15.32)(tsx@4.20.3)(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@4.20.3)(yaml@2.8.0) + + '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@24.0.3)(tsx@4.20.3)(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@24.0.3)(tsx@4.20.3)(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 @@ -5606,11 +5619,6 @@ snapshots: bindings: 1.5.0 prebuild-install: 7.1.3 - better-sqlite3@9.6.0: - dependencies: - bindings: 1.5.0 - prebuild-install: 7.1.3 - bindings@1.5.0: dependencies: file-uri-to-path: 1.0.0 @@ -7512,7 +7520,7 @@ snapshots: dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@24.0.4)(tsx@4.20.3)(yaml@2.8.0)) + '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@22.15.32)(tsx@4.20.3)(yaml@2.8.0)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -7595,7 +7603,7 @@ snapshots: dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@24.0.4)(tsx@4.20.3)(yaml@2.8.0)) + '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@24.0.3)(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..cbc343523 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,9 +1,16 @@ 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/* +onlyBuiltDependencies: + - '@biomejs/biome' + - better-sqlite3 + - cbor-extract + - esbuild + - lefthook + - sharp + - workerd