Skip to content
This repository was archived by the owner on Oct 22, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions packages/core/fixtures/driver-test-suite/action-inputs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { actor } from "@rivetkit/core";

export interface State {
initialInput?: unknown;
onCreateInput?: unknown;
}

// Test actor that can capture input during creation
export const inputActor = actor({
onAuth: () => {},
createState: (c, input): State => {
return {
initialInput: input,
onCreateInput: undefined,
};
},

onCreate: (c, input) => {
c.state.onCreateInput = input;
},

actions: {
getInputs: (c) => {
return {
initialInput: c.state.initialInput,
onCreateInput: c.state.onCreateInput,
};
},
},
});
68 changes: 68 additions & 0 deletions packages/core/fixtures/driver-test-suite/action-timeout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { actor } from "@rivetkit/core";

// Short timeout actor
export const shortTimeoutActor = actor({
onAuth: () => {},
state: { value: 0 },
options: {
action: {
timeout: 50, // 50ms timeout
},
},
actions: {
quickAction: async (c) => {
return "quick response";
},
slowAction: async (c) => {
// This action should timeout
await new Promise((resolve) => setTimeout(resolve, 100));
return "slow response";
},
},
});

// Long timeout actor
export const longTimeoutActor = actor({
onAuth: () => {},
state: { value: 0 },
options: {
action: {
timeout: 200, // 200ms timeout
},
},
actions: {
delayedAction: async (c) => {
// This action should complete within timeout
await new Promise((resolve) => setTimeout(resolve, 100));
return "delayed response";
},
},
});

// Default timeout actor
export const defaultTimeoutActor = actor({
onAuth: () => {},
state: { value: 0 },
actions: {
normalAction: async (c) => {
await new Promise((resolve) => setTimeout(resolve, 50));
return "normal response";
},
},
});

// Sync actor (timeout shouldn't apply)
export const syncTimeoutActor = actor({
onAuth: () => {},
state: { value: 0 },
options: {
action: {
timeout: 50, // 50ms timeout
},
},
actions: {
syncAction: (c) => {
return "sync response";
},
},
});
85 changes: 85 additions & 0 deletions packages/core/fixtures/driver-test-suite/action-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { actor, UserError } from "@rivetkit/core";

// Actor with synchronous actions
export const syncActionActor = actor({
onAuth: () => {},
state: { value: 0 },
actions: {
// Simple synchronous action that returns a value directly
increment: (c, amount = 1) => {
c.state.value += amount;
return c.state.value;
},
// Synchronous action that returns an object
getInfo: (c) => {
return {
currentValue: c.state.value,
timestamp: Date.now(),
};
},
// Synchronous action with no return value (void)
reset: (c) => {
c.state.value = 0;
},
},
});

// Actor with asynchronous actions
export const asyncActionActor = actor({
onAuth: () => {},
state: { value: 0, data: null as any },
actions: {
// Async action with a delay
delayedIncrement: async (c, amount = 1) => {
await Promise.resolve();
c.state.value += amount;
return c.state.value;
},
// Async action that simulates an API call
fetchData: async (c, id: string) => {
await Promise.resolve();

// Simulate response data
const data = { id, timestamp: Date.now() };
c.state.data = data;
return data;
},
// Async action with error handling
asyncWithError: async (c, shouldError: boolean) => {
await Promise.resolve();

if (shouldError) {
throw new UserError("Intentional error");
}

return "Success";
},
},
});

// Actor with promise actions
export const promiseActor = actor({
onAuth: () => {},
state: { results: [] as string[] },
actions: {
// Action that returns a resolved promise
resolvedPromise: (c) => {
return Promise.resolve("resolved value");
},
// Action that returns a promise that resolves after a delay
delayedPromise: (c): Promise<string> => {
return new Promise<string>((resolve) => {
c.state.results.push("delayed");
resolve("delayed value");
});
},
// Action that returns a rejected promise
rejectedPromise: (c) => {
return Promise.reject(new UserError("promised rejection"));
},
// Action to check the collected results
getResults: (c) => {
return c.state.results;
},
},
});
103 changes: 103 additions & 0 deletions packages/core/fixtures/driver-test-suite/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { actor, UserError } from "@rivetkit/core";

// Basic auth actor - requires API key
export const authActor = actor({
state: { requests: 0 },
onAuth: (opts, params: { apiKey?: string } | undefined) => {
const apiKey = params?.apiKey;
if (!apiKey) {
throw new UserError("API key required", { code: "missing_auth" });
}

if (apiKey !== "valid-api-key") {
throw new UserError("Invalid API key", { code: "invalid_auth" });
}

return { userId: "user123", token: apiKey };
},
actions: {
getRequests: (c) => {
c.state.requests++;
return c.state.requests;
},
getUserAuth: (c) => c.conn.auth,
},
});

// Intent-specific auth actor - checks different permissions for different intents
export const intentAuthActor = actor({
state: { value: 0 },
onAuth: ({ request, intents }, params: { role: string }) => {
console.log("intents", intents, params);
const role = params.role;

if (intents.has("create") && role !== "admin") {
throw new UserError("Admin role required for create operations", {
code: "insufficient_permissions",
});
}

if (intents.has("action") && !["admin", "user"].includes(role || "")) {
throw new UserError("User or admin role required for actions", {
code: "insufficient_permissions",
});
}

return { role, timestamp: Date.now() };
},
actions: {
getValue: (c) => c.state.value,
setValue: (c, value: number) => {
c.state.value = value;
return value;
},
getAuth: (c) => c.conn.auth,
},
});

// Public actor - empty onAuth to allow public access
export const publicActor = actor({
state: { visitors: 0 },
onAuth: () => {
return null; // Allow public access
},
actions: {
visit: (c) => {
c.state.visitors++;
return c.state.visitors;
},
},
});

// No auth actor - should fail when accessed publicly (no onAuth defined)
export const noAuthActor = actor({
state: { value: 42 },
actions: {
getValue: (c) => c.state.value,
},
});

// Async auth actor - tests promise-based authentication
export const asyncAuthActor = actor({
state: { count: 0 },
onAuth: async (opts, params: { token?: string } | undefined) => {
const token = params?.token;
if (!token) {
throw new UserError("Token required", { code: "missing_token" });
}

// Simulate token validation
if (token === "invalid") {
throw new UserError("Token is invalid", { code: "invalid_token" });
}

return { userId: `user-${token}`, validated: true };
},
actions: {
increment: (c) => {
c.state.count++;
return c.state.count;
},
getAuthData: (c) => c.conn.auth,
},
});
52 changes: 52 additions & 0 deletions packages/core/fixtures/driver-test-suite/conn-liveness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { actor, CONNECTION_DRIVER_WEBSOCKET } from "@rivetkit/core";

export const connLivenessActor = actor({
onAuth: () => {},
state: {
counter: 0,
acceptingConnections: true,
},
options: {
lifecycle: {
connectionLivenessInterval: 5_000,
connectionLivenessTimeout: 2_500,
},
},
onConnect: (c, conn) => {
if (!c.state.acceptingConnections) {
conn.disconnect();
throw new Error("Actor is not accepting connections");
}
},
actions: {
getWsConnectionsLiveness: (c) => {
return Array.from(c.conns.values())
.filter((conn) => conn.driver === CONNECTION_DRIVER_WEBSOCKET)
.map((conn) => ({
id: conn.id,
status: conn.status,
lastSeen: conn.lastSeen,
}));
},
getConnectionId: (c) => {
return c.conn.id;
},
kill: (c, connId: string) => {
c.state.acceptingConnections = false;
// Disconnect the connection with the given ID
// This simulates a network failure or a manual disconnection
// The connection will be cleaned up by the actor manager after the timeout
const conn = c.conns.get(connId);
if (conn) {
conn.disconnect();
}
},
getCounter: (c) => {
return c.state.counter;
},
increment: (c, amount: number) => {
c.state.counter += amount;
return c.state.counter;
},
},
});
28 changes: 28 additions & 0 deletions packages/core/fixtures/driver-test-suite/conn-params.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { actor } from "@rivetkit/core";

export const counterWithParams = actor({
onAuth: () => {},
state: { count: 0, initializers: [] as string[] },
createConnState: (c, opts, params: { name?: string }) => {
return {
name: params.name || "anonymous",
};
},
onConnect: (c, conn) => {
// Record connection name
c.state.initializers.push(conn.state.name);
},
actions: {
increment: (c, x: number) => {
c.state.count += x;
c.broadcast("newCount", {
count: c.state.count,
by: c.conn.state.name,
});
return c.state.count;
},
getInitializers: (c) => {
return c.state.initializers;
},
},
});
Loading
Loading