@rivetkit/core
Version:
1,138 lines (1,099 loc) • 164 kB
JavaScript
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
var _chunk5YH3BFI6cjs = require('../chunk-5YH3BFI6.cjs');
var _chunkAXTFLZYFcjs = require('../chunk-AXTFLZYF.cjs');
require('../chunk-MDVDLD3K.cjs');
var _chunkZCUB7MR5cjs = require('../chunk-ZCUB7MR5.cjs');
var _chunkQAYICQKZcjs = require('../chunk-QAYICQKZ.cjs');
var _chunkDSGTB57Jcjs = require('../chunk-DSGTB57J.cjs');
var _chunkOBXZ7YJ7cjs = require('../chunk-OBXZ7YJ7.cjs');
require('../chunk-ON577KND.cjs');
var _chunk4KRNEW7Dcjs = require('../chunk-4KRNEW7D.cjs');
require('../chunk-HIB3AS73.cjs');
var _chunk53LWTTEXcjs = require('../chunk-53LWTTEX.cjs');
// src/driver-test-suite/mod.ts
var _nodeserver = require('@hono/node-server');
var _nodews = require('@hono/node-ws');
var _bundlerequire = require('bundle-require');
var _invariant = require('invariant'); var _invariant2 = _interopRequireDefault(_invariant);
var _vitest = require('vitest');
// src/driver-test-suite/tests/action-features.ts
// src/driver-test-suite/utils.ts
var _path = require('path');
// src/driver-test-suite/test-inline-client-driver.ts
var _cborx = require('cbor-x'); var cbor = _interopRequireWildcard(_cborx);
// src/driver-test-suite/log.ts
var LOGGER_NAME = "test-suite";
function logger() {
return _chunk4KRNEW7Dcjs.getLogger.call(void 0, LOGGER_NAME);
}
// src/driver-test-suite/test-inline-client-driver.ts
function createTestInlineClientDriver(endpoint, transport) {
return {
action: async (c, actorQuery, encoding, params, name, args) => {
return makeInlineRequest(
endpoint,
encoding,
transport,
"action",
[void 0, actorQuery, encoding, params, name, args]
);
},
resolveActorId: async (c, actorQuery, encodingKind, params) => {
return makeInlineRequest(
endpoint,
encodingKind,
transport,
"resolveActorId",
[void 0, actorQuery, encodingKind, params]
);
},
connectWebSocket: async (c, actorQuery, encodingKind, params) => {
const WebSocket2 = await _chunkQAYICQKZcjs.importWebSocket.call(void 0, );
logger().debug("creating websocket connection via test inline driver", {
actorQuery,
encodingKind
});
const wsUrl = new URL(
`${endpoint}/registry/.test/inline-driver/connect-websocket`
);
wsUrl.searchParams.set("actorQuery", JSON.stringify(actorQuery));
if (params !== void 0)
wsUrl.searchParams.set("params", JSON.stringify(params));
wsUrl.searchParams.set("encodingKind", encodingKind);
const wsProtocol = wsUrl.protocol === "https:" ? "wss:" : "ws:";
const finalWsUrl = `${wsProtocol}//${wsUrl.host}${wsUrl.pathname}${wsUrl.search}`;
logger().debug("connecting to websocket", { url: finalWsUrl });
const ws = new WebSocket2(finalWsUrl, [
// HACK: See packages/drivers/cloudflare-workers/src/websocket.ts
"rivetkit"
]);
return ws;
},
connectSse: async (c, actorQuery, encodingKind, params) => {
logger().debug("creating sse connection via test inline driver", {
actorQuery,
encodingKind,
params
});
const EventSourceImport = await Promise.resolve().then(() => _interopRequireWildcard(require("eventsource")));
const EventSourceConstructor = EventSourceImport.default || EventSourceImport;
const actorQueryParam = encodeURIComponent(JSON.stringify(actorQuery));
const encodingParam = encodeURIComponent(encodingKind);
const paramsParam = params ? encodeURIComponent(JSON.stringify(params)) : null;
const sseUrl = new URL(
`${endpoint}/registry/.test/inline-driver/connect-sse`
);
sseUrl.searchParams.set("actorQueryRaw", actorQueryParam);
sseUrl.searchParams.set("encodingKind", encodingParam);
if (paramsParam) {
sseUrl.searchParams.set("params", paramsParam);
}
logger().debug("connecting to sse", { url: sseUrl.toString() });
const eventSource = new EventSourceConstructor(sseUrl.toString());
await new Promise((resolve2, reject) => {
eventSource.onopen = () => {
logger().debug("sse connection established");
resolve2();
};
eventSource.onerror = (event) => {
logger().error("sse connection failed", { event });
reject(new Error("Failed to establish SSE connection"));
};
setTimeout(() => {
if (eventSource.readyState !== EventSourceConstructor.OPEN) {
reject(new Error("SSE connection timed out"));
}
}, 1e4);
});
return eventSource;
},
sendHttpMessage: async (c, actorId, encoding, connectionId, connectionToken, message) => {
logger().debug("sending http message via test inline driver", {
actorId,
encoding,
connectionId,
transport
});
const result = await fetch(
`${endpoint}/registry/.test/inline-driver/call`,
{
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
encoding,
transport,
method: "sendHttpMessage",
args: [
void 0,
actorId,
encoding,
connectionId,
connectionToken,
message
]
})
}
);
if (!result.ok) {
throw new Error(`Failed to send HTTP message: ${result.statusText}`);
}
return new Response(await result.text(), {
status: result.status,
statusText: result.statusText,
headers: result.headers
});
},
rawHttpRequest: async (c, actorQuery, encoding, params, path, init) => {
var _a;
const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
logger().debug("sending raw http request via test inline driver", {
actorQuery,
encoding,
path: normalizedPath
});
const url = `${endpoint}/registry/.test/inline-driver/raw-http/${normalizedPath}`;
logger().debug("rewriting http url", {
from: path,
to: url
});
const headers = new Headers(init.headers);
headers.set(_chunkOBXZ7YJ7cjs.HEADER_ACTOR_QUERY, JSON.stringify(actorQuery));
headers.set(_chunkOBXZ7YJ7cjs.HEADER_ENCODING, encoding);
if (params !== void 0) {
headers.set(_chunkOBXZ7YJ7cjs.HEADER_CONN_PARAMS, JSON.stringify(params));
}
const response = await fetch(url, {
...init,
headers
});
if (!response.ok && ((_a = response.headers.get("content-type")) == null ? void 0 : _a.includes("application/json"))) {
try {
const clonedResponse = response.clone();
const errorData = await clonedResponse.json();
if (errorData.error) {
if (typeof errorData.error === "object") {
throw new (0, _chunkDSGTB57Jcjs.ActorError)(
errorData.error.code,
errorData.error.message,
errorData.error.metadata
);
}
}
} catch (e) {
if (!(e instanceof _chunkDSGTB57Jcjs.ActorError)) {
return response;
}
throw e;
}
}
return response;
},
rawWebSocket: async (_c, actorQuery, encoding, params, path, protocols) => {
logger().debug("test inline driver rawWebSocket called");
const WebSocket2 = await _chunkQAYICQKZcjs.importWebSocket.call(void 0, );
const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
logger().debug(
"creating raw websocket connection via test inline driver",
{
actorQuery,
encoding,
path: normalizedPath,
protocols
}
);
const wsUrl = new URL(
`${endpoint}/registry/.test/inline-driver/raw-websocket`
);
wsUrl.searchParams.set("actorQuery", JSON.stringify(actorQuery));
if (params !== void 0)
wsUrl.searchParams.set("params", JSON.stringify(params));
wsUrl.searchParams.set("encodingKind", encoding);
wsUrl.searchParams.set("path", normalizedPath);
if (protocols !== void 0)
wsUrl.searchParams.set("protocols", JSON.stringify(protocols));
const wsProtocol = wsUrl.protocol === "https:" ? "wss:" : "ws:";
const finalWsUrl = `${wsProtocol}//${wsUrl.host}${wsUrl.pathname}${wsUrl.search}`;
logger().debug("connecting to raw websocket", { url: finalWsUrl });
logger().debug("rewriting websocket url", {
from: path,
to: finalWsUrl
});
const ws = new WebSocket2(finalWsUrl, [
// HACK: See packages/drivers/cloudflare-workers/src/websocket.ts
"rivetkit"
]);
logger().debug("test inline driver created websocket", {
readyState: ws.readyState,
url: ws.url
});
return ws;
}
};
}
async function makeInlineRequest(endpoint, encoding, transport, method, args) {
logger().debug("sending inline request", {
encoding,
transport,
method,
args
});
const response = await fetch(
`${endpoint}/registry/.test/inline-driver/call`,
{
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: cbor.encode({
encoding,
transport,
method,
args
})
}
);
if (!response.ok) {
throw new Error(`Failed to call inline ${method}: ${response.statusText}`);
}
const buffer = await response.arrayBuffer();
const callResponse = cbor.decode(
new Uint8Array(buffer)
);
if ("ok" in callResponse) {
return callResponse.ok;
} else if ("err" in callResponse) {
throw new (0, _chunkDSGTB57Jcjs.ActorError)(
callResponse.err.code,
callResponse.err.message,
callResponse.err.metadata
);
} else {
_chunkOBXZ7YJ7cjs.assertUnreachable.call(void 0, callResponse);
}
}
// src/driver-test-suite/utils.ts
async function setupDriverTest(c, driverTestConfig) {
if (!driverTestConfig.useRealTimers) {
_vitest.vi.useFakeTimers();
}
const projectPath = _path.resolve.call(void 0, __dirname, "../../fixtures/driver-test-suite");
const { endpoint, cleanup } = await driverTestConfig.start(projectPath);
c.onTestFinished(cleanup);
let client;
if (driverTestConfig.clientType === "http") {
client = _chunkZCUB7MR5cjs.createClient.call(void 0, endpoint, {
transport: driverTestConfig.transport
});
} else if (driverTestConfig.clientType === "inline") {
const clientDriver = createTestInlineClientDriver(
endpoint,
_nullishCoalesce(driverTestConfig.transport, () => ( "websocket"))
);
client = _chunkDSGTB57Jcjs.createClientWithDriver.call(void 0, clientDriver);
} else {
_chunkOBXZ7YJ7cjs.assertUnreachable.call(void 0, driverTestConfig.clientType);
}
if (!driverTestConfig.HACK_skipCleanupNet) {
c.onTestFinished(async () => await client.dispose());
}
return {
client,
endpoint
};
}
async function waitFor(driverTestConfig, ms) {
if (driverTestConfig.useRealTimers) {
return new Promise((resolve2) => setTimeout(resolve2, ms));
} else {
_vitest.vi.advanceTimersByTime(ms);
return Promise.resolve();
}
}
// src/driver-test-suite/tests/action-features.ts
function runActionFeaturesTests(driverTestConfig) {
_vitest.describe.call(void 0, "Action Features", () => {
_vitest.describe.skip("Action Timeouts", () => {
const usesFakeTimers = !driverTestConfig.useRealTimers;
_vitest.test.call(void 0, "should timeout actions that exceed the configured timeout", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const quickResult = await client.shortTimeoutActor.getOrCreate().quickAction();
_vitest.expect.call(void 0, quickResult).toBe("quick response");
await _vitest.expect.call(void 0,
client.shortTimeoutActor.getOrCreate().slowAction()
).rejects.toThrow("Action timed out");
});
_vitest.test.call(void 0, "should respect the default timeout", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const result = await client.defaultTimeoutActor.getOrCreate().normalAction();
_vitest.expect.call(void 0, result).toBe("normal response");
});
_vitest.test.call(void 0, "non-promise action results should not be affected by timeout", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const result = await client.syncTimeoutActor.getOrCreate().syncAction();
_vitest.expect.call(void 0, result).toBe("sync response");
});
_vitest.test.call(void 0, "should allow configuring different timeouts for different actors", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
await _vitest.expect.call(void 0,
client.shortTimeoutActor.getOrCreate().slowAction()
).rejects.toThrow("Action timed out");
const result = await client.longTimeoutActor.getOrCreate().delayedAction();
_vitest.expect.call(void 0, result).toBe("delayed response");
});
});
_vitest.describe.call(void 0, "Action Sync & Async", () => {
_vitest.test.call(void 0, "should support synchronous actions", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.syncActionActor.getOrCreate();
let result = await instance.increment(5);
_vitest.expect.call(void 0, result).toBe(5);
result = await instance.increment(3);
_vitest.expect.call(void 0, result).toBe(8);
const info = await instance.getInfo();
_vitest.expect.call(void 0, info.currentValue).toBe(8);
_vitest.expect.call(void 0, typeof info.timestamp).toBe("number");
await instance.reset();
result = await instance.increment(0);
_vitest.expect.call(void 0, result).toBe(0);
});
_vitest.test.call(void 0, "should support asynchronous actions", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.asyncActionActor.getOrCreate();
const result = await instance.delayedIncrement(5);
_vitest.expect.call(void 0, result).toBe(5);
const data = await instance.fetchData("test-123");
_vitest.expect.call(void 0, data.id).toBe("test-123");
_vitest.expect.call(void 0, typeof data.timestamp).toBe("number");
const success = await instance.asyncWithError(false);
_vitest.expect.call(void 0, success).toBe("Success");
try {
await instance.asyncWithError(true);
_vitest.expect.fail("did not error");
} catch (error) {
_vitest.expect.call(void 0, error.message).toBe("Intentional error");
}
});
_vitest.test.call(void 0, "should handle promises returned from actions correctly", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.promiseActor.getOrCreate();
const resolvedValue = await instance.resolvedPromise();
_vitest.expect.call(void 0, resolvedValue).toBe("resolved value");
const delayedValue = await instance.delayedPromise();
_vitest.expect.call(void 0, delayedValue).toBe("delayed value");
await _vitest.expect.call(void 0, instance.rejectedPromise()).rejects.toThrow(
"promised rejection"
);
const results = await instance.getResults();
_vitest.expect.call(void 0, results).toContain("delayed");
});
});
});
}
// src/driver-test-suite/tests/actor-auth.ts
function runActorAuthTests(driverTestConfig) {
_vitest.describe.call(void 0, "Actor Authentication Tests", () => {
_vitest.describe.call(void 0, "Basic Authentication", () => {
_vitest.test.call(void 0, "should allow access with valid auth", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.authActor.getOrCreate(void 0, {
params: { apiKey: "valid-api-key" }
});
const authData = await instance.getUserAuth();
if (driverTestConfig.clientType === "inline") {
_vitest.expect.call(void 0, authData).toBeUndefined();
} else {
_vitest.expect.call(void 0, authData).toEqual({
userId: "user123",
token: "valid-api-key"
});
}
const requests = await instance.getRequests();
_vitest.expect.call(void 0, requests).toBe(1);
});
_vitest.test.call(void 0, "should deny access with invalid auth", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.authActor.getOrCreate();
if (driverTestConfig.clientType === "inline") {
const requests = await instance.getRequests();
_vitest.expect.call(void 0, typeof requests).toBe("number");
} else {
try {
await instance.getRequests();
_vitest.expect.fail("Expected authentication error");
} catch (error) {
_vitest.expect.call(void 0, error.code).toBe("missing_auth");
}
}
});
_vitest.test.call(void 0, "should expose auth data on connection", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.authActor.getOrCreate(void 0, {
params: { apiKey: "valid-api-key" }
});
const authData = await instance.getUserAuth();
if (driverTestConfig.clientType === "inline") {
_vitest.expect.call(void 0, authData).toBeUndefined();
} else {
_vitest.expect.call(void 0, authData).toBeDefined();
_vitest.expect.call(void 0, authData.userId).toBe("user123");
_vitest.expect.call(void 0, authData.token).toBe("valid-api-key");
}
});
});
_vitest.describe.call(void 0, "Intent-Based Authentication", () => {
_vitest.test.call(void 0, "should allow get operations for any role", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const createdInstance = await client.intentAuthActor.create(["foo"], {
params: { role: "admin" }
});
const actorId = await createdInstance.resolve();
if (driverTestConfig.clientType === "inline") {
const instance = client.intentAuthActor.getForId(actorId);
const value = await instance.getValue();
_vitest.expect.call(void 0, value).toBe(0);
} else {
const instance = client.intentAuthActor.getForId(actorId, {
params: { role: "user" }
// Actions require user or admin role
});
const value = await instance.getValue();
_vitest.expect.call(void 0, value).toBe(0);
}
});
_vitest.test.call(void 0, "should require admin role for create operations", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
if (driverTestConfig.clientType === "inline") {
const instance = client.intentAuthActor.getOrCreate(void 0, {
params: { role: "user" }
});
const value = await instance.getValue();
_vitest.expect.call(void 0, value).toBe(0);
} else {
try {
const instance = client.intentAuthActor.getOrCreate(void 0, {
params: { role: "user" }
});
await instance.getValue();
_vitest.expect.fail("Expected permission error for create operation");
} catch (error) {
_vitest.expect.call(void 0, error.code).toBe("insufficient_permissions");
_vitest.expect.call(void 0, error.message).toContain(
"Admin role required"
);
}
}
});
_vitest.test.call(void 0, "should allow actions for user and admin roles", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const createdInstance = await client.intentAuthActor.create(["foo"], {
params: { role: "admin" }
});
const actorId = await createdInstance.resolve();
const instance = client.intentAuthActor.getForId(actorId, {
params: { role: "guest" }
});
if (driverTestConfig.clientType === "inline") {
const result = await instance.setValue(42);
_vitest.expect.call(void 0, result).toBe(42);
} else {
try {
await instance.setValue(42);
_vitest.expect.fail("Expected permission error for action");
} catch (error) {
_vitest.expect.call(void 0, error.code).toBe("insufficient_permissions");
_vitest.expect.call(void 0, error.message).toContain(
"User or admin role required"
);
}
}
});
});
_vitest.describe.call(void 0, "Public Access", () => {
_vitest.test.call(void 0, "should allow access with empty onAuth", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.publicActor.getOrCreate();
const visitors = await instance.visit();
_vitest.expect.call(void 0, visitors).toBe(1);
const visitors2 = await instance.visit();
_vitest.expect.call(void 0, visitors2).toBe(2);
});
_vitest.test.call(void 0, "should deny access without onAuth defined", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.noAuthActor.getOrCreate();
if (driverTestConfig.clientType === "inline") {
const value = await instance.getValue();
_vitest.expect.call(void 0, value).toBe(42);
} else {
try {
await instance.getValue();
_vitest.expect.fail(
"Expected access to be denied for actor without onAuth"
);
} catch (error) {
_vitest.expect.call(void 0, error.code).toBe("forbidden");
}
}
});
});
_vitest.describe.call(void 0, "Async Authentication", () => {
_vitest.test.call(void 0, "should handle promise-based auth", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.asyncAuthActor.getOrCreate(void 0, {
params: { token: "valid" }
});
const result = await instance.increment();
_vitest.expect.call(void 0, result).toBe(1);
const authData = await instance.getAuthData();
if (driverTestConfig.clientType === "inline") {
_vitest.expect.call(void 0, authData).toBeUndefined();
} else {
_vitest.expect.call(void 0, authData).toBeDefined();
_vitest.expect.call(void 0, authData.userId).toBe("user-valid");
_vitest.expect.call(void 0, authData.validated).toBe(true);
}
});
_vitest.test.call(void 0, "should handle async auth failures", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.asyncAuthActor.getOrCreate();
if (driverTestConfig.clientType === "inline") {
const result = await instance.increment();
_vitest.expect.call(void 0, result).toBe(1);
} else {
try {
await instance.increment();
_vitest.expect.fail("Expected async auth failure");
} catch (error) {
_vitest.expect.call(void 0, error.code).toBe("missing_token");
}
}
});
});
_vitest.describe.call(void 0, "Authentication Across Transports", () => {
if (driverTestConfig.transport === "websocket") {
_vitest.test.call(void 0, "should authenticate WebSocket connections", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.authActor.getOrCreate(void 0, {
params: { apiKey: "valid-api-key" }
});
const authData = await instance.getUserAuth();
_vitest.expect.call(void 0, authData).toBeDefined();
_vitest.expect.call(void 0, authData.userId).toBe("user123");
});
}
_vitest.test.call(void 0, "should authenticate HTTP actions", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.authActor.getOrCreate(void 0, {
params: { apiKey: "valid-api-key" }
});
const requests = await instance.getRequests();
_vitest.expect.call(void 0, typeof requests).toBe("number");
});
});
_vitest.describe.call(void 0, "Error Handling", () => {
_vitest.test.call(void 0, "should handle auth errors gracefully", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.authActor.getOrCreate();
if (driverTestConfig.clientType === "inline") {
const requests = await instance.getRequests();
_vitest.expect.call(void 0, typeof requests).toBe("number");
} else {
try {
await instance.getRequests();
_vitest.expect.fail("Expected authentication error");
} catch (error) {
const actorError = error;
_vitest.expect.call(void 0, actorError.code).toBeDefined();
_vitest.expect.call(void 0, actorError.message).toBeDefined();
}
}
});
_vitest.test.call(void 0, "should preserve error details for debugging", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.asyncAuthActor.getOrCreate();
if (driverTestConfig.clientType === "inline") {
const result = await instance.increment();
_vitest.expect.call(void 0, result).toBe(1);
} else {
try {
await instance.increment();
_vitest.expect.fail("Expected token error");
} catch (error) {
const actorError = error;
_vitest.expect.call(void 0, actorError.code).toBe("missing_token");
_vitest.expect.call(void 0, actorError.message).toBe("Token required");
}
}
});
});
_vitest.describe.call(void 0, "Raw HTTP Authentication", () => {
_vitest.test.call(void 0, "should allow raw HTTP access with valid auth", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.rawHttpAuthActor.getOrCreate(void 0, {
params: { apiKey: "valid-api-key" }
});
const response = await instance.fetch("api/auth-info");
_vitest.expect.call(void 0, response.ok).toBe(true);
const data = await response.json();
_vitest.expect.call(void 0, data.message).toBe("Authenticated request");
_vitest.expect.call(void 0, data.requestCount).toBe(1);
const count = await instance.getRequestCount();
_vitest.expect.call(void 0, count).toBe(1);
});
_vitest.test.call(void 0, "should deny raw HTTP access without auth", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.rawHttpAuthActor.getOrCreate();
const response = await instance.fetch("api/protected");
if (driverTestConfig.clientType === "inline") {
_vitest.expect.call(void 0, response.ok).toBe(true);
_vitest.expect.call(void 0, response.status).toBe(200);
} else {
_vitest.expect.call(void 0, response.ok).toBe(false);
_vitest.expect.call(void 0, response.status).toBe(400);
}
try {
const errorData = await response.json();
_vitest.expect.call(void 0, errorData.c || errorData.code).toBe("missing_auth");
} catch (e2) {
}
});
_vitest.test.call(void 0, "should deny raw HTTP for actors without onAuth", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.rawHttpNoAuthActor.getOrCreate();
const response = await instance.fetch("api/test");
if (driverTestConfig.clientType === "inline") {
_vitest.expect.call(void 0, response.ok).toBe(true);
_vitest.expect.call(void 0, response.status).toBe(200);
} else {
_vitest.expect.call(void 0, response.ok).toBe(false);
_vitest.expect.call(void 0, response.status).toBe(403);
}
try {
const errorData = await response.json();
_vitest.expect.call(void 0, errorData.c || errorData.code).toBe("forbidden");
} catch (e3) {
}
});
_vitest.test.call(void 0, "should allow public raw HTTP access", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.rawHttpPublicActor.getOrCreate();
const response = await instance.fetch("api/visit");
_vitest.expect.call(void 0, response.ok).toBe(true);
const data = await response.json();
_vitest.expect.call(void 0, data.message).toBe("Welcome visitor!");
_vitest.expect.call(void 0, data.count).toBe(1);
const response2 = await instance.fetch("api/visit");
const data2 = await response2.json();
_vitest.expect.call(void 0, data2.count).toBe(2);
});
_vitest.test.call(void 0, "should handle custom auth in onFetch", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.rawHttpCustomAuthActor.getOrCreate();
const response1 = await instance.fetch("api/data");
_vitest.expect.call(void 0, response1.ok).toBe(false);
_vitest.expect.call(void 0, response1.status).toBe(401);
const error1 = await response1.json();
_vitest.expect.call(void 0, error1.error).toBe("Unauthorized");
const response2 = await instance.fetch("api/data", {
headers: {
Authorization: "Bearer wrong-token"
}
});
_vitest.expect.call(void 0, response2.ok).toBe(false);
_vitest.expect.call(void 0, response2.status).toBe(403);
const response3 = await instance.fetch("api/data", {
headers: {
Authorization: "Bearer custom-token"
}
});
_vitest.expect.call(void 0, response3.ok).toBe(true);
const data = await response3.json();
_vitest.expect.call(void 0, data.message).toBe("Authorized!");
_vitest.expect.call(void 0, data.authorized).toBe(1);
const stats = await instance.getStats();
_vitest.expect.call(void 0, stats.authorized).toBe(1);
_vitest.expect.call(void 0, stats.unauthorized).toBe(2);
});
});
_vitest.describe.call(void 0, "Raw WebSocket Authentication", () => {
_vitest.test.call(void 0, "should allow raw WebSocket access with valid auth", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.rawWebSocketAuthActor.getOrCreate(void 0, {
params: { apiKey: "valid-api-key" }
});
const ws = await instance.websocket();
const welcomePromise = new Promise((resolve2, reject) => {
ws.addEventListener("message", (event) => {
const data = JSON.parse(event.data);
if (data.type === "welcome") {
resolve2(data);
}
});
ws.addEventListener("close", () => reject("closed"));
});
const welcomeData = await welcomePromise;
_vitest.expect.call(void 0, welcomeData.message).toBe("Authenticated WebSocket connection");
_vitest.expect.call(void 0, welcomeData.connectionCount).toBe(1);
ws.close();
});
_vitest.test.call(void 0, "should deny raw WebSocket access without auth", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.rawWebSocketAuthActor.getOrCreate();
try {
await instance.websocket();
_vitest.expect.fail("Expected authentication error");
} catch (error) {
_vitest.expect.call(void 0, error).toBeDefined();
}
});
_vitest.test.call(void 0, "should deny raw WebSocket for actors without onAuth", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.rawWebSocketNoAuthActor.getOrCreate();
try {
await instance.websocket();
_vitest.expect.fail("Expected forbidden error");
} catch (error) {
_vitest.expect.call(void 0, error).toBeDefined();
}
});
_vitest.test.call(void 0, "should allow public raw WebSocket access", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.rawWebSocketPublicActor.getOrCreate();
const ws = await instance.websocket();
const welcomePromise = new Promise((resolve2, reject) => {
ws.addEventListener("message", (event) => {
const data = JSON.parse(event.data);
if (data.type === "welcome") {
resolve2(data);
}
});
ws.addEventListener("close", reject);
});
const welcomeData = await welcomePromise;
_vitest.expect.call(void 0, welcomeData.message).toBe("Public WebSocket connection");
_vitest.expect.call(void 0, welcomeData.visitorNumber).toBe(1);
ws.close();
});
_vitest.test.call(void 0, "should handle custom auth in onWebSocket", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const instance = client.rawWebSocketCustomAuthActor.getOrCreate();
try {
const ws1 = await instance.websocket();
const errorPromise = new Promise((resolve2, reject) => {
ws1.addEventListener("message", (event) => {
const data = JSON.parse(event.data);
if (data.type === "error") {
resolve2(data);
}
});
ws1.addEventListener("close", reject);
});
const errorData = await errorPromise;
_vitest.expect.call(void 0, errorData.type).toBe("error");
_vitest.expect.call(void 0, errorData.message).toBe("Unauthorized");
} catch (error) {
_vitest.expect.call(void 0, error).toBeDefined();
}
const ws2 = await instance.websocket("?token=custom-ws-token");
const authPromise = new Promise((resolve2, reject) => {
ws2.addEventListener("message", (event) => {
const data = JSON.parse(event.data);
if (data.type === "authorized") {
resolve2(data);
}
});
ws2.addEventListener("close", reject);
});
const authData = await authPromise;
_vitest.expect.call(void 0, authData.message).toBe("Welcome authenticated user!");
ws2.close();
const stats = await instance.getStats();
_vitest.expect.call(void 0, stats.authorized).toBeGreaterThanOrEqual(1);
_vitest.expect.call(void 0, stats.unauthorized).toBeGreaterThanOrEqual(1);
});
});
});
}
// src/driver-test-suite/tests/actor-conn.ts
function runActorConnTests(driverTestConfig) {
_vitest.describe.call(void 0, "Actor Connection Tests", () => {
_vitest.describe.call(void 0, "Connection Methods", () => {
_vitest.test.call(void 0, "should connect using .get().connect()", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
await client.counter.create(["test-get"]);
const handle = client.counter.get(["test-get"]);
const connection = handle.connect();
const count = await connection.increment(5);
_vitest.expect.call(void 0, count).toBe(5);
await connection.dispose();
});
_vitest.test.call(void 0, "should connect using .getForId().connect()", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const handle = client.counter.getOrCreate(["test-get-for-id"]);
await handle.increment(3);
const actorId = await handle.resolve();
const idHandle = client.counter.getForId(actorId);
const connection = idHandle.connect();
const count = await connection.getCount();
_vitest.expect.call(void 0, count).toBe(3);
await connection.dispose();
});
_vitest.test.call(void 0, "should connect using .getOrCreate().connect()", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const handle = client.counter.getOrCreate(["test-get-or-create"]);
const connection = handle.connect();
const count = await connection.increment(7);
_vitest.expect.call(void 0, count).toBe(7);
await connection.dispose();
});
_vitest.test.call(void 0, "should connect using (await create()).connect()", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const handle = await client.counter.create(["test-create"]);
const connection = handle.connect();
const count = await connection.increment(9);
_vitest.expect.call(void 0, count).toBe(9);
await connection.dispose();
});
});
_vitest.describe.call(void 0, "Event Communication", () => {
_vitest.test.call(void 0, "should mix RPC calls and WebSocket events", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const handle = client.counter.getOrCreate(["test-mixed-rpc-ws"]);
const connection = handle.connect();
const receivedEvents = [];
connection.on("newCount", (count) => {
receivedEvents.push(count);
});
await connection.increment(1);
await handle.increment(5);
await handle.increment(3);
_vitest.expect.call(void 0, receivedEvents).toContain(1);
_vitest.expect.call(void 0, receivedEvents).toContain(6);
_vitest.expect.call(void 0, receivedEvents).toContain(9);
await connection.dispose();
});
_vitest.test.call(void 0, "should receive events via broadcast", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const handle = client.counter.getOrCreate(["test-broadcast"]);
const connection = handle.connect();
const receivedEvents = [];
connection.on("newCount", (count) => {
receivedEvents.push(count);
});
await connection.increment(5);
await connection.increment(3);
_vitest.expect.call(void 0, receivedEvents).toContain(5);
_vitest.expect.call(void 0, receivedEvents).toContain(8);
await connection.dispose();
});
_vitest.test.call(void 0, "should handle one-time events with once()", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const handle = client.counter.getOrCreate(["test-once"]);
const connection = handle.connect();
const receivedEvents = [];
connection.once("newCount", (count) => {
receivedEvents.push(count);
});
await connection.increment(5);
await connection.increment(3);
_vitest.expect.call(void 0, receivedEvents).toEqual([5]);
_vitest.expect.call(void 0, receivedEvents).not.toContain(8);
await connection.dispose();
});
_vitest.test.call(void 0, "should unsubscribe from events", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const handle = client.counter.getOrCreate(["test-unsubscribe"]);
const connection = handle.connect();
const receivedEvents = [];
const unsubscribe = connection.on("newCount", (count) => {
receivedEvents.push(count);
});
await connection.increment(5);
unsubscribe();
await connection.increment(3);
_vitest.expect.call(void 0, receivedEvents).toEqual([5]);
_vitest.expect.call(void 0, receivedEvents).not.toContain(8);
await connection.dispose();
});
});
_vitest.describe.call(void 0, "Connection Parameters", () => {
_vitest.test.call(void 0, "should pass connection parameters", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const handle1 = client.counterWithParams.getOrCreate(["test-params"], {
params: { name: "user1" }
});
const handle2 = client.counterWithParams.getOrCreate(["test-params"], {
params: { name: "user2" }
});
const conn1 = handle1.connect();
const conn2 = handle2.connect();
await conn1.getInitializers();
await conn2.getInitializers();
const initializers = await conn1.getInitializers();
_vitest.expect.call(void 0, initializers).toContain("user1");
_vitest.expect.call(void 0, initializers).toContain("user2");
await conn1.dispose();
await conn2.dispose();
});
});
_vitest.describe.call(void 0, "Lifecycle Hooks", () => {
_vitest.test.call(void 0, "should trigger lifecycle hooks", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const connHandle = client.counterWithLifecycle.getOrCreate(
["test-lifecycle"],
{
params: { trackLifecycle: true }
}
);
const connection = connHandle.connect();
const events = await connection.getEvents();
_vitest.expect.call(void 0, events).toEqual(["onStart", "onBeforeConnect", "onConnect"]);
await connection.dispose();
const handle = client.counterWithLifecycle.getOrCreate([
"test-lifecycle"
]);
const finalEvents = await handle.getEvents();
_vitest.expect.call(void 0, finalEvents).toBeOneOf([
// Still active
["onStart", "onBeforeConnect", "onConnect", "onDisconnect"],
// Went to sleep and woke back up
[
"onStart",
"onBeforeConnect",
"onConnect",
"onDisconnect",
"onStart"
]
]);
});
});
});
}
// src/driver-test-suite/tests/actor-conn-state.ts
function runActorConnStateTests(driverTestConfig) {
_vitest.describe.call(void 0, "Actor Connection State Tests", () => {
_vitest.describe.call(void 0, "Connection State Initialization", () => {
_vitest.test.call(void 0, "should retrieve connection state", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const connection = client.connStateActor.getOrCreate().connect();
const connState = await connection.getConnectionState();
_vitest.expect.call(void 0, connState.id).toBeDefined();
_vitest.expect.call(void 0, connState.username).toBeDefined();
_vitest.expect.call(void 0, connState.role).toBeDefined();
_vitest.expect.call(void 0, connState.counter).toBeDefined();
_vitest.expect.call(void 0, connState.createdAt).toBeDefined();
await connection.dispose();
});
_vitest.test.call(void 0, "should initialize connection state with custom parameters", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const connection = client.connStateActor.getOrCreate([], {
params: {
username: "testuser",
role: "admin"
}
}).connect();
const connState = await connection.getConnectionState();
_vitest.expect.call(void 0, connState.username).toBe("testuser");
_vitest.expect.call(void 0, connState.role).toBe("admin");
await connection.dispose();
});
});
_vitest.describe.call(void 0, "Connection State Management", () => {
_vitest.test.call(void 0, "should maintain unique state for each connection", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const conn1 = client.connStateActor.getOrCreate([], {
params: { username: "user1" }
}).connect();
const conn2 = client.connStateActor.getOrCreate([], {
params: { username: "user2" }
}).connect();
await conn1.incrementConnCounter(5);
await conn2.incrementConnCounter(10);
const state1 = await conn1.getConnectionState();
const state2 = await conn2.getConnectionState();
_vitest.expect.call(void 0, state1.counter).toBe(5);
_vitest.expect.call(void 0, state2.counter).toBe(10);
_vitest.expect.call(void 0, state1.username).toBe("user1");
_vitest.expect.call(void 0, state2.username).toBe("user2");
await conn1.dispose();
await conn2.dispose();
});
_vitest.test.call(void 0, "should track connections in shared state", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const handle = client.connStateActor.getOrCreate();
const conn1 = handle.connect();
const conn2 = handle.connect();
const state1 = await conn1.getConnectionState();
const connectionIds = await conn1.getConnectionIds();
_vitest.expect.call(void 0, connectionIds.length).toBeGreaterThanOrEqual(2);
_vitest.expect.call(void 0, connectionIds).toContain(state1.id);
await conn1.dispose();
await conn2.dispose();
});
_vitest.test.call(void 0, "should identify different connections in the same actor", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const handle = client.connStateActor.getOrCreate();
const conn1 = handle.connect();
const conn2 = handle.connect();
const allStates = await conn1.getAllConnectionStates();
_vitest.expect.call(void 0, allStates.length).toBeGreaterThanOrEqual(2);
const ids = allStates.map((state) => state.id);
const uniqueIds = [...new Set(ids)];
_vitest.expect.call(void 0, uniqueIds.length).toBe(ids.length);
await conn1.dispose();
await conn2.dispose();
});
});
_vitest.describe.call(void 0, "Connection Lifecycle", () => {
_vitest.test.call(void 0, "should track connection and disconnection events", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const handle = client.connStateActor.getOrCreate();
const conn = handle.connect();
const connState = await conn.getConnectionState();
const connectionIds = await conn.getConnectionIds();
_vitest.expect.call(void 0, connectionIds).toContain(connState.id);
const initialDisconnections = await conn.getDisconnectionCount();
await conn.dispose();
const newConn = handle.connect();
await _vitest.vi.waitFor(async () => {
const newDisconnections = await newConn.getDisconnectionCount();
_vitest.expect.call(void 0, newDisconnections).toBeGreaterThan(initialDisconnections);
});
await newConn.dispose();
});
_vitest.test.call(void 0, "should update connection state", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const conn = client.connStateActor.getOrCreate().connect();
const initialState = await conn.getConnectionState();
_vitest.expect.call(void 0, initialState.username).toBe("anonymous");
const updatedState = await conn.updateConnection({
username: "newname",
role: "moderator"
});
_vitest.expect.call(void 0, updatedState.username).toBe("newname");
_vitest.expect.call(void 0, updatedState.role).toBe("moderator");
const latestState = await conn.getConnectionState();
_vitest.expect.call(void 0, latestState.username).toBe("newname");
_vitest.expect.call(void 0, latestState.role).toBe("moderator");
await conn.dispose();
});
});
_vitest.describe.call(void 0, "Connection Communication", () => {
_vitest.test.call(void 0, "should send messages to specific connections", async (c) => {
const { client } = await setupDriverTest(c, driverTestConfig);
const handle = client.connStateActor.getOrCreate();
const conn1 = handle.connect();
const conn2 = handle.connect();
const state1 = await conn1.getConnectionState();
const state2 = await conn2.getConnectionState();
const receivedMessages = [];
conn2.on("directMessage", (data) => {
receivedMessages.push(data);
});
const success = await conn1.sendToConnection(
state2.id,
"Hello from conn1"
);
_vitest.expect.call(void 0, success).toBe(true);
_vitest.expect.call(void 0, receivedMessages.length).toBe(1);