From c6a8a3a6209ac7e1ef041b41069248f4a1ee2a2e Mon Sep 17 00:00:00 2001 From: "rivet-docs-sync[bot]" Date: Thu, 29 Oct 2026 08:18:16 +0000 Subject: [PATCH] docs(integrations): sync from rivet-dev/rivet@4a58441 Amp-Thread-ID: https://ampcode.com/threads/T-28153e7f-cca7-4ed0-9e45-c74935ab7ac0 Co-authored-by: Amp --- .../integrations/docs/content/docs/turso.mdx | 133 +++++++++++++++++ .../log-cache.ts | 15 ++ .../actors-quickstart-next-js/app/page.tsx | 5 + .../rivet/Counter.tsx | 23 +++ .../actors-quickstart-next-js/rivet/node.ts | 3 + .../{ => rivet}/registry.ts | 0 .../examples/docs/api/actors-destroy.ts | 2 +- .../examples/docs/api/actors-list-names.ts | 2 +- .../examples/docs/api/actors-list.ts | 2 +- .../examples/docs/api/actors-reschedule.ts | 2 +- .../examples/docs/api/actors-sleep.ts | 2 +- .../examples/docs/api/connection-actions.ts | 2 +- .../examples/docs/api/connection-connect.ts | 2 +- .../examples/docs/api/connection-errors.ts | 2 +- .../examples/docs/api/connection-events.ts | 2 +- .../docs/api/control-plane-datacenters.ts | 2 +- .../docs/api/control-plane-metadata.ts | 2 +- .../examples/docs/api/gateway-metadata.ts | 2 +- .../examples/docs/api/gateway-queue.ts | 2 +- .../examples/docs/api/inspector-action.ts | 2 +- .../docs/api/inspector-connections.ts | 2 +- .../docs/api/inspector-database-execute.ts | 2 +- .../docs/api/inspector-database-rows.ts | 2 +- .../docs/api/inspector-database-schema.ts | 2 +- .../docs/api/inspector-queue-delete.ts | 2 +- .../examples/docs/api/inspector-queue-get.ts | 2 +- .../examples/docs/api/inspector-queue-post.ts | 2 +- .../examples/docs/api/inspector-rpcs.ts | 2 +- .../examples/docs/api/inspector-state-get.ts | 2 +- .../docs/api/inspector-state-patch.ts | 2 +- .../examples/docs/api/inspector-summary.ts | 2 +- .../examples/docs/api/inspector-traces.ts | 2 +- .../docs/api/inspector-workflow-history.ts | 2 +- .../docs/api/inspector-workflow-replay.ts | 2 +- .../examples/docs/api/namespaces-create.ts | 2 +- .../examples/docs/api/namespaces-list.ts | 2 +- .../examples/docs/api/tokens-inspect.ts | 2 +- .../docs/api/workers-configs-delete.ts | 2 +- .../examples/docs/api/workers-configs-list.ts | 2 +- .../api/workers-configs-refresh-metadata.ts | 2 +- .../docs/api/workers-configs-upsert.ts | 2 +- .../examples/docs/api/workers-list.ts | 2 +- .../api/workers-serverless-health-check.ts | 2 +- .../docs/cookbook-cron-jobs/daily-report.ts | 18 --- .../docs/general-jwt/quickstart/client.ts | 2 +- .../integrations/examples/docs/package.json | 4 +- vendor/integrations/examples/turso/.gitignore | 4 + vendor/integrations/examples/turso/README.md | 43 ++++++ .../integrations/examples/turso/package.json | 31 ++++ .../examples/turso/scripts/client.ts | 18 +++ .../integrations/examples/turso/src/index.ts | 140 ++++++++++++++++++ .../examples/turso/tests/turso.test.ts | 51 +++++++ .../integrations/examples/turso/tsconfig.json | 15 ++ vendor/integrations/examples/turso/turbo.json | 4 + .../examples/turso/vitest.config.ts | 9 ++ 55 files changed, 534 insertions(+), 58 deletions(-) create mode 100644 vendor/integrations/docs/content/docs/turso.mdx create mode 100644 vendor/integrations/examples/docs/actors-performance-monitoring/log-cache.ts create mode 100644 vendor/integrations/examples/docs/actors-quickstart-next-js/app/page.tsx create mode 100644 vendor/integrations/examples/docs/actors-quickstart-next-js/rivet/Counter.tsx create mode 100644 vendor/integrations/examples/docs/actors-quickstart-next-js/rivet/node.ts rename vendor/integrations/examples/docs/actors-quickstart-next-js/{ => rivet}/registry.ts (100%) delete mode 100644 vendor/integrations/examples/docs/cookbook-cron-jobs/daily-report.ts create mode 100644 vendor/integrations/examples/turso/.gitignore create mode 100644 vendor/integrations/examples/turso/README.md create mode 100644 vendor/integrations/examples/turso/package.json create mode 100644 vendor/integrations/examples/turso/scripts/client.ts create mode 100644 vendor/integrations/examples/turso/src/index.ts create mode 100644 vendor/integrations/examples/turso/tests/turso.test.ts create mode 100644 vendor/integrations/examples/turso/tsconfig.json create mode 100644 vendor/integrations/examples/turso/turbo.json create mode 100644 vendor/integrations/examples/turso/vitest.config.ts diff --git a/vendor/integrations/docs/content/docs/turso.mdx b/vendor/integrations/docs/content/docs/turso.mdx new file mode 100644 index 00000000..54045a29 --- /dev/null +++ b/vendor/integrations/docs/content/docs/turso.mdx @@ -0,0 +1,133 @@ +--- +title: "Turso" +description: "Give each Rivet Actor its own Turso Cloud database." +skill: false +--- + +[Turso Cloud](https://turso.tech) hosts SQLite-compatible databases you reach over the network, and you can create as many as you need through its Platform API. That fits Rivet Actors well: each actor creates its own Turso database, opens a client to it in `createVars`, and deletes the database when the actor is destroyed. + + + +## Quickstart + + + + + +Install the [Turso CLI](https://docs.turso.tech/cli/installation), sign in, and find your organization slug: + +```sh +turso auth login +turso org list +``` + +Mint a Platform API token. The actor uses it to create and delete databases: + +```sh +turso auth api-tokens mint rivet-todos +``` + + + + + +```sh +npm install rivetkit @libsql/client @tursodatabase/api +``` + +`@tursodatabase/api` calls the Platform API. `@libsql/client` queries a database. The Platform API creates [libSQL](https://docs.turso.tech/libsql) databases by default, which use that driver. + + + + + +Create `.env` with your organization slug and token: + + + + + + + +Each `todoList` actor owns one list and one Turso database. + + + + + + + +Start the server, then call the actor from a client: + +```sh +npx tsx --env-file=.env src/index.ts +``` + + + +```sh +npx tsx scripts/client.ts +``` + + + + + +## Database lifecycle + +| Hook | What it does | +| --- | --- | +| `createState` | Runs once, when the actor is created. Creates the actor's database and a token scoped to it, and saves both in [state](/actors/docs/state). A database left over from a failed creation attempt is reused. | +| `createVars` | Runs on every start. Opens a client to the database on `c.vars` and creates the table if it does not exist. When the actor sleeps, `c.vars` is dropped, and the next wake opens a new client. | +| `onDestroy` | Deletes the database. | + +The client lives on `c.vars` because it is a live object. [Ephemeral variables](/actors/docs/state#ephemeral-state) are never persisted, so each start gets a fresh client. + +Databases are named `todos-`, so a new actor with a reused key gets a new database. Each one counts toward your Turso plan's database limit. + +## Why the client is never closed + +Every action awaits its statement. `execute()` resolves only after the server returns the result, so the write is committed before the action returns. + +In Node, `@libsql/client` sends `libsql://` URLs over HTTP. Each statement opens a stream and closes it when its result arrives, and connections come from Node's shared `fetch` pool. An idle client holds no connections, so dropping `c.vars` releases it. + +Calling `close()` in `onSleep` or `onDestroy` would not release anything more, and it can break writes. `close()` is synchronous and does not flush: it rejects statements the client has not sent yet. `onSleep` and `onDestroy` run alongside in-flight actions during the [shutdown sequence](/actors/docs/lifecycle#shutdown-sequence), so a write that is still queued would fail. + +This relies on the HTTP transport. A `wss://` URL keeps a WebSocket open, and an interactive transaction holds a server-side stream until it commits or rolls back. Close those explicitly, after every statement that uses them has settled. + +`onDestroy` is best effort: if the process crashes during destroy, the database stays and must be deleted with the Turso CLI or Platform API. + +## Credentials + +The Platform API token can create and delete every database in its organization, so it stays in the server's environment. Each actor keeps only the token for its own database in its state. + +## Startup timeout + +`createVars` must finish within `createVarsTimeout`, which defaults to 5 seconds. Its first query opens the connection to Turso, so a node far from the database's region spends part of that budget on the round trip. Raise `options.createVarsTimeout` if starts time out. See [Options](/actors/docs/lifecycle#options). + +## Testing + +The test creates real Turso databases, so it reads the same environment variables and is skipped without them. It checks that each list gets its own database and that destroying a list deletes it: + + + +See the [Turso Platform API](https://docs.turso.tech/api-reference/introduction) and [TypeScript reference](https://docs.turso.tech/sdk/ts/reference) for the full APIs. + +## Local disk + +This guide queries Turso Cloud over the network, so nodes need no local disk. Turso's local options keep a database file on the node's disk instead: [embedded replicas](https://docs.turso.tech/features/embedded-replicas/introduction), `@tursodatabase/database`, and `@tursodatabase/sync`. + +If you use one of them, verify that your platform gives nodes a local disk. Some serverless platforms do not by default. Google Cloud Run, for example, uses an [in-memory file system](https://cloud.google.com/run/docs/container-contract#filesystem), so the database file uses the instance's memory and is lost when the instance stops. Rivet Cloud provides local disk to nodes, so local Turso databases work there without extra setup. diff --git a/vendor/integrations/examples/docs/actors-performance-monitoring/log-cache.ts b/vendor/integrations/examples/docs/actors-performance-monitoring/log-cache.ts new file mode 100644 index 00000000..e6e211d5 --- /dev/null +++ b/vendor/integrations/examples/docs/actors-performance-monitoring/log-cache.ts @@ -0,0 +1,15 @@ +import { actor } from "rivetkit"; +import { db } from "rivetkit/db"; + +export const myActor = actor({ + db: db(), + actions: { + logCache: async (c) => { + await c.db.execute("SELECT 1"); + const metrics = await c.db.nativeMetrics?.(); + if (metrics) { + c.log.info({ msg: "SQLite cache", ...metrics }); + } + }, + }, +}); diff --git a/vendor/integrations/examples/docs/actors-quickstart-next-js/app/page.tsx b/vendor/integrations/examples/docs/actors-quickstart-next-js/app/page.tsx new file mode 100644 index 00000000..a0c8ade1 --- /dev/null +++ b/vendor/integrations/examples/docs/actors-quickstart-next-js/app/page.tsx @@ -0,0 +1,5 @@ +import { Counter } from "../rivet/Counter"; + +export default function Home() { + return ; +} diff --git a/vendor/integrations/examples/docs/actors-quickstart-next-js/rivet/Counter.tsx b/vendor/integrations/examples/docs/actors-quickstart-next-js/rivet/Counter.tsx new file mode 100644 index 00000000..f13b0c67 --- /dev/null +++ b/vendor/integrations/examples/docs/actors-quickstart-next-js/rivet/Counter.tsx @@ -0,0 +1,23 @@ +"use client"; + +import { createRivetKit } from "@rivetkit/next-js/client"; +import { useState } from "react"; +import type { registry } from "./registry"; + +const { useActor } = createRivetKit({ + endpoint: process.env.NEXT_PUBLIC_RIVET_ENDPOINT ?? "http://localhost:6420", +}); + +export function Counter() { + const [count, setCount] = useState(0); + const counter = useActor({ name: "counter", key: ["my-counter"] }); + + counter.useEvent("newCount", (value: number) => setCount(value)); + + return ( +
+

Count: {count}

+ +
+ ); +} diff --git a/vendor/integrations/examples/docs/actors-quickstart-next-js/rivet/node.ts b/vendor/integrations/examples/docs/actors-quickstart-next-js/rivet/node.ts new file mode 100644 index 00000000..aa0ee6ed --- /dev/null +++ b/vendor/integrations/examples/docs/actors-quickstart-next-js/rivet/node.ts @@ -0,0 +1,3 @@ +import { registry } from "./registry"; + +registry.start(); diff --git a/vendor/integrations/examples/docs/actors-quickstart-next-js/registry.ts b/vendor/integrations/examples/docs/actors-quickstart-next-js/rivet/registry.ts similarity index 100% rename from vendor/integrations/examples/docs/actors-quickstart-next-js/registry.ts rename to vendor/integrations/examples/docs/actors-quickstart-next-js/rivet/registry.ts diff --git a/vendor/integrations/examples/docs/api/actors-destroy.ts b/vendor/integrations/examples/docs/api/actors-destroy.ts index 7718ad8c..d76fa102 100644 --- a/vendor/integrations/examples/docs/api/actors-destroy.ts +++ b/vendor/integrations/examples/docs/api/actors-destroy.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const actorId = "00000000-0000-0000-0000-000000000000"; diff --git a/vendor/integrations/examples/docs/api/actors-list-names.ts b/vendor/integrations/examples/docs/api/actors-list-names.ts index ce5f865f..19ca05e2 100644 --- a/vendor/integrations/examples/docs/api/actors-list-names.ts +++ b/vendor/integrations/examples/docs/api/actors-list-names.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; diff --git a/vendor/integrations/examples/docs/api/actors-list.ts b/vendor/integrations/examples/docs/api/actors-list.ts index fcca97ee..55a79fcb 100644 --- a/vendor/integrations/examples/docs/api/actors-list.ts +++ b/vendor/integrations/examples/docs/api/actors-list.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; diff --git a/vendor/integrations/examples/docs/api/actors-reschedule.ts b/vendor/integrations/examples/docs/api/actors-reschedule.ts index 3a2f9b23..3bb1a563 100644 --- a/vendor/integrations/examples/docs/api/actors-reschedule.ts +++ b/vendor/integrations/examples/docs/api/actors-reschedule.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const actorId = "00000000-0000-0000-0000-000000000000"; diff --git a/vendor/integrations/examples/docs/api/actors-sleep.ts b/vendor/integrations/examples/docs/api/actors-sleep.ts index e1232b21..a1d07784 100644 --- a/vendor/integrations/examples/docs/api/actors-sleep.ts +++ b/vendor/integrations/examples/docs/api/actors-sleep.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const actorId = "00000000-0000-0000-0000-000000000000"; diff --git a/vendor/integrations/examples/docs/api/connection-actions.ts b/vendor/integrations/examples/docs/api/connection-actions.ts index d90ec127..3de81cd1 100644 --- a/vendor/integrations/examples/docs/api/connection-actions.ts +++ b/vendor/integrations/examples/docs/api/connection-actions.ts @@ -1,5 +1,5 @@ const ws = new WebSocket( - `wss://rivet.example.com/gateway/${process.env.ACTOR_ID}/connect`, + `wss://api.rivet.dev/gateway/${process.env.ACTOR_ID}/connect`, ["rivet", "rivet_encoding.json", `rivet_token.${process.env.RIVET_TOKEN}`], ); diff --git a/vendor/integrations/examples/docs/api/connection-connect.ts b/vendor/integrations/examples/docs/api/connection-connect.ts index ee4bf891..88e74ed3 100644 --- a/vendor/integrations/examples/docs/api/connection-connect.ts +++ b/vendor/integrations/examples/docs/api/connection-connect.ts @@ -1,7 +1,7 @@ // Open a connection by actor name. The selector query parameters are the same // ones used by the HTTP endpoints; the token and encoding travel as // WebSocket subprotocols because browsers cannot set headers on an upgrade. -const url = new URL("wss://rivet.example.com/gateway/counter/connect"); +const url = new URL("wss://api.rivet.dev/gateway/counter/connect"); url.searchParams.set("rvt-namespace", process.env.RIVET_NAMESPACE!); url.searchParams.set("rvt-method", "getOrCreate"); url.searchParams.set("rvt-key", "my-counter"); diff --git a/vendor/integrations/examples/docs/api/connection-errors.ts b/vendor/integrations/examples/docs/api/connection-errors.ts index f8e796c7..6345825a 100644 --- a/vendor/integrations/examples/docs/api/connection-errors.ts +++ b/vendor/integrations/examples/docs/api/connection-errors.ts @@ -1,5 +1,5 @@ const ws = new WebSocket( - `wss://rivet.example.com/gateway/${process.env.ACTOR_ID}/connect`, + `wss://api.rivet.dev/gateway/${process.env.ACTOR_ID}/connect`, ["rivet", "rivet_encoding.json", `rivet_token.${process.env.RIVET_TOKEN}`], ); diff --git a/vendor/integrations/examples/docs/api/connection-events.ts b/vendor/integrations/examples/docs/api/connection-events.ts index 71ad178a..7e85c61b 100644 --- a/vendor/integrations/examples/docs/api/connection-events.ts +++ b/vendor/integrations/examples/docs/api/connection-events.ts @@ -1,5 +1,5 @@ const ws = new WebSocket( - `wss://rivet.example.com/gateway/${process.env.ACTOR_ID}/connect`, + `wss://api.rivet.dev/gateway/${process.env.ACTOR_ID}/connect`, ["rivet", "rivet_encoding.json", `rivet_token.${process.env.RIVET_TOKEN}`], ); diff --git a/vendor/integrations/examples/docs/api/control-plane-datacenters.ts b/vendor/integrations/examples/docs/api/control-plane-datacenters.ts index 6f14c5eb..d5afca6c 100644 --- a/vendor/integrations/examples/docs/api/control-plane-datacenters.ts +++ b/vendor/integrations/examples/docs/api/control-plane-datacenters.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const token = process.env.RIVET_TOKEN ?? ""; const response = await fetch(`${endpoint}/datacenters`, { diff --git a/vendor/integrations/examples/docs/api/control-plane-metadata.ts b/vendor/integrations/examples/docs/api/control-plane-metadata.ts index ea784880..43300b91 100644 --- a/vendor/integrations/examples/docs/api/control-plane-metadata.ts +++ b/vendor/integrations/examples/docs/api/control-plane-metadata.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch(`${endpoint}/metadata`); const metadata = await response.json(); diff --git a/vendor/integrations/examples/docs/api/gateway-metadata.ts b/vendor/integrations/examples/docs/api/gateway-metadata.ts index 95da90f4..d677d2dd 100644 --- a/vendor/integrations/examples/docs/api/gateway-metadata.ts +++ b/vendor/integrations/examples/docs/api/gateway-metadata.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch( `${endpoint}/gateway/${process.env.ACTOR_ID}/metadata`, { diff --git a/vendor/integrations/examples/docs/api/gateway-queue.ts b/vendor/integrations/examples/docs/api/gateway-queue.ts index 73f95114..8d6a2aa6 100644 --- a/vendor/integrations/examples/docs/api/gateway-queue.ts +++ b/vendor/integrations/examples/docs/api/gateway-queue.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const actorId = process.env.ACTOR_ID; const response = await fetch(`${endpoint}/gateway/${actorId}/queue/increment`, { method: "POST", diff --git a/vendor/integrations/examples/docs/api/inspector-action.ts b/vendor/integrations/examples/docs/api/inspector-action.ts index ac8aca2c..78a79d4a 100644 --- a/vendor/integrations/examples/docs/api/inspector-action.ts +++ b/vendor/integrations/examples/docs/api/inspector-action.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch( `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/action/increment`, { diff --git a/vendor/integrations/examples/docs/api/inspector-connections.ts b/vendor/integrations/examples/docs/api/inspector-connections.ts index cebb890d..e9bb0ade 100644 --- a/vendor/integrations/examples/docs/api/inspector-connections.ts +++ b/vendor/integrations/examples/docs/api/inspector-connections.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch( `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/connections`, { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, diff --git a/vendor/integrations/examples/docs/api/inspector-database-execute.ts b/vendor/integrations/examples/docs/api/inspector-database-execute.ts index 0786a92e..d657c202 100644 --- a/vendor/integrations/examples/docs/api/inspector-database-execute.ts +++ b/vendor/integrations/examples/docs/api/inspector-database-execute.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch( `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/database/execute`, { diff --git a/vendor/integrations/examples/docs/api/inspector-database-rows.ts b/vendor/integrations/examples/docs/api/inspector-database-rows.ts index a21e1be3..060781c7 100644 --- a/vendor/integrations/examples/docs/api/inspector-database-rows.ts +++ b/vendor/integrations/examples/docs/api/inspector-database-rows.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const query = new URLSearchParams({ table: "users", limit: "100", diff --git a/vendor/integrations/examples/docs/api/inspector-database-schema.ts b/vendor/integrations/examples/docs/api/inspector-database-schema.ts index e6d5acdc..b95bd360 100644 --- a/vendor/integrations/examples/docs/api/inspector-database-schema.ts +++ b/vendor/integrations/examples/docs/api/inspector-database-schema.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch( `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/database/schema`, { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, diff --git a/vendor/integrations/examples/docs/api/inspector-queue-delete.ts b/vendor/integrations/examples/docs/api/inspector-queue-delete.ts index 748c1b4c..0786860a 100644 --- a/vendor/integrations/examples/docs/api/inspector-queue-delete.ts +++ b/vendor/integrations/examples/docs/api/inspector-queue-delete.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch( `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/queue`, { diff --git a/vendor/integrations/examples/docs/api/inspector-queue-get.ts b/vendor/integrations/examples/docs/api/inspector-queue-get.ts index a55ec407..82528552 100644 --- a/vendor/integrations/examples/docs/api/inspector-queue-get.ts +++ b/vendor/integrations/examples/docs/api/inspector-queue-get.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch( `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/queue?limit=50`, { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, diff --git a/vendor/integrations/examples/docs/api/inspector-queue-post.ts b/vendor/integrations/examples/docs/api/inspector-queue-post.ts index d5c71989..9a5d80ad 100644 --- a/vendor/integrations/examples/docs/api/inspector-queue-post.ts +++ b/vendor/integrations/examples/docs/api/inspector-queue-post.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch( `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/queue`, { diff --git a/vendor/integrations/examples/docs/api/inspector-rpcs.ts b/vendor/integrations/examples/docs/api/inspector-rpcs.ts index 356e615e..4f9f0c7c 100644 --- a/vendor/integrations/examples/docs/api/inspector-rpcs.ts +++ b/vendor/integrations/examples/docs/api/inspector-rpcs.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch( `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/rpcs`, { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, diff --git a/vendor/integrations/examples/docs/api/inspector-state-get.ts b/vendor/integrations/examples/docs/api/inspector-state-get.ts index 783deb57..53eacb7e 100644 --- a/vendor/integrations/examples/docs/api/inspector-state-get.ts +++ b/vendor/integrations/examples/docs/api/inspector-state-get.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch( `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/state`, { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, diff --git a/vendor/integrations/examples/docs/api/inspector-state-patch.ts b/vendor/integrations/examples/docs/api/inspector-state-patch.ts index 36ef34dc..bcdf52c1 100644 --- a/vendor/integrations/examples/docs/api/inspector-state-patch.ts +++ b/vendor/integrations/examples/docs/api/inspector-state-patch.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch( `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/state`, { diff --git a/vendor/integrations/examples/docs/api/inspector-summary.ts b/vendor/integrations/examples/docs/api/inspector-summary.ts index 37f0f793..5ddc54d9 100644 --- a/vendor/integrations/examples/docs/api/inspector-summary.ts +++ b/vendor/integrations/examples/docs/api/inspector-summary.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch( `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/summary`, { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, diff --git a/vendor/integrations/examples/docs/api/inspector-traces.ts b/vendor/integrations/examples/docs/api/inspector-traces.ts index 9a3c1a62..c9fc7ca1 100644 --- a/vendor/integrations/examples/docs/api/inspector-traces.ts +++ b/vendor/integrations/examples/docs/api/inspector-traces.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch( `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/traces?startMs=0&limit=100`, { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, diff --git a/vendor/integrations/examples/docs/api/inspector-workflow-history.ts b/vendor/integrations/examples/docs/api/inspector-workflow-history.ts index 64d289d0..0e1ed297 100644 --- a/vendor/integrations/examples/docs/api/inspector-workflow-history.ts +++ b/vendor/integrations/examples/docs/api/inspector-workflow-history.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch( `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/workflow-history`, { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, diff --git a/vendor/integrations/examples/docs/api/inspector-workflow-replay.ts b/vendor/integrations/examples/docs/api/inspector-workflow-replay.ts index 3bf3cdc8..23736edb 100644 --- a/vendor/integrations/examples/docs/api/inspector-workflow-replay.ts +++ b/vendor/integrations/examples/docs/api/inspector-workflow-replay.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch( `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/workflow/replay`, { diff --git a/vendor/integrations/examples/docs/api/namespaces-create.ts b/vendor/integrations/examples/docs/api/namespaces-create.ts index c2f92ff5..3bda46bc 100644 --- a/vendor/integrations/examples/docs/api/namespaces-create.ts +++ b/vendor/integrations/examples/docs/api/namespaces-create.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const token = process.env.RIVET_TOKEN ?? ""; const response = await fetch(`${endpoint}/namespaces`, { diff --git a/vendor/integrations/examples/docs/api/namespaces-list.ts b/vendor/integrations/examples/docs/api/namespaces-list.ts index 5b598685..34700884 100644 --- a/vendor/integrations/examples/docs/api/namespaces-list.ts +++ b/vendor/integrations/examples/docs/api/namespaces-list.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const token = process.env.RIVET_TOKEN ?? ""; const response = await fetch(`${endpoint}/namespaces`, { diff --git a/vendor/integrations/examples/docs/api/tokens-inspect.ts b/vendor/integrations/examples/docs/api/tokens-inspect.ts index c562d121..7573b89f 100644 --- a/vendor/integrations/examples/docs/api/tokens-inspect.ts +++ b/vendor/integrations/examples/docs/api/tokens-inspect.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const token = process.env.RIVET_TOKEN ?? ""; // Inspect reports on the token used to authenticate the request itself. diff --git a/vendor/integrations/examples/docs/api/workers-configs-delete.ts b/vendor/integrations/examples/docs/api/workers-configs-delete.ts index cdc01d9e..f830246e 100644 --- a/vendor/integrations/examples/docs/api/workers-configs-delete.ts +++ b/vendor/integrations/examples/docs/api/workers-configs-delete.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const workerName = process.env.RUNNER_NAME ?? "default"; diff --git a/vendor/integrations/examples/docs/api/workers-configs-list.ts b/vendor/integrations/examples/docs/api/workers-configs-list.ts index 1f1c8521..8f13f84f 100644 --- a/vendor/integrations/examples/docs/api/workers-configs-list.ts +++ b/vendor/integrations/examples/docs/api/workers-configs-list.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; diff --git a/vendor/integrations/examples/docs/api/workers-configs-refresh-metadata.ts b/vendor/integrations/examples/docs/api/workers-configs-refresh-metadata.ts index 337d7c97..1f1a7c02 100644 --- a/vendor/integrations/examples/docs/api/workers-configs-refresh-metadata.ts +++ b/vendor/integrations/examples/docs/api/workers-configs-refresh-metadata.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const workerName = process.env.RUNNER_NAME ?? "default"; diff --git a/vendor/integrations/examples/docs/api/workers-configs-upsert.ts b/vendor/integrations/examples/docs/api/workers-configs-upsert.ts index 50a37d3d..f46c7f76 100644 --- a/vendor/integrations/examples/docs/api/workers-configs-upsert.ts +++ b/vendor/integrations/examples/docs/api/workers-configs-upsert.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const workerName = process.env.RUNNER_NAME ?? "default"; diff --git a/vendor/integrations/examples/docs/api/workers-list.ts b/vendor/integrations/examples/docs/api/workers-list.ts index 06f1d56e..7d627ad4 100644 --- a/vendor/integrations/examples/docs/api/workers-list.ts +++ b/vendor/integrations/examples/docs/api/workers-list.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; diff --git a/vendor/integrations/examples/docs/api/workers-serverless-health-check.ts b/vendor/integrations/examples/docs/api/workers-serverless-health-check.ts index 860536f6..c6e0c54f 100644 --- a/vendor/integrations/examples/docs/api/workers-serverless-health-check.ts +++ b/vendor/integrations/examples/docs/api/workers-serverless-health-check.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; diff --git a/vendor/integrations/examples/docs/cookbook-cron-jobs/daily-report.ts b/vendor/integrations/examples/docs/cookbook-cron-jobs/daily-report.ts deleted file mode 100644 index c434d36c..00000000 --- a/vendor/integrations/examples/docs/cookbook-cron-jobs/daily-report.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { actor } from "rivetkit"; - -export const dailyReport = actor({ - state: { lastRunAt: 0 }, - onCreate: async (c) => { - await c.cron.set({ - name: "daily-report", - expression: "0 9 * * *", - action: "runReport", - }); - }, - actions: { - runReport: (c) => { - // Do the job's work, then record the run. - c.state.lastRunAt = Date.now(); - }, - }, -}); diff --git a/vendor/integrations/examples/docs/general-jwt/quickstart/client.ts b/vendor/integrations/examples/docs/general-jwt/quickstart/client.ts index bf78e5d5..49cbb1ed 100644 --- a/vendor/integrations/examples/docs/general-jwt/quickstart/client.ts +++ b/vendor/integrations/examples/docs/general-jwt/quickstart/client.ts @@ -14,7 +14,7 @@ async function fetchToken(): Promise<{ actorId: string; token: string }> { const { actorId } = await fetchToken(); const client = createClient({ - endpoint: "https://my-namespace@rivet.example.com", + endpoint: "https://rivet.example.com", namespace: "production", // Called whenever RivetKit needs a credential, including after one expires. diff --git a/vendor/integrations/examples/docs/package.json b/vendor/integrations/examples/docs/package.json index d38b92a7..a0e98db3 100644 --- a/vendor/integrations/examples/docs/package.json +++ b/vendor/integrations/examples/docs/package.json @@ -16,8 +16,8 @@ "@rivetkit/rivetkit-wasm": "workspace:*", "@rivetkit/supabase": "workspace:*", "@rivetkit/effect": "workspace:*", - "effect": "4.0.0-beta.66", - "@effect/platform-node": "4.0.0-beta.66", + "effect": "4.0.0", + "@effect/platform-node": "4.0.0", "@ai-sdk/openai": "^3.0.30", "ai": "^6.0.92", "hono": "^4.7.0", diff --git a/vendor/integrations/examples/turso/.gitignore b/vendor/integrations/examples/turso/.gitignore new file mode 100644 index 00000000..806ac366 --- /dev/null +++ b/vendor/integrations/examples/turso/.gitignore @@ -0,0 +1,4 @@ +.actorcore +node_modules +.env +*.db diff --git a/vendor/integrations/examples/turso/README.md b/vendor/integrations/examples/turso/README.md new file mode 100644 index 00000000..11aa5603 --- /dev/null +++ b/vendor/integrations/examples/turso/README.md @@ -0,0 +1,43 @@ +# Turso + +Example project demonstrating a Turso Cloud database per Rivet Actor, created when the actor is created and deleted when it is destroyed. + +## Getting Started + +```sh +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/turso +npm install +cp .env.example .env # fill in your Turso organization and Platform API token +npm run dev +``` + +In another terminal, run the client: + +```sh +npm run client +``` + +## Features + +- **Database per actor**: `createState` creates a Turso database for each actor through the Platform API +- **Live objects in `c.vars`**: `createVars` opens a `@libsql/client` client to the actor's database on every start, and sleep drops it +- **Cleanup on destroy**: `onDestroy` deletes the actor's database + +## Prerequisites + +- A [Turso Cloud](https://turso.tech) organization and a Platform API token from `turso auth api-tokens mint` + +## Implementation + +The `todoList` actor creates its database and a scoped token in `createState`, then opens a client and creates its table in `createVars`. The client uses HTTP, so an idle client holds no connections and is never closed. `deleteList` destroys the actor, which runs `onDestroy`. + +See the implementation in [`src/index.ts`](https://github.com/rivet-dev/rivet/tree/main/examples/turso/src/index.ts) and the test in [`tests/turso.test.ts`](https://github.com/rivet-dev/rivet/tree/main/examples/turso/tests/turso.test.ts). + +## Resources + +Read the [Turso integration guide](https://rivet.dev/integrations/turso), and more about [state](https://rivet.dev/actors/docs/state), [lifecycle hooks](https://rivet.dev/actors/docs/lifecycle), and [destroying actors](https://rivet.dev/actors/docs/destroy). + +## License + +MIT diff --git a/vendor/integrations/examples/turso/package.json b/vendor/integrations/examples/turso/package.json new file mode 100644 index 00000000..c7770146 --- /dev/null +++ b/vendor/integrations/examples/turso/package.json @@ -0,0 +1,31 @@ +{ + "name": "turso", + "version": "2.0.21", + "private": true, + "type": "module", + "scripts": { + "dev": "tsx watch --env-file=.env src/index.ts", + "start": "tsx --env-file=.env src/index.ts", + "client": "tsx scripts/client.ts", + "check-types": "tsc --noEmit", + "test": "vitest run" + }, + "dependencies": { + "@libsql/client": "^0.18.0", + "@tursodatabase/api": "^2.0.5", + "rivetkit": "^2.3.31" + }, + "devDependencies": { + "@types/node": "^22.13.9", + "tsx": "^4.19.0", + "typescript": "^5.5.2", + "vitest": "^3.1.1" + }, + "template": { + "technologies": ["typescript", "turso"], + "tags": ["database"], + "noFrontend": true + }, + "stableVersion": "0.8.0", + "license": "MIT" +} diff --git a/vendor/integrations/examples/turso/scripts/client.ts b/vendor/integrations/examples/turso/scripts/client.ts new file mode 100644 index 00000000..0e9a6642 --- /dev/null +++ b/vendor/integrations/examples/turso/scripts/client.ts @@ -0,0 +1,18 @@ +import { createClient } from "rivetkit/client"; +import type { registry } from "../src/index.ts"; + +const client = createClient({ + endpoint: process.env.RIVET_ENDPOINT ?? "http://localhost:6420", +}); + +// Each key is its own todo list actor with its own Turso client. +const list = client.todoList.getOrCreate(["groceries"]); + +const milk = await list.addTodo("Buy milk"); +await list.addTodo("Buy eggs"); +await list.toggleTodo(milk.id); +console.log("todos:", await list.listTodos()); + +// Destroying the actor deletes its rows from Turso and closes its client. +await list.deleteList(); +console.log("deleted the groceries list"); diff --git a/vendor/integrations/examples/turso/src/index.ts b/vendor/integrations/examples/turso/src/index.ts new file mode 100644 index 00000000..6494d99e --- /dev/null +++ b/vendor/integrations/examples/turso/src/index.ts @@ -0,0 +1,140 @@ +import { createClient as createDatabaseClient } from "@libsql/client"; +import { createClient as createPlatformClient } from "@tursodatabase/api"; +import { actor, setup } from "rivetkit"; + +export type Todo = { + id: number; + title: string; + completed: boolean; + createdAt: number; +}; + +type TodoDatabase = { name: string; url: string; authToken: string }; + +// One Platform API client for the whole process. It creates and deletes +// databases. Each actor queries its own database through c.vars.db. +const turso = createPlatformClient({ + org: requireEnv("TURSO_ORG"), + token: requireEnv("TURSO_PLATFORM_TOKEN"), +}); + +export const todoList = actor({ + // Create this actor's own Turso database once, when the actor is created: + // https://rivet.dev/docs/actors/state + createState: async (c): Promise<{ database: TodoDatabase }> => { + const name = databaseName(c.actorId); + const hostname = await createDatabase(name); + const { jwt } = await turso.databases.createToken(name, { + authorization: "full-access", + }); + return { + database: { name, url: `libsql://${hostname}`, authToken: jwt }, + }; + }, + + // Open a client to this actor's database each time the actor starts. vars + // are never persisted, so live objects like clients belong here: + // https://rivet.dev/docs/actors/state#ephemeral-state + // + // The client is never closed. In Node, a libsql:// URL uses HTTP: each + // statement opens and closes its own stream, so an idle client holds no + // connections, and dropping vars when the actor sleeps releases it. + // close() would reject statements that in-flight actions have not sent yet. + createVars: async (c) => { + const db = createDatabaseClient({ + url: c.state.database.url, + authToken: c.state.database.authToken, + }); + await db.execute(` + CREATE TABLE IF NOT EXISTS todos ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + title TEXT NOT NULL, + completed INTEGER NOT NULL DEFAULT 0, + created_at INTEGER NOT NULL + ) + `); + return { db }; + }, + + // The actor is gone for good, so delete its database too: + // https://rivet.dev/docs/actors/lifecycle#ondestroy + onDestroy: async (c) => { + await turso.databases.delete(c.state.database.name); + }, + + actions: { + // Callable functions from clients: https://rivet.dev/docs/actors/actions + // Each action awaits its statement, so a write is committed before the + // action returns. + addTodo: async (c, title: string): Promise => { + const createdAt = Date.now(); + const result = await c.vars.db.execute({ + sql: "INSERT INTO todos (title, created_at) VALUES (?, ?)", + args: [title, createdAt], + }); + return { + id: Number(result.lastInsertRowid), + title, + completed: false, + createdAt, + }; + }, + + toggleTodo: async (c, id: number) => { + await c.vars.db.execute({ + sql: "UPDATE todos SET completed = NOT completed WHERE id = ?", + args: [id], + }); + }, + + listTodos: async (c): Promise => { + const result = await c.vars.db.execute( + "SELECT id, title, completed, created_at FROM todos ORDER BY id", + ); + return result.rows.map((row) => ({ + id: Number(row.id), + title: String(row.title), + completed: Boolean(row.completed), + createdAt: Number(row.created_at), + })); + }, + + // Destroy the actor, which runs onDestroy: + // https://rivet.dev/docs/actors/destroy + deleteList: (c) => { + c.destroy(); + }, + }, +}); + +// Turso database names allow lowercase letters, digits, and dashes. +export function databaseName(actorId: string): string { + return `todos-${actorId}`.toLowerCase().replace(/[^a-z0-9-]/g, "-"); +} + +// Creates the database, or finds it if a previous attempt to create this +// actor already did. +async function createDatabase(name: string): Promise { + try { + const database = await turso.databases.create(name, { + group: process.env.TURSO_GROUP ?? "default", + }); + return database.hostname; + } catch (error) { + if ((error as { status?: number }).status !== 409) throw error; + return (await turso.databases.get(name)).hostname; + } +} + +function requireEnv(name: string): string { + const value = process.env[name]; + if (!value) throw new Error(`${name} is not set. See .env.example.`); + return value; +} + +// Register actors and start the server: https://rivet.dev/docs/setup +export const registry = setup({ + use: { todoList }, +}); + +registry.start(); diff --git a/vendor/integrations/examples/turso/tests/turso.test.ts b/vendor/integrations/examples/turso/tests/turso.test.ts new file mode 100644 index 00000000..b450c548 --- /dev/null +++ b/vendor/integrations/examples/turso/tests/turso.test.ts @@ -0,0 +1,51 @@ +import { createClient } from "@tursodatabase/api"; +import { setupTest } from "rivetkit/test"; +import { expect, test, vi } from "vitest"; + +// Each actor creates a real Turso database, so this test needs Turso credentials. +test.skipIf(!process.env.TURSO_PLATFORM_TOKEN)( + "each list gets its own database, deleted with the list", + async (ctx) => { + const { registry, databaseName } = await import("../src/index.ts"); + const { client } = await setupTest(ctx, registry); + const turso = createClient({ + org: process.env.TURSO_ORG as string, + token: process.env.TURSO_PLATFORM_TOKEN as string, + }); + + const groceries = client.todoList.getOrCreate(["groceries"]); + const chores = client.todoList.getOrCreate(["chores"]); + const milk = await groceries.addTodo("Buy milk"); + await groceries.addTodo("Buy eggs"); + await chores.addTodo("Do laundry"); + await groceries.toggleTodo(milk.id); + + // Separate databases, so both lists number their rows from 1. + expect(await groceries.listTodos()).toMatchObject([ + { id: 1, title: "Buy milk", completed: true }, + { id: 2, title: "Buy eggs", completed: false }, + ]); + expect(await chores.listTodos()).toMatchObject([ + { id: 1, title: "Do laundry" }, + ]); + + const groceriesDb = databaseName(await groceries.resolve()); + const choresDb = databaseName(await chores.resolve()); + await expect(turso.databases.get(groceriesDb)).resolves.toBeDefined(); + + await groceries.deleteList(); + await chores.deleteList(); + + // Destroy is asynchronous, so poll until onDestroy has deleted both databases. + await vi.waitFor( + async () => { + const names = (await turso.databases.list()).map( + (db) => db.name, + ); + expect(names).not.toContain(groceriesDb); + expect(names).not.toContain(choresDb); + }, + { timeout: 30_000, interval: 1_000 }, + ); + }, +); diff --git a/vendor/integrations/examples/turso/tsconfig.json b/vendor/integrations/examples/turso/tsconfig.json new file mode 100644 index 00000000..5bd6dbd7 --- /dev/null +++ b/vendor/integrations/examples/turso/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "esnext", + "lib": ["esnext"], + "module": "esnext", + "moduleResolution": "bundler", + "types": ["node"], + "noEmit": true, + "strict": true, + "skipLibCheck": true, + "allowImportingTsExtensions": true, + "rewriteRelativeImportExtensions": true + }, + "include": ["src/**/*", "scripts/**/*", "tests/**/*"] +} diff --git a/vendor/integrations/examples/turso/turbo.json b/vendor/integrations/examples/turso/turbo.json new file mode 100644 index 00000000..29d4cb26 --- /dev/null +++ b/vendor/integrations/examples/turso/turbo.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://turbo.build/schema.json", + "extends": ["//"] +} diff --git a/vendor/integrations/examples/turso/vitest.config.ts b/vendor/integrations/examples/turso/vitest.config.ts new file mode 100644 index 00000000..63d4d87d --- /dev/null +++ b/vendor/integrations/examples/turso/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + include: ["tests/**/*.test.ts"], + // Creating and deleting Turso databases takes a few seconds. + testTimeout: 60_000, + }, +});