@methodacting/actor-kit 0.47.0 → 0.47.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/schemas.ts","../src/constants.ts","../src/storage.ts","../src/alarms.ts","../src/durable-object-system.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport const BotManagementSchema = z.object({\n corporateProxy: z.boolean(),\n verifiedBot: z.boolean(),\n jsDetection: z.object({\n passed: z.boolean(),\n }),\n staticResource: z.boolean(),\n detectionIds: z.record(z.any()),\n score: z.number(),\n});\n\nexport const EnvironmentSchema = z.object({\n ACTOR_KIT_SECRET: z.string(),\n ACTOR_KIT_HOST: z.string(),\n});\n\nexport const RequestInfoSchema = z.object({\n longitude: z.string(),\n latitude: z.string(),\n continent: z.string(),\n country: z.string(),\n city: z.string(),\n timezone: z.string(),\n postalCode: z.string(),\n region: z.string(),\n regionCode: z.string(),\n metroCode: z.string(),\n botManagement: BotManagementSchema,\n});\n\nexport const CallerSchema = z.object({\n id: z.string(),\n type: z.enum([\"client\", \"system\", \"service\"]),\n});\n\nexport const AnyEventSchema = z.object({\n type: z.string(),\n});\n\nexport const SystemEventSchema = z.discriminatedUnion(\"type\", [\n z.object({\n type: z.literal(\"INITIALIZE\"),\n caller: z.object({ type: z.literal(\"system\"), id: z.string() }),\n }),\n z.object({\n type: z.literal(\"CONNECT\"),\n caller: z.object({ type: z.literal(\"system\"), id: z.string() }),\n connectingCaller: CallerSchema,\n }),\n z.object({\n type: z.literal(\"DISCONNECT\"),\n caller: z.object({ type: z.literal(\"system\"), id: z.string() }),\n disconnectingCaller: CallerSchema,\n }),\n z.object({\n type: z.literal(\"RESUME\"),\n caller: z.object({ type: z.literal(\"system\"), id: z.string() }),\n }),\n z.object({\n type: z.literal(\"MIGRATE\"),\n caller: z.object({ type: z.literal(\"system\"), id: z.string() }),\n operations: z.array(z.any()),\n }),\n]);\n\nexport const CallerIdTypeSchema = z.enum([\"client\", \"service\", \"system\"]);\n\nexport const CallerStringSchema = z.string().transform((val, ctx) => {\n if (val === \"anonymous\") {\n return { type: \"client\" as const, id: \"anonymous\" };\n }\n\n // Regular expression to validate the UUID format\n const callerTypeParseResult = CallerIdTypeSchema.safeParse(val.split(\"-\")[0]);\n if (!callerTypeParseResult.success) {\n callerTypeParseResult.error.issues.forEach(ctx.addIssue);\n return z.NEVER;\n }\n const type = callerTypeParseResult.data;\n\n const id = val.substring(val.indexOf(\"-\") + 1);\n if (z.string().uuid().safeParse(id).success) {\n return { type, id };\n } else {\n // If not valid, add a custom issue\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Must be a valid uuid or 'anonymous'. Received '${id}' on value '${val}'.`,\n });\n // Return the special NEVER symbol to indicate a validation failure\n return z.NEVER;\n }\n});\n","import { CallerType } from \"./types\";\nimport type { AlarmType } from \"./alarms\";\n\nexport const HEADERS = {\n X_CALLER_ID: \"X-Caller-ID\",\n X_CALLER_TYPE: \"X-Caller-Type\",\n X_ACTOR_ID: \"X-Actor-ID\",\n X_ACTOR_TYPE: \"X-Actor-Type\",\n};\n\n/**\n * Defines the types of callers that can interact with the actor system.\n * Each type represents a different source of events with varying levels of trust and permissions.\n * Note: SYSTEM events are handled internally by Actor Kit and are not defined by the user.\n */\nexport const CallerTypes: Record<CallerType, CallerType> = {\n client: \"client\",\n system: \"system\", // Handled internally by Actor Kit\n service: \"service\",\n};\n\n/**\n * Alarm types supported by the alarm system\n */\nexport const AlarmTypes: Record<AlarmType, AlarmType> = {\n \"xstate-delay\": \"xstate-delay\",\n \"cache-cleanup\": \"cache-cleanup\",\n custom: \"custom\",\n};\n\nexport const PERSISTED_SNAPSHOT_KEY = \"persistedSnapshot\";\n","import { PERSISTED_SNAPSHOT_KEY } from \"./constants\";\nimport type { Caller } from \"./types\";\n\n/**\n * SQL schema for the actor-kit SQLite storage\n */\nconst SQL_SCHEMA = `\n-- Alarms table - supports one-time and recurring alarms\nCREATE TABLE IF NOT EXISTS alarms (\n id TEXT PRIMARY KEY,\n type TEXT NOT NULL,\n scheduled_at INTEGER NOT NULL,\n repeat_interval INTEGER,\n payload TEXT,\n created_at INTEGER NOT NULL\n);\n\n-- Index for efficient due alarm queries\nCREATE INDEX IF NOT EXISTS idx_alarms_scheduled_at ON alarms(scheduled_at);\n\n-- Actor metadata (replaces KV keys: actorType, actorId, initialCaller, input)\nCREATE TABLE IF NOT EXISTS actor_meta (\n actor_id TEXT PRIMARY KEY,\n actor_type TEXT NOT NULL,\n initial_caller TEXT NOT NULL,\n input TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n);\n\n-- Snapshots table (replaces PERSISTED_SNAPSHOT_KEY)\nCREATE TABLE IF NOT EXISTS snapshots (\n actor_id TEXT PRIMARY KEY,\n snapshot TEXT NOT NULL,\n checksum TEXT,\n updated_at INTEGER NOT NULL\n);\n`;\n\n/**\n * Alarm record from the database\n */\nexport interface AlarmRecord {\n id: string;\n type: string;\n scheduled_at: number;\n repeat_interval: number | null;\n payload: string | null;\n created_at: number;\n}\n\n/**\n * Scheduled alarm options\n */\nexport interface AlarmScheduleOptions {\n id: string;\n type: string;\n scheduledAt: number;\n repeatInterval?: number;\n payload: Record<string, unknown>;\n}\n\n/**\n * Actor metadata record\n */\nexport interface ActorMetaRecord {\n actor_id: string;\n actor_type: string;\n initial_caller: string; // JSON stringified Caller\n input: string; // JSON stringified\n created_at: number;\n updated_at: number;\n}\n\n/**\n * Actor metadata as an object\n */\nexport interface ActorMeta {\n actorId: string;\n actorType: string;\n initialCaller: Caller;\n input: Record<string, unknown>;\n}\n\n/**\n * Snapshot record\n */\nexport interface SnapshotRecord {\n actor_id: string;\n snapshot: string; // JSON stringified\n checksum: string | null;\n updated_at: number;\n}\n\n/**\n * Snapshot as an object\n */\nexport interface Snapshot {\n actorId: string;\n snapshot: unknown;\n checksum?: string;\n}\n\n/**\n * SQLite storage wrapper for actor-kit Durable Objects\n * Provides methods for managing alarms, actor metadata, and snapshots\n */\nexport class ActorKitStorage {\n private initialized = false;\n private sql: DurableObjectStorage[\"sql\"];\n\n constructor(private storage: DurableObjectStorage) {\n this.sql = storage.sql;\n }\n\n /**\n * Initialize the database schema if not already done\n */\n async ensureInitialized(): Promise<void> {\n if (this.initialized) return;\n\n try {\n // Execute schema creation - SQLite will ignore IF NOT EXISTS if tables exist\n await this.sql.exec(SQL_SCHEMA);\n this.initialized = true;\n } catch (error) {\n console.error(\"Failed to initialize database schema:\", error);\n throw error;\n }\n }\n\n // ==================== Alarms ====================\n\n /**\n * Get all alarms, optionally filtered by actor\n */\n async getAlarms(): Promise<AlarmRecord[]> {\n await this.ensureInitialized();\n const result = await this.sql.exec(\n \"SELECT id, type, scheduled_at, repeat_interval, payload, created_at FROM alarms ORDER BY scheduled_at ASC\"\n );\n return (await this.parseRows(result)) as AlarmRecord[];\n }\n\n /**\n * Get alarms that are due before a given timestamp\n */\n async getDueAlarms(before: number): Promise<AlarmRecord[]> {\n await this.ensureInitialized();\n const result = await this.sql.exec(\n \"SELECT id, type, scheduled_at, repeat_interval, payload, created_at FROM alarms WHERE scheduled_at <= ? ORDER BY scheduled_at ASC\",\n [before]\n );\n return (await this.parseRows(result)) as AlarmRecord[];\n }\n\n /**\n * Get the earliest scheduled alarm\n */\n async getEarliestAlarm(): Promise<AlarmRecord | null> {\n await this.ensureInitialized();\n const result = await this.sql.exec(\n \"SELECT id, type, scheduled_at, repeat_interval, payload, created_at FROM alarms ORDER BY scheduled_at ASC LIMIT 1\"\n );\n const rows = (await this.parseRows(result)) as AlarmRecord[];\n return rows[0] || null;\n }\n\n /**\n * Insert a new alarm\n */\n async insertAlarm(options: AlarmScheduleOptions): Promise<void> {\n await this.ensureInitialized();\n await this.sql.exec(\n \"INSERT INTO alarms (id, type, scheduled_at, repeat_interval, payload, created_at) VALUES (?, ?, ?, ?, ?, ?)\",\n [\n options.id,\n options.type,\n options.scheduledAt,\n options.repeatInterval ?? null,\n JSON.stringify(options.payload),\n Date.now(),\n ]\n );\n }\n\n /**\n * Update an alarm's scheduled time (for recurring alarms)\n */\n async updateAlarm(options: AlarmScheduleOptions): Promise<void> {\n await this.ensureInitialized();\n await this.sql.exec(\n \"UPDATE alarms SET scheduled_at = ?, repeat_interval = ?, payload = ? WHERE id = ?\",\n [options.scheduledAt, options.repeatInterval ?? null, JSON.stringify(options.payload), options.id]\n );\n }\n\n /**\n * Delete an alarm by ID\n */\n async deleteAlarm(id: string): Promise<void> {\n await this.ensureInitialized();\n await this.sql.exec(\"DELETE FROM alarms WHERE id = ?\", [id]);\n }\n\n /**\n * Delete all alarms of a specific type\n */\n async deleteAlarmsByType(type: string): Promise<void> {\n await this.ensureInitialized();\n await this.sql.exec(\"DELETE FROM alarms WHERE type = ?\", [type]);\n }\n\n // ==================== Actor Metadata ====================\n\n /**\n * Get actor metadata by ID\n */\n async getActorMeta(actorId?: string): Promise<ActorMeta | null> {\n await this.ensureInitialized();\n\n if (!actorId) {\n // Get the first (and only) actor metadata\n const result = await this.sql.exec(\n \"SELECT actor_id, actor_type, initial_caller, input, created_at, updated_at FROM actor_meta LIMIT 1\"\n );\n const rows = (await this.parseRows(result)) as ActorMetaRecord[];\n if (rows.length === 0) return null;\n\n const row = rows[0];\n return {\n actorId: row.actor_id,\n actorType: row.actor_type,\n initialCaller: JSON.parse(row.initial_caller) as Caller,\n input: JSON.parse(row.input),\n };\n }\n\n const result = await this.sql.exec(\n \"SELECT actor_id, actor_type, initial_caller, input, created_at, updated_at FROM actor_meta WHERE actor_id = ?\",\n [actorId]\n );\n const rows = (await this.parseRows(result)) as ActorMetaRecord[];\n if (rows.length === 0) return null;\n\n const row = rows[0];\n return {\n actorId: row.actor_id,\n actorType: row.actor_type,\n initialCaller: JSON.parse(row.initial_caller) as Caller,\n input: JSON.parse(row.input),\n };\n }\n\n /**\n * Set actor metadata\n */\n async setActorMeta(meta: ActorMeta): Promise<void> {\n await this.ensureInitialized();\n const now = Date.now();\n await this.sql.exec(\n `INSERT INTO actor_meta (actor_id, actor_type, initial_caller, input, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(actor_id) DO UPDATE SET\n actor_type = excluded.actor_type,\n initial_caller = excluded.initial_caller,\n input = excluded.input,\n updated_at = excluded.updated_at`,\n [\n meta.actorId,\n meta.actorType,\n JSON.stringify(meta.initialCaller),\n JSON.stringify(meta.input),\n now,\n now,\n ]\n );\n }\n\n /**\n * Delete actor metadata\n */\n async deleteActorMeta(actorId: string): Promise<void> {\n await this.ensureInitialized();\n await this.sql.exec(\"DELETE FROM actor_meta WHERE actor_id = ?\", [actorId]);\n }\n\n // ==================== Snapshots ====================\n\n /**\n * Get a snapshot by actor ID\n */\n async getSnapshot(actorId: string): Promise<Snapshot | null> {\n await this.ensureInitialized();\n const result = await this.sql.exec(\n \"SELECT actor_id, snapshot, checksum, updated_at FROM snapshots WHERE actor_id = ?\",\n [actorId]\n );\n const rows = (await this.parseRows(result)) as SnapshotRecord[];\n if (rows.length === 0) return null;\n\n const row = rows[0];\n return {\n actorId: row.actor_id,\n snapshot: JSON.parse(row.snapshot),\n checksum: row.checksum ?? undefined,\n };\n }\n\n /**\n * Set a snapshot for an actor\n */\n async setSnapshot(actorId: string, snapshot: unknown, checksum?: string): Promise<void> {\n await this.ensureInitialized();\n await this.sql.exec(\n `INSERT INTO snapshots (actor_id, snapshot, checksum, updated_at)\n VALUES (?, ?, ?, ?)\n ON CONFLICT(actor_id) DO UPDATE SET\n snapshot = excluded.snapshot,\n checksum = excluded.checksum,\n updated_at = excluded.updated_at`,\n [actorId, JSON.stringify(snapshot), checksum ?? null, Date.now()]\n );\n }\n\n /**\n * Delete a snapshot\n */\n async deleteSnapshot(actorId: string): Promise<void> {\n await this.ensureInitialized();\n await this.sql.exec(\"DELETE FROM snapshots WHERE actor_id = ?\", [actorId]);\n }\n\n // ==================== Migration Helpers ====================\n\n /**\n * Migrate data from legacy KV storage to SQLite\n * This is a one-time migration helper\n */\n async migrateFromKV(storage: DurableObjectStorage): Promise<void> {\n await this.ensureInitialized();\n\n // Migrate actor metadata\n const [actorType, actorId, initialCallerString, inputString] = await Promise.all([\n storage.get(\"actorType\"),\n storage.get(\"actorId\"),\n storage.get(\"initialCaller\"),\n storage.get(\"input\"),\n ]);\n\n if (actorType && actorId && initialCallerString && inputString) {\n await this.setActorMeta({\n actorId: actorId as string,\n actorType: actorType as string,\n initialCaller: JSON.parse(initialCallerString as string) as Caller,\n input: JSON.parse(inputString as string),\n });\n }\n\n // Migrate persisted snapshot\n const persistedSnapshot = await storage.get(PERSISTED_SNAPSHOT_KEY);\n if (persistedSnapshot) {\n const snapshot = JSON.parse(persistedSnapshot as string);\n await this.setSnapshot(actorId as string, snapshot);\n }\n }\n\n // ==================== Utility Methods ====================\n\n /**\n * Parse SQL result rows - handles both arrays and cursors\n */\n private async parseRows(result: any): Promise<unknown[]> {\n // Check if result is an async iterable (cursor)\n if (result && typeof result[Symbol.asyncIterator] === \"function\") {\n const cursor = result as AsyncIterable<{ columns: string[]; results: (string | number | null)[][] }>;\n const rows: unknown[] = [];\n let columns: string[] = [];\n\n for await (const batch of cursor) {\n if (!columns) columns = batch.columns;\n for (const row of batch.results) {\n const obj: Record<string, unknown> = {};\n columns.forEach((col, i) => {\n obj[col] = row[i];\n });\n rows.push(obj);\n }\n }\n return rows;\n }\n\n // Handle array format\n if (Array.isArray(result) && result.length === 0) return [];\n const { columns, rows } = result[0];\n return rows.map((row: unknown[]) => {\n const obj: Record<string, unknown> = {};\n columns.forEach((col: string, i: number) => {\n obj[col] = row[i];\n });\n return obj;\n });\n }\n}\n","import type {\n ActorKitStorage,\n AlarmRecord,\n AlarmScheduleOptions,\n} from \"./storage\";\n\n/**\n * Supported alarm types\n */\nexport type AlarmType = \"xstate-delay\" | \"cache-cleanup\" | \"custom\";\n\n/**\n * Alarm data from the database with parsed payload\n */\nexport interface Alarm {\n id: string;\n type: AlarmType;\n scheduledAt: number;\n repeatInterval?: number;\n payload: Record<string, unknown>;\n createdAt: number;\n}\n\n/**\n * Options for scheduling a new alarm\n */\nexport interface ScheduleAlarmOptions {\n id: string;\n type: AlarmType;\n scheduledAt: number;\n repeatInterval?: number;\n payload: Record<string, unknown>;\n}\n\n/**\n * Result from handling an alarm\n */\nexport interface AlarmHandleResult {\n id: string;\n type: AlarmType;\n rescheduled?: boolean;\n deleted: boolean;\n}\n\n/**\n * Manages alarms for a Durable Object using SQLite storage\n * and the Durable Object alarm API\n */\nexport class AlarmManager {\n private storage: ActorKitStorage;\n private state: DurableObjectState;\n private currentAlarmId: string | null = null;\n private currentAlarmTime: number | null = null;\n\n constructor(storage: ActorKitStorage, state: DurableObjectState) {\n this.storage = storage;\n this.state = state;\n }\n\n /**\n * Schedule a new alarm\n */\n async schedule(options: ScheduleAlarmOptions): Promise<void> {\n await this.storage.insertAlarm(options);\n await this.rescheduleNextAlarm();\n }\n\n /**\n * Cancel an alarm by ID\n */\n async cancel(id: string): Promise<void> {\n await this.storage.deleteAlarm(id);\n // If we canceled the current alarm, reschedule\n if (this.currentAlarmId === id) {\n await this.rescheduleNextAlarm();\n }\n }\n\n /**\n * Cancel all alarms of a specific type\n */\n async cancelByType(type: AlarmType): Promise<void> {\n await this.storage.deleteAlarmsByType(type);\n await this.rescheduleNextAlarm();\n }\n\n /**\n * Get all pending alarms\n */\n async getPendingAlarms(): Promise<Alarm[]> {\n const records = await this.storage.getAlarms();\n return records.map(this.parseAlarmRecord);\n }\n\n /**\n * Get alarms that are due now or before a given time\n */\n async getDueAlarms(before: number = Date.now()): Promise<Alarm[]> {\n const records = await this.storage.getDueAlarms(before);\n return records.map(this.parseAlarmRecord);\n }\n\n /**\n * Delete an alarm after it has been handled\n */\n async deleteAlarm(id: string): Promise<void> {\n await this.storage.deleteAlarm(id);\n }\n\n /**\n * Update an alarm (for rescheduling recurring alarms)\n */\n async updateAlarm(options: ScheduleAlarmOptions): Promise<void> {\n await this.storage.updateAlarm(options);\n }\n\n /**\n * Reschedule the next DO alarm based on the earliest alarm in storage\n * This sets the actual Durable Object alarm that will trigger the alarm() handler\n */\n async rescheduleNextAlarm(): Promise<void> {\n const earliest = await this.storage.getEarliestAlarm();\n\n if (!earliest) {\n // No alarms pending, clear the DO alarm\n this.currentAlarmId = null;\n this.currentAlarmTime = null;\n // Note: There's no way to \"clear\" a DO alarm, but we can set one far in the future\n // or just let it expire naturally\n return;\n }\n\n // Only set a new alarm if the earliest one is different from current\n if (this.currentAlarmId !== earliest.id || this.currentAlarmTime !== earliest.scheduled_at) {\n this.currentAlarmId = earliest.id;\n this.currentAlarmTime = earliest.scheduled_at;\n await this.state.storage.setAlarm(earliest.scheduled_at);\n }\n }\n\n /**\n * Handle due alarms and return results\n * This should be called from the Durable Object's alarm() handler\n */\n async handleDueAlarms(handler: (alarm: Alarm) => Promise<boolean>): Promise<AlarmHandleResult[]> {\n const now = Date.now();\n const dueAlarms = await this.getDueAlarms(now);\n const results: AlarmHandleResult[] = [];\n\n for (const alarm of dueAlarms) {\n let rescheduled = false;\n let deleted = true;\n\n if (alarm.repeatInterval) {\n // Recurring alarm - reschedule it\n const nextScheduledAt = now + alarm.repeatInterval;\n await this.updateAlarm({\n id: alarm.id,\n type: alarm.type,\n scheduledAt: nextScheduledAt,\n repeatInterval: alarm.repeatInterval,\n payload: alarm.payload,\n });\n rescheduled = true;\n deleted = false;\n } else {\n // One-time alarm - delete it\n await this.deleteAlarm(alarm.id);\n }\n\n // Call the handler and let it perform the alarm-specific action\n try {\n await handler(alarm);\n } catch (error) {\n console.error(`Error handling alarm ${alarm.id}:`, error);\n }\n\n results.push({\n id: alarm.id,\n type: alarm.type,\n rescheduled,\n deleted,\n });\n }\n\n // Reschedule the next DO alarm\n await this.rescheduleNextAlarm();\n\n return results;\n }\n\n /**\n * Get the current scheduled DO alarm info\n */\n getCurrentAlarm(): { id: string | null; time: number | null } {\n return {\n id: this.currentAlarmId,\n time: this.currentAlarmTime,\n };\n }\n\n /**\n * Parse an alarm record from the database into an Alarm object\n */\n private parseAlarmRecord(record: AlarmRecord): Alarm {\n return {\n id: record.id,\n type: record.type as AlarmType,\n scheduledAt: record.scheduled_at,\n repeatInterval: record.repeat_interval ?? undefined,\n payload: record.payload ? JSON.parse(record.payload) : {},\n createdAt: record.created_at,\n };\n }\n}\n\n/**\n * Generate a unique alarm ID\n */\nexport function generateAlarmId(): string {\n return `alarm-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n}\n\n/**\n * Calculate the next scheduled time for a recurring alarm\n */\nexport function calculateNextRecurringAlarm(\n baseTime: number,\n interval: number,\n now: number = Date.now()\n): number {\n let next = baseTime;\n while (next < now) {\n next += interval;\n }\n return next;\n}\n","import type { AnyActorRef, AnyEventObject } from \"xstate\";\nimport type { AlarmManager } from \"./alarms\";\n\n/**\n * Serializable data stored with each alarm for XState delayed events\n */\nexport interface XStateAlarmData {\n type: \"xstate-delay\";\n sourceSessionId: string;\n targetSessionId: string;\n event: AnyEventObject;\n scheduledEventId: string;\n alarmId: string;\n [key: string]: unknown; // Index signature for Record<string, unknown> compatibility\n}\n\n/**\n * Snapshot of scheduled events for persistence\n */\nexport interface ScheduledEventSnapshot {\n sourceSessionId: string;\n targetSessionId: string;\n event: AnyEventObject;\n delay: number;\n id: string;\n startedAt: number;\n}\n\n/**\n * Clock interface for compatibility with XState\n */\nexport interface Clock {\n setTimeout: (fn: () => void, delay: number) => unknown;\n clearTimeout: (id: unknown) => void;\n}\n\n/**\n * Simple no-op clock for XState actors that use alarm-based scheduling\n * This clock doesn't actually schedule anything - delays are handled via alarms\n */\nexport const NOOP_CLOCK: Clock = {\n setTimeout: () => Math.random(), // Return a fake ID\n clearTimeout: () => {\n // No-op - alarms manage cancellation\n },\n};\n\n/**\n * Map to track scheduled events by their scheduledEventId\n * This is used to look up event data when an alarm fires\n */\nconst scheduledEventsMap = new Map<string, ScheduledEventSnapshot>();\n\n/**\n * Create an alarm-based scheduler for XState actors\n * This replaces the default setTimeout-based scheduler with one that uses Durable Object alarms\n *\n * @param alarmManager - The alarm manager to schedule alarms with\n * @param system - The XState ActorSystem (used to relay events)\n * @returns A scheduler object with schedule, cancel, and cancelAll methods\n */\nexport function createAlarmScheduler(\n alarmManager: AlarmManager,\n system: any\n): {\n schedule: (\n source: AnyActorRef,\n target: AnyActorRef,\n event: AnyEventObject,\n delay: number,\n id?: string\n ) => void;\n cancel: (source: AnyActorRef, id: string) => void;\n cancelAll: (actorRef: AnyActorRef) => void;\n} {\n return {\n schedule: (\n source: AnyActorRef,\n target: AnyActorRef,\n event: AnyEventObject,\n delay: number,\n id: string = Math.random().toString(36).slice(2)\n ) => {\n const scheduledEventId = `${source.sessionId}.${id}`;\n\n // Store the event data for later retrieval\n const snapshot: ScheduledEventSnapshot = {\n sourceSessionId: source.sessionId,\n targetSessionId: target.sessionId,\n event,\n delay,\n id,\n startedAt: Date.now(),\n };\n scheduledEventsMap.set(scheduledEventId, snapshot);\n\n // Schedule the alarm\n const alarmId = `xstate-${scheduledEventId}`;\n\n alarmManager.schedule({\n id: alarmId,\n type: \"xstate-delay\",\n scheduledAt: Date.now() + delay,\n payload: {\n type: \"xstate-delay\",\n sourceSessionId: source.sessionId,\n targetSessionId: target.sessionId,\n event,\n scheduledEventId,\n alarmId,\n },\n }).catch((error) => {\n console.error(`[AlarmScheduler] Error scheduling alarm:`, error);\n scheduledEventsMap.delete(scheduledEventId);\n });\n },\n\n cancel: (source: AnyActorRef, id: string) => {\n const scheduledEventId = `${source.sessionId}.${id}`;\n\n // Remove from our tracking map\n scheduledEventsMap.delete(scheduledEventId);\n\n // Cancel the alarm\n alarmManager.cancel(`xstate-${scheduledEventId}`).catch((error) => {\n console.error(`[AlarmScheduler] Error canceling alarm:`, error);\n });\n },\n\n cancelAll: (actorRef: AnyActorRef) => {\n // Find all events for this actor\n const eventsToCancel: string[] = [];\n\n for (const [scheduledEventId, snapshot] of scheduledEventsMap.entries()) {\n if (snapshot.sourceSessionId === actorRef.sessionId) {\n eventsToCancel.push(scheduledEventId);\n }\n }\n\n // Cancel each event\n for (const scheduledEventId of eventsToCancel) {\n scheduledEventsMap.delete(scheduledEventId);\n alarmManager.cancel(`xstate-${scheduledEventId}`).catch((error) => {\n console.error(`[AlarmScheduler] Error canceling alarm:`, error);\n });\n }\n },\n };\n}\n\n/**\n * Handle an XState delayed event alarm\n * This should be called from the Durable Object's alarm() handler\n *\n * @param alarmData - The alarm data from the XState alarm\n * @param actor - The actor to send the event to\n */\nexport async function handleXStateAlarm(\n alarmData: XStateAlarmData,\n actor: any\n): Promise<void> {\n const { scheduledEventId, event } = alarmData;\n\n // Remove from tracking map\n scheduledEventsMap.delete(scheduledEventId);\n\n // Send the event to the actor\n try {\n // Use the actor's internal _relay method to deliver the event\n if (actor.system && actor.system._relay) {\n actor.system._relay(actor, actor, event);\n } else {\n // Fallback: send directly to the actor\n actor.send(event);\n }\n } catch (error) {\n console.error(`[AlarmScheduler] Error handling XState alarm:`, error);\n }\n}\n\n/**\n * Get all scheduled events (useful for debugging/inspection)\n */\nexport function getScheduledEvents(): Map<string, ScheduledEventSnapshot> {\n return new Map(scheduledEventsMap);\n}\n\n/**\n * Restore scheduled events from storage (called after DO hibernation)\n */\nexport function restoreScheduledEvents(\n alarms: Array<{ payload: XStateAlarmData; scheduledAt: number }>\n): void {\n for (const alarm of alarms) {\n if (alarm.payload.type === \"xstate-delay\") {\n const { sourceSessionId, targetSessionId, event, scheduledEventId } = alarm.payload;\n const delay = alarm.scheduledAt - Date.now();\n\n // Only restore if the alarm is still in the future\n if (delay > 0) {\n scheduledEventsMap.set(scheduledEventId, {\n sourceSessionId,\n targetSessionId,\n event,\n delay,\n id: scheduledEventId.split(\".\").pop() || scheduledEventId,\n startedAt: alarm.scheduledAt - delay,\n });\n }\n }\n }\n}\n"],"names":["BotManagementSchema","z","object","corporateProxy","boolean","verifiedBot","jsDetection","passed","staticResource","detectionIds","record","any","score","number","EnvironmentSchema","ACTOR_KIT_SECRET","string","ACTOR_KIT_HOST","RequestInfoSchema","longitude","latitude","continent","country","city","timezone","postalCode","region","regionCode","metroCode","botManagement","CallerSchema","id","type","enum","AnyEventSchema","SystemEventSchema","discriminatedUnion","literal","caller","connectingCaller","disconnectingCaller","operations","array","CallerIdTypeSchema","CallerStringSchema","transform","val","ctx","callerTypeParseResult","safeParse","split","success","error","issues","forEach","addIssue","NEVER","data","substring","indexOf","uuid","code","ZodIssueCode","custom","message","HEADERS","X_CALLER_ID","X_CALLER_TYPE","X_ACTOR_ID","X_ACTOR_TYPE","CallerTypes","client","system","service","AlarmTypes","PERSISTED_SNAPSHOT_KEY","ActorKitStorage","storage","initialized","sql","constructor","this","ensureInitialized","exec","console","getAlarms","result","parseRows","getDueAlarms","before","getEarliestAlarm","insertAlarm","options","scheduledAt","repeatInterval","JSON","stringify","payload","Date","now","updateAlarm","deleteAlarm","deleteAlarmsByType","getActorMeta","actorId","rows","length","row","actor_id","actorType","actor_type","initialCaller","parse","initial_caller","input","setActorMeta","meta","deleteActorMeta","getSnapshot","snapshot","checksum","undefined","setSnapshot","deleteSnapshot","migrateFromKV","initialCallerString","inputString","Promise","all","get","persistedSnapshot","Symbol","asyncIterator","cursor","columns","batch","results","obj","col","i","push","Array","isArray","map","AlarmManager","state","currentAlarmId","currentAlarmTime","schedule","rescheduleNextAlarm","cancel","cancelByType","getPendingAlarms","parseAlarmRecord","earliest","scheduled_at","setAlarm","handleDueAlarms","handler","dueAlarms","alarm","rescheduled","deleted","nextScheduledAt","getCurrentAlarm","time","repeat_interval","createdAt","created_at","generateAlarmId","Math","random","toString","slice","calculateNextRecurringAlarm","baseTime","interval","next","NOOP_CLOCK","setTimeout","clearTimeout","scheduledEventsMap","Map","createAlarmScheduler","alarmManager","source","target","event","delay","scheduledEventId","sessionId","sourceSessionId","targetSessionId","startedAt","set","alarmId","catch","delete","cancelAll","actorRef","eventsToCancel","entries","async","handleXStateAlarm","alarmData","actor","_relay","send","getScheduledEvents","restoreScheduledEvents","alarms","pop"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/schemas.ts","../src/constants.ts","../src/storage.ts","../src/alarms.ts","../src/durable-object-system.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport const BotManagementSchema = z.object({\n corporateProxy: z.boolean(),\n verifiedBot: z.boolean(),\n jsDetection: z.object({\n passed: z.boolean(),\n }),\n staticResource: z.boolean(),\n detectionIds: z.record(z.string(), z.any()),\n score: z.number(),\n});\n\nexport const EnvironmentSchema = z.object({\n ACTOR_KIT_SECRET: z.string(),\n ACTOR_KIT_HOST: z.string(),\n});\n\nexport const RequestInfoSchema = z.object({\n longitude: z.string(),\n latitude: z.string(),\n continent: z.string(),\n country: z.string(),\n city: z.string(),\n timezone: z.string(),\n postalCode: z.string(),\n region: z.string(),\n regionCode: z.string(),\n metroCode: z.string(),\n botManagement: BotManagementSchema,\n});\n\nexport const CallerSchema = z.object({\n id: z.string(),\n type: z.enum([\"client\", \"system\", \"service\"]),\n});\n\nexport const AnyEventSchema = z.object({\n type: z.string(),\n});\n\nexport const SystemEventSchema = z.discriminatedUnion(\"type\", [\n z.object({\n type: z.literal(\"INITIALIZE\"),\n caller: z.object({ type: z.literal(\"system\"), id: z.string() }),\n }),\n z.object({\n type: z.literal(\"CONNECT\"),\n caller: z.object({ type: z.literal(\"system\"), id: z.string() }),\n connectingCaller: CallerSchema,\n }),\n z.object({\n type: z.literal(\"DISCONNECT\"),\n caller: z.object({ type: z.literal(\"system\"), id: z.string() }),\n disconnectingCaller: CallerSchema,\n }),\n z.object({\n type: z.literal(\"RESUME\"),\n caller: z.object({ type: z.literal(\"system\"), id: z.string() }),\n }),\n z.object({\n type: z.literal(\"MIGRATE\"),\n caller: z.object({ type: z.literal(\"system\"), id: z.string() }),\n operations: z.array(z.any()),\n }),\n]);\n\nexport const CallerIdTypeSchema = z.enum([\"client\", \"service\", \"system\"]);\n\nexport const CallerStringSchema = z.string().transform((val, ctx) => {\n if (val === \"anonymous\") {\n return { type: \"client\" as const, id: \"anonymous\" };\n }\n\n // Regular expression to validate the UUID format\n const callerTypeParseResult = CallerIdTypeSchema.safeParse(val.split(\"-\")[0]);\n if (!callerTypeParseResult.success) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Invalid caller type: ${val.split(\"-\")[0]}`,\n });\n return z.NEVER;\n }\n const type = callerTypeParseResult.data;\n\n const id = val.substring(val.indexOf(\"-\") + 1);\n if (z.string().uuid().safeParse(id).success) {\n return { type, id };\n } else {\n // If not valid, add a custom issue\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Must be a valid uuid or 'anonymous'. Received '${id}' on value '${val}'.`,\n });\n // Return the special NEVER symbol to indicate a validation failure\n return z.NEVER;\n }\n});\n","import { CallerType } from \"./types\";\nimport type { AlarmType } from \"./alarms\";\n\nexport const HEADERS = {\n X_CALLER_ID: \"X-Caller-ID\",\n X_CALLER_TYPE: \"X-Caller-Type\",\n X_ACTOR_ID: \"X-Actor-ID\",\n X_ACTOR_TYPE: \"X-Actor-Type\",\n};\n\n/**\n * Defines the types of callers that can interact with the actor system.\n * Each type represents a different source of events with varying levels of trust and permissions.\n * Note: SYSTEM events are handled internally by Actor Kit and are not defined by the user.\n */\nexport const CallerTypes: Record<CallerType, CallerType> = {\n client: \"client\",\n system: \"system\", // Handled internally by Actor Kit\n service: \"service\",\n};\n\n/**\n * Alarm types supported by the alarm system\n */\nexport const AlarmTypes: Record<AlarmType, AlarmType> = {\n \"xstate-delay\": \"xstate-delay\",\n \"cache-cleanup\": \"cache-cleanup\",\n custom: \"custom\",\n};\n\nexport const PERSISTED_SNAPSHOT_KEY = \"persistedSnapshot\";\n","import { PERSISTED_SNAPSHOT_KEY } from \"./constants\";\nimport type { Caller } from \"./types\";\n\n/**\n * SQL schema for the actor-kit SQLite storage\n */\nconst SQL_SCHEMA = `\n-- Alarms table - supports one-time and recurring alarms\nCREATE TABLE IF NOT EXISTS alarms (\n id TEXT PRIMARY KEY,\n type TEXT NOT NULL,\n scheduled_at INTEGER NOT NULL,\n repeat_interval INTEGER,\n payload TEXT,\n created_at INTEGER NOT NULL\n);\n\n-- Index for efficient due alarm queries\nCREATE INDEX IF NOT EXISTS idx_alarms_scheduled_at ON alarms(scheduled_at);\n\n-- Actor metadata (replaces KV keys: actorType, actorId, initialCaller, input)\nCREATE TABLE IF NOT EXISTS actor_meta (\n actor_id TEXT PRIMARY KEY,\n actor_type TEXT NOT NULL,\n initial_caller TEXT NOT NULL,\n input TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n);\n\n-- Snapshots table (replaces PERSISTED_SNAPSHOT_KEY)\nCREATE TABLE IF NOT EXISTS snapshots (\n actor_id TEXT PRIMARY KEY,\n snapshot TEXT NOT NULL,\n checksum TEXT,\n updated_at INTEGER NOT NULL\n);\n`;\n\n/**\n * Alarm record from the database\n */\nexport interface AlarmRecord {\n id: string;\n type: string;\n scheduled_at: number;\n repeat_interval: number | null;\n payload: string | null;\n created_at: number;\n}\n\n/**\n * Scheduled alarm options\n */\nexport interface AlarmScheduleOptions {\n id: string;\n type: string;\n scheduledAt: number;\n repeatInterval?: number;\n payload: Record<string, unknown>;\n}\n\n/**\n * Actor metadata record\n */\nexport interface ActorMetaRecord {\n actor_id: string;\n actor_type: string;\n initial_caller: string; // JSON stringified Caller\n input: string; // JSON stringified\n created_at: number;\n updated_at: number;\n}\n\n/**\n * Actor metadata as an object\n */\nexport interface ActorMeta {\n actorId: string;\n actorType: string;\n initialCaller: Caller;\n input: Record<string, unknown>;\n}\n\n/**\n * Snapshot record\n */\nexport interface SnapshotRecord {\n actor_id: string;\n snapshot: string; // JSON stringified\n checksum: string | null;\n updated_at: number;\n}\n\n/**\n * Snapshot as an object\n */\nexport interface Snapshot {\n actorId: string;\n snapshot: unknown;\n checksum?: string;\n}\n\n/**\n * SQLite storage wrapper for actor-kit Durable Objects\n * Provides methods for managing alarms, actor metadata, and snapshots\n */\nexport class ActorKitStorage {\n private initialized = false;\n private sql: DurableObjectStorage[\"sql\"];\n\n constructor(private readonly storage: DurableObjectStorage) {\n this.sql = storage.sql;\n }\n\n /**\n * Initialize the database schema if not already done\n */\n async ensureInitialized(): Promise<void> {\n if (this.initialized) return;\n\n try {\n // Execute schema creation - SQLite will ignore IF NOT EXISTS if tables exist\n await this.sql.exec(SQL_SCHEMA);\n this.initialized = true;\n } catch (error) {\n console.error(\"Failed to initialize database schema:\", error);\n throw error;\n }\n }\n\n // ==================== Alarms ====================\n\n /**\n * Get all alarms, optionally filtered by actor\n */\n async getAlarms(): Promise<AlarmRecord[]> {\n await this.ensureInitialized();\n const result = await this.sql.exec(\n \"SELECT id, type, scheduled_at, repeat_interval, payload, created_at FROM alarms ORDER BY scheduled_at ASC\"\n );\n return (await this.parseRows(result)) as AlarmRecord[];\n }\n\n /**\n * Get alarms that are due before a given timestamp\n */\n async getDueAlarms(before: number): Promise<AlarmRecord[]> {\n await this.ensureInitialized();\n const result = await this.sql.exec(\n \"SELECT id, type, scheduled_at, repeat_interval, payload, created_at FROM alarms WHERE scheduled_at <= ? ORDER BY scheduled_at ASC\",\n before\n );\n return (await this.parseRows(result)) as AlarmRecord[];\n }\n\n /**\n * Get the earliest scheduled alarm\n */\n async getEarliestAlarm(): Promise<AlarmRecord | null> {\n await this.ensureInitialized();\n const result = await this.sql.exec(\n \"SELECT id, type, scheduled_at, repeat_interval, payload, created_at FROM alarms ORDER BY scheduled_at ASC LIMIT 1\"\n );\n const rows = (await this.parseRows(result)) as AlarmRecord[];\n return rows[0] || null;\n }\n\n /**\n * Insert a new alarm\n */\n async insertAlarm(options: AlarmScheduleOptions): Promise<void> {\n await this.ensureInitialized();\n await this.sql.exec(\n \"INSERT INTO alarms (id, type, scheduled_at, repeat_interval, payload, created_at) VALUES (?, ?, ?, ?, ?, ?)\",\n options.id,\n options.type,\n options.scheduledAt,\n options.repeatInterval ?? null,\n JSON.stringify(options.payload),\n Date.now()\n );\n }\n\n /**\n * Update an alarm's scheduled time (for recurring alarms)\n */\n async updateAlarm(options: AlarmScheduleOptions): Promise<void> {\n await this.ensureInitialized();\n await this.sql.exec(\n \"UPDATE alarms SET scheduled_at = ?, repeat_interval = ?, payload = ? WHERE id = ?\",\n options.scheduledAt,\n options.repeatInterval ?? null,\n JSON.stringify(options.payload),\n options.id\n );\n }\n\n /**\n * Delete an alarm by ID\n */\n async deleteAlarm(id: string): Promise<void> {\n await this.ensureInitialized();\n await this.sql.exec(\"DELETE FROM alarms WHERE id = ?\", id);\n }\n\n /**\n * Delete all alarms of a specific type\n */\n async deleteAlarmsByType(type: string): Promise<void> {\n await this.ensureInitialized();\n await this.sql.exec(\"DELETE FROM alarms WHERE type = ?\", type);\n }\n\n // ==================== Actor Metadata ====================\n\n /**\n * Get actor metadata by ID\n */\n async getActorMeta(actorId?: string): Promise<ActorMeta | null> {\n await this.ensureInitialized();\n\n if (!actorId) {\n // Get the first (and only) actor metadata\n const result = await this.sql.exec(\n \"SELECT actor_id, actor_type, initial_caller, input, created_at, updated_at FROM actor_meta LIMIT 1\"\n );\n const rows = (await this.parseRows(result)) as ActorMetaRecord[];\n if (rows.length === 0) return null;\n\n const row = rows[0];\n return {\n actorId: row.actor_id,\n actorType: row.actor_type,\n initialCaller: JSON.parse(row.initial_caller) as Caller,\n input: JSON.parse(row.input),\n };\n }\n\n const result = await this.sql.exec(\n \"SELECT actor_id, actor_type, initial_caller, input, created_at, updated_at FROM actor_meta WHERE actor_id = ?\",\n actorId\n );\n const rows = (await this.parseRows(result)) as ActorMetaRecord[];\n if (rows.length === 0) return null;\n\n const row = rows[0];\n return {\n actorId: row.actor_id,\n actorType: row.actor_type,\n initialCaller: JSON.parse(row.initial_caller) as Caller,\n input: JSON.parse(row.input),\n };\n }\n\n /**\n * Set actor metadata\n */\n async setActorMeta(meta: ActorMeta): Promise<void> {\n await this.ensureInitialized();\n const now = Date.now();\n await this.sql.exec(\n `INSERT INTO actor_meta (actor_id, actor_type, initial_caller, input, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(actor_id) DO UPDATE SET\n actor_type = excluded.actor_type,\n initial_caller = excluded.initial_caller,\n input = excluded.input,\n updated_at = excluded.updated_at`,\n meta.actorId,\n meta.actorType,\n JSON.stringify(meta.initialCaller),\n JSON.stringify(meta.input),\n now,\n now\n );\n }\n\n /**\n * Delete actor metadata\n */\n async deleteActorMeta(actorId: string): Promise<void> {\n await this.ensureInitialized();\n await this.sql.exec(\"DELETE FROM actor_meta WHERE actor_id = ?\", actorId);\n }\n\n // ==================== Snapshots ====================\n\n /**\n * Get a snapshot by actor ID\n */\n async getSnapshot(actorId: string): Promise<Snapshot | null> {\n await this.ensureInitialized();\n const result = await this.sql.exec(\n \"SELECT actor_id, snapshot, checksum, updated_at FROM snapshots WHERE actor_id = ?\",\n actorId\n );\n const rows = (await this.parseRows(result)) as SnapshotRecord[];\n if (rows.length === 0) return null;\n\n const row = rows[0];\n return {\n actorId: row.actor_id,\n snapshot: JSON.parse(row.snapshot),\n checksum: row.checksum ?? undefined,\n };\n }\n\n /**\n * Set a snapshot for an actor\n */\n async setSnapshot(actorId: string, snapshot: unknown, checksum?: string): Promise<void> {\n await this.ensureInitialized();\n await this.sql.exec(\n `INSERT INTO snapshots (actor_id, snapshot, checksum, updated_at)\n VALUES (?, ?, ?, ?)\n ON CONFLICT(actor_id) DO UPDATE SET\n snapshot = excluded.snapshot,\n checksum = excluded.checksum,\n updated_at = excluded.updated_at`,\n actorId,\n JSON.stringify(snapshot),\n checksum ?? null,\n Date.now()\n );\n }\n\n /**\n * Delete a snapshot\n */\n async deleteSnapshot(actorId: string): Promise<void> {\n await this.ensureInitialized();\n await this.sql.exec(\"DELETE FROM snapshots WHERE actor_id = ?\", actorId);\n }\n\n // ==================== Migration Helpers ====================\n\n /**\n * Migrate data from legacy KV storage to SQLite\n * This is a one-time migration helper\n */\n async migrateFromKV(storage: DurableObjectStorage): Promise<void> {\n await this.ensureInitialized();\n\n // Migrate actor metadata\n const [actorType, actorId, initialCallerString, inputString] = await Promise.all([\n storage.get(\"actorType\"),\n storage.get(\"actorId\"),\n storage.get(\"initialCaller\"),\n storage.get(\"input\"),\n ]);\n\n if (actorType && actorId && initialCallerString && inputString) {\n await this.setActorMeta({\n actorId: actorId as string,\n actorType: actorType as string,\n initialCaller: JSON.parse(initialCallerString as string) as Caller,\n input: JSON.parse(inputString as string),\n });\n }\n\n // Migrate persisted snapshot\n const persistedSnapshot = await storage.get(PERSISTED_SNAPSHOT_KEY);\n if (persistedSnapshot) {\n const snapshot = JSON.parse(persistedSnapshot as string);\n await this.setSnapshot(actorId as string, snapshot);\n }\n }\n\n // ==================== Utility Methods ====================\n\n /**\n * Parse SQL result rows - handles both arrays and cursors\n */\n private async parseRows(result: any): Promise<unknown[]> {\n // Check if result is an async iterable (cursor)\n if (result && typeof result[Symbol.asyncIterator] === \"function\") {\n const cursor = result as AsyncIterable<{ columns: string[]; results: (string | number | null)[][] }>;\n const rows: unknown[] = [];\n let columns: string[] | null = null;\n\n for await (const batch of cursor) {\n if (!columns) columns = batch.columns;\n for (const row of batch.results) {\n const obj: Record<string, unknown> = {};\n (columns ?? []).forEach((col, i) => {\n obj[col] = row[i];\n });\n rows.push(obj);\n }\n }\n return rows;\n }\n\n // Handle row batches returned by sql.exec()\n const batches = Array.isArray(result) ? result : result ? [result] : [];\n if (batches.length === 0) return [];\n\n const first = batches[0] as {\n columns?: string[];\n columnNames?: string[];\n rows?: unknown[][];\n results?: unknown[][];\n };\n\n const columns = first?.columns ?? first?.columnNames ?? [];\n const rows = first?.rows ?? first?.results ?? [];\n if (!columns.length || !rows.length) return [];\n\n return rows.map((row: unknown[]) => {\n const obj: Record<string, unknown> = {};\n columns.forEach((col: string, i: number) => {\n obj[col] = row[i];\n });\n return obj;\n });\n }\n}\n","import type {\n ActorKitStorage,\n AlarmRecord,\n AlarmScheduleOptions,\n} from \"./storage\";\n\n/**\n * Supported alarm types\n */\nexport type AlarmType = \"xstate-delay\" | \"cache-cleanup\" | \"custom\";\n\n/**\n * Alarm data from the database with parsed payload\n */\nexport interface Alarm {\n id: string;\n type: AlarmType;\n scheduledAt: number;\n repeatInterval?: number;\n payload: Record<string, unknown>;\n createdAt: number;\n}\n\n/**\n * Options for scheduling a new alarm\n */\nexport interface ScheduleAlarmOptions {\n id: string;\n type: AlarmType;\n scheduledAt: number;\n repeatInterval?: number;\n payload: Record<string, unknown>;\n}\n\n/**\n * Result from handling an alarm\n */\nexport interface AlarmHandleResult {\n id: string;\n type: AlarmType;\n rescheduled?: boolean;\n deleted: boolean;\n}\n\n/**\n * Manages alarms for a Durable Object using SQLite storage\n * and the Durable Object alarm API\n */\nexport class AlarmManager {\n private storage: ActorKitStorage;\n private state: DurableObjectState;\n private currentAlarmId: string | null = null;\n private currentAlarmTime: number | null = null;\n\n constructor(storage: ActorKitStorage, state: DurableObjectState) {\n this.storage = storage;\n this.state = state;\n }\n\n /**\n * Schedule a new alarm\n */\n async schedule(options: ScheduleAlarmOptions): Promise<void> {\n await this.storage.insertAlarm(options);\n await this.rescheduleNextAlarm();\n }\n\n /**\n * Cancel an alarm by ID\n */\n async cancel(id: string): Promise<void> {\n await this.storage.deleteAlarm(id);\n // If we canceled the current alarm, reschedule\n if (this.currentAlarmId === id) {\n await this.rescheduleNextAlarm();\n }\n }\n\n /**\n * Cancel all alarms of a specific type\n */\n async cancelByType(type: AlarmType): Promise<void> {\n await this.storage.deleteAlarmsByType(type);\n await this.rescheduleNextAlarm();\n }\n\n /**\n * Get all pending alarms\n */\n async getPendingAlarms(): Promise<Alarm[]> {\n const records = await this.storage.getAlarms();\n return records.map(this.parseAlarmRecord);\n }\n\n /**\n * Get alarms that are due now or before a given time\n */\n async getDueAlarms(before: number = Date.now()): Promise<Alarm[]> {\n const records = await this.storage.getDueAlarms(before);\n return records.map(this.parseAlarmRecord);\n }\n\n /**\n * Delete an alarm after it has been handled\n */\n async deleteAlarm(id: string): Promise<void> {\n await this.storage.deleteAlarm(id);\n }\n\n /**\n * Update an alarm (for rescheduling recurring alarms)\n */\n async updateAlarm(options: ScheduleAlarmOptions): Promise<void> {\n await this.storage.updateAlarm(options);\n }\n\n /**\n * Reschedule the next DO alarm based on the earliest alarm in storage\n * This sets the actual Durable Object alarm that will trigger the alarm() handler\n */\n async rescheduleNextAlarm(): Promise<void> {\n const earliest = await this.storage.getEarliestAlarm();\n\n if (!earliest) {\n // No alarms pending, clear the DO alarm\n this.currentAlarmId = null;\n this.currentAlarmTime = null;\n // Note: There's no way to \"clear\" a DO alarm, but we can set one far in the future\n // or just let it expire naturally\n return;\n }\n\n // Only set a new alarm if the earliest one is different from current\n if (this.currentAlarmId !== earliest.id || this.currentAlarmTime !== earliest.scheduled_at) {\n this.currentAlarmId = earliest.id;\n this.currentAlarmTime = earliest.scheduled_at;\n await this.state.storage.setAlarm(earliest.scheduled_at);\n }\n }\n\n /**\n * Handle due alarms and return results\n * This should be called from the Durable Object's alarm() handler\n */\n async handleDueAlarms(handler: (alarm: Alarm) => Promise<boolean>): Promise<AlarmHandleResult[]> {\n const now = Date.now();\n const dueAlarms = await this.getDueAlarms(now);\n const results: AlarmHandleResult[] = [];\n\n for (const alarm of dueAlarms) {\n let rescheduled = false;\n let deleted = true;\n\n if (alarm.repeatInterval) {\n // Recurring alarm - reschedule it\n const nextScheduledAt = now + alarm.repeatInterval;\n await this.updateAlarm({\n id: alarm.id,\n type: alarm.type,\n scheduledAt: nextScheduledAt,\n repeatInterval: alarm.repeatInterval,\n payload: alarm.payload,\n });\n rescheduled = true;\n deleted = false;\n } else {\n // One-time alarm - delete it\n await this.deleteAlarm(alarm.id);\n }\n\n // Call the handler and let it perform the alarm-specific action\n try {\n await handler(alarm);\n } catch (error) {\n console.error(`Error handling alarm ${alarm.id}:`, error);\n }\n\n results.push({\n id: alarm.id,\n type: alarm.type,\n rescheduled,\n deleted,\n });\n }\n\n // Reschedule the next DO alarm\n await this.rescheduleNextAlarm();\n\n return results;\n }\n\n /**\n * Get the current scheduled DO alarm info\n */\n getCurrentAlarm(): { id: string | null; time: number | null } {\n return {\n id: this.currentAlarmId,\n time: this.currentAlarmTime,\n };\n }\n\n /**\n * Parse an alarm record from the database into an Alarm object\n */\n private parseAlarmRecord(record: AlarmRecord): Alarm {\n return {\n id: record.id,\n type: record.type as AlarmType,\n scheduledAt: record.scheduled_at,\n repeatInterval: record.repeat_interval ?? undefined,\n payload: record.payload ? JSON.parse(record.payload) : {},\n createdAt: record.created_at,\n };\n }\n}\n\n/**\n * Generate a unique alarm ID\n */\nexport function generateAlarmId(): string {\n return `alarm-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n}\n\n/**\n * Calculate the next scheduled time for a recurring alarm\n */\nexport function calculateNextRecurringAlarm(\n baseTime: number,\n interval: number,\n now: number = Date.now()\n): number {\n let next = baseTime;\n while (next < now) {\n next += interval;\n }\n return next;\n}\n","import type { AnyActorRef, AnyEventObject } from \"xstate\";\nimport type { AlarmManager } from \"./alarms\";\n\n/**\n * Serializable data stored with each alarm for XState delayed events\n */\nexport interface XStateAlarmData {\n type: \"xstate-delay\";\n sourceSessionId: string;\n targetSessionId: string;\n event: AnyEventObject;\n scheduledEventId: string;\n alarmId: string;\n [key: string]: unknown; // Index signature for Record<string, unknown> compatibility\n}\n\n/**\n * Snapshot of scheduled events for persistence\n */\nexport interface ScheduledEventSnapshot {\n sourceSessionId: string;\n targetSessionId: string;\n event: AnyEventObject;\n delay: number;\n id: string;\n startedAt: number;\n}\n\n/**\n * Clock interface for compatibility with XState\n */\nexport interface Clock {\n setTimeout: (fn: () => void, delay: number) => unknown;\n clearTimeout: (id: unknown) => void;\n}\n\n/**\n * Simple no-op clock for XState actors that use alarm-based scheduling\n * This clock doesn't actually schedule anything - delays are handled via alarms\n */\nexport const NOOP_CLOCK: Clock = {\n setTimeout: () => Math.random(), // Return a fake ID\n clearTimeout: () => {\n // No-op - alarms manage cancellation\n },\n};\n\n/**\n * Map to track scheduled events by their scheduledEventId\n * This is used to look up event data when an alarm fires\n */\nconst scheduledEventsMap = new Map<string, ScheduledEventSnapshot>();\n\n/**\n * Create an alarm-based scheduler for XState actors\n * This replaces the default setTimeout-based scheduler with one that uses Durable Object alarms\n *\n * @param alarmManager - The alarm manager to schedule alarms with\n * @param system - The XState ActorSystem (used to relay events)\n * @returns A scheduler object with schedule, cancel, and cancelAll methods\n */\nexport function createAlarmScheduler(\n alarmManager: AlarmManager,\n system: any\n): {\n schedule: (\n source: AnyActorRef,\n target: AnyActorRef,\n event: AnyEventObject,\n delay: number,\n id?: string\n ) => void;\n cancel: (source: AnyActorRef, id: string) => void;\n cancelAll: (actorRef: AnyActorRef) => void;\n} {\n return {\n schedule: (\n source: AnyActorRef,\n target: AnyActorRef,\n event: AnyEventObject,\n delay: number,\n id: string = Math.random().toString(36).slice(2)\n ) => {\n const scheduledEventId = `${source.sessionId}.${id}`;\n\n // Store the event data for later retrieval\n const snapshot: ScheduledEventSnapshot = {\n sourceSessionId: source.sessionId,\n targetSessionId: target.sessionId,\n event,\n delay,\n id,\n startedAt: Date.now(),\n };\n scheduledEventsMap.set(scheduledEventId, snapshot);\n\n // Schedule the alarm\n const alarmId = `xstate-${scheduledEventId}`;\n\n alarmManager.schedule({\n id: alarmId,\n type: \"xstate-delay\",\n scheduledAt: Date.now() + delay,\n payload: {\n type: \"xstate-delay\",\n sourceSessionId: source.sessionId,\n targetSessionId: target.sessionId,\n event,\n scheduledEventId,\n alarmId,\n },\n }).catch((error) => {\n console.error(`[AlarmScheduler] Error scheduling alarm:`, error);\n scheduledEventsMap.delete(scheduledEventId);\n });\n },\n\n cancel: (source: AnyActorRef, id: string) => {\n const scheduledEventId = `${source.sessionId}.${id}`;\n\n // Remove from our tracking map\n scheduledEventsMap.delete(scheduledEventId);\n\n // Cancel the alarm\n alarmManager.cancel(`xstate-${scheduledEventId}`).catch((error) => {\n console.error(`[AlarmScheduler] Error canceling alarm:`, error);\n });\n },\n\n cancelAll: (actorRef: AnyActorRef) => {\n // Find all events for this actor\n const eventsToCancel: string[] = [];\n\n for (const [scheduledEventId, snapshot] of scheduledEventsMap.entries()) {\n if (snapshot.sourceSessionId === actorRef.sessionId) {\n eventsToCancel.push(scheduledEventId);\n }\n }\n\n // Cancel each event\n for (const scheduledEventId of eventsToCancel) {\n scheduledEventsMap.delete(scheduledEventId);\n alarmManager.cancel(`xstate-${scheduledEventId}`).catch((error) => {\n console.error(`[AlarmScheduler] Error canceling alarm:`, error);\n });\n }\n },\n };\n}\n\n/**\n * Handle an XState delayed event alarm\n * This should be called from the Durable Object's alarm() handler\n *\n * @param alarmData - The alarm data from the XState alarm\n * @param actor - The actor to send the event to\n */\nexport async function handleXStateAlarm(\n alarmData: XStateAlarmData,\n actor: any\n): Promise<void> {\n const { scheduledEventId, event } = alarmData;\n\n // Remove from tracking map\n scheduledEventsMap.delete(scheduledEventId);\n\n // Send the event to the actor\n try {\n // Use the actor's internal _relay method to deliver the event\n if (actor.system && actor.system._relay) {\n actor.system._relay(actor, actor, event);\n } else {\n // Fallback: send directly to the actor\n actor.send(event);\n }\n } catch (error) {\n console.error(`[AlarmScheduler] Error handling XState alarm:`, error);\n }\n}\n\n/**\n * Get all scheduled events (useful for debugging/inspection)\n */\nexport function getScheduledEvents(): Map<string, ScheduledEventSnapshot> {\n return new Map(scheduledEventsMap);\n}\n\n/**\n * Restore scheduled events from storage (called after DO hibernation)\n */\nexport function restoreScheduledEvents(\n alarms: Array<{ payload: XStateAlarmData; scheduledAt: number }>\n): void {\n for (const alarm of alarms) {\n if (alarm.payload.type === \"xstate-delay\") {\n const { sourceSessionId, targetSessionId, event, scheduledEventId } = alarm.payload;\n const delay = alarm.scheduledAt - Date.now();\n\n // Only restore if the alarm is still in the future\n if (delay > 0) {\n scheduledEventsMap.set(scheduledEventId, {\n sourceSessionId,\n targetSessionId,\n event,\n delay,\n id: scheduledEventId.split(\".\").pop() || scheduledEventId,\n startedAt: alarm.scheduledAt - delay,\n });\n }\n }\n }\n}\n"],"names":["BotManagementSchema","z","object","corporateProxy","boolean","verifiedBot","jsDetection","passed","staticResource","detectionIds","record","string","any","score","number","EnvironmentSchema","ACTOR_KIT_SECRET","ACTOR_KIT_HOST","RequestInfoSchema","longitude","latitude","continent","country","city","timezone","postalCode","region","regionCode","metroCode","botManagement","CallerSchema","id","type","enum","AnyEventSchema","SystemEventSchema","discriminatedUnion","literal","caller","connectingCaller","disconnectingCaller","operations","array","CallerIdTypeSchema","CallerStringSchema","transform","val","ctx","callerTypeParseResult","safeParse","split","success","addIssue","code","ZodIssueCode","custom","message","NEVER","data","substring","indexOf","uuid","HEADERS","X_CALLER_ID","X_CALLER_TYPE","X_ACTOR_ID","X_ACTOR_TYPE","CallerTypes","client","system","service","AlarmTypes","PERSISTED_SNAPSHOT_KEY","ActorKitStorage","storage","initialized","sql","constructor","this","ensureInitialized","exec","error","console","getAlarms","result","parseRows","getDueAlarms","before","getEarliestAlarm","insertAlarm","options","scheduledAt","repeatInterval","JSON","stringify","payload","Date","now","updateAlarm","deleteAlarm","deleteAlarmsByType","getActorMeta","actorId","rows","length","row","actor_id","actorType","actor_type","initialCaller","parse","initial_caller","input","setActorMeta","meta","deleteActorMeta","getSnapshot","snapshot","checksum","undefined","setSnapshot","deleteSnapshot","migrateFromKV","initialCallerString","inputString","Promise","all","get","persistedSnapshot","Symbol","asyncIterator","cursor","columns","batch","results","obj","forEach","col","i","push","batches","Array","isArray","first","columnNames","map","AlarmManager","state","currentAlarmId","currentAlarmTime","schedule","rescheduleNextAlarm","cancel","cancelByType","getPendingAlarms","parseAlarmRecord","earliest","scheduled_at","setAlarm","handleDueAlarms","handler","dueAlarms","alarm","rescheduled","deleted","nextScheduledAt","getCurrentAlarm","time","repeat_interval","createdAt","created_at","generateAlarmId","Math","random","toString","slice","calculateNextRecurringAlarm","baseTime","interval","next","NOOP_CLOCK","setTimeout","clearTimeout","scheduledEventsMap","Map","createAlarmScheduler","alarmManager","source","target","event","delay","scheduledEventId","sessionId","sourceSessionId","targetSessionId","startedAt","set","alarmId","catch","delete","cancelAll","actorRef","eventsToCancel","entries","async","handleXStateAlarm","alarmData","actor","_relay","send","getScheduledEvents","restoreScheduledEvents","alarms","pop"],"mappings":"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"}
package/dist/react.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import React, { ReactNode } from 'react';
2
- import { AnyEventObject, StateMachine, StateValueFrom, AnyStateMachine, SnapshotFrom } from 'xstate';
2
+ import { AnyStateMachine, SnapshotFrom, EventFromLogic, StateValueFrom } from 'xstate';
3
3
  import { DurableObject } from 'cloudflare:workers';
4
4
  import { z } from 'zod';
5
5
 
@@ -19,252 +19,26 @@ declare const RequestInfoSchema: z.ZodObject<{
19
19
  verifiedBot: z.ZodBoolean;
20
20
  jsDetection: z.ZodObject<{
21
21
  passed: z.ZodBoolean;
22
- }, "strip", z.ZodTypeAny, {
23
- passed: boolean;
24
- }, {
25
- passed: boolean;
26
- }>;
22
+ }, z.core.$strip>;
27
23
  staticResource: z.ZodBoolean;
28
24
  detectionIds: z.ZodRecord<z.ZodString, z.ZodAny>;
29
25
  score: z.ZodNumber;
30
- }, "strip", z.ZodTypeAny, {
31
- corporateProxy: boolean;
32
- verifiedBot: boolean;
33
- jsDetection: {
34
- passed: boolean;
35
- };
36
- staticResource: boolean;
37
- detectionIds: Record<string, any>;
38
- score: number;
39
- }, {
40
- corporateProxy: boolean;
41
- verifiedBot: boolean;
42
- jsDetection: {
43
- passed: boolean;
44
- };
45
- staticResource: boolean;
46
- detectionIds: Record<string, any>;
47
- score: number;
48
- }>;
49
- }, "strip", z.ZodTypeAny, {
50
- longitude: string;
51
- latitude: string;
52
- continent: string;
53
- country: string;
54
- city: string;
55
- timezone: string;
56
- postalCode: string;
57
- region: string;
58
- regionCode: string;
59
- metroCode: string;
60
- botManagement: {
61
- corporateProxy: boolean;
62
- verifiedBot: boolean;
63
- jsDetection: {
64
- passed: boolean;
65
- };
66
- staticResource: boolean;
67
- detectionIds: Record<string, any>;
68
- score: number;
69
- };
70
- }, {
71
- longitude: string;
72
- latitude: string;
73
- continent: string;
74
- country: string;
75
- city: string;
76
- timezone: string;
77
- postalCode: string;
78
- region: string;
79
- regionCode: string;
80
- metroCode: string;
81
- botManagement: {
82
- corporateProxy: boolean;
83
- verifiedBot: boolean;
84
- jsDetection: {
85
- passed: boolean;
86
- };
87
- staticResource: boolean;
88
- detectionIds: Record<string, any>;
89
- score: number;
90
- };
91
- }>;
26
+ }, z.core.$strip>;
27
+ }, z.core.$strip>;
92
28
  declare const CallerSchema: z.ZodObject<{
93
29
  id: z.ZodString;
94
- type: z.ZodEnum<["client", "system", "service"]>;
95
- }, "strip", z.ZodTypeAny, {
96
- type: "client" | "system" | "service";
97
- id: string;
98
- }, {
99
- type: "client" | "system" | "service";
100
- id: string;
101
- }>;
102
- declare const SystemEventSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
103
- type: z.ZodLiteral<"INITIALIZE">;
104
- caller: z.ZodObject<{
105
- type: z.ZodLiteral<"system">;
106
- id: z.ZodString;
107
- }, "strip", z.ZodTypeAny, {
108
- type: "system";
109
- id: string;
110
- }, {
111
- type: "system";
112
- id: string;
113
- }>;
114
- }, "strip", z.ZodTypeAny, {
115
- type: "INITIALIZE";
116
- caller: {
117
- type: "system";
118
- id: string;
119
- };
120
- }, {
121
- type: "INITIALIZE";
122
- caller: {
123
- type: "system";
124
- id: string;
125
- };
126
- }>, z.ZodObject<{
127
- type: z.ZodLiteral<"CONNECT">;
128
- caller: z.ZodObject<{
129
- type: z.ZodLiteral<"system">;
130
- id: z.ZodString;
131
- }, "strip", z.ZodTypeAny, {
132
- type: "system";
133
- id: string;
134
- }, {
135
- type: "system";
136
- id: string;
137
- }>;
138
- connectingCaller: z.ZodObject<{
139
- id: z.ZodString;
140
- type: z.ZodEnum<["client", "system", "service"]>;
141
- }, "strip", z.ZodTypeAny, {
142
- type: "client" | "system" | "service";
143
- id: string;
144
- }, {
145
- type: "client" | "system" | "service";
146
- id: string;
147
- }>;
148
- }, "strip", z.ZodTypeAny, {
149
- type: "CONNECT";
150
- caller: {
151
- type: "system";
152
- id: string;
153
- };
154
- connectingCaller: {
155
- type: "client" | "system" | "service";
156
- id: string;
157
- };
158
- }, {
159
- type: "CONNECT";
160
- caller: {
161
- type: "system";
162
- id: string;
163
- };
164
- connectingCaller: {
165
- type: "client" | "system" | "service";
166
- id: string;
167
- };
168
- }>, z.ZodObject<{
169
- type: z.ZodLiteral<"DISCONNECT">;
170
- caller: z.ZodObject<{
171
- type: z.ZodLiteral<"system">;
172
- id: z.ZodString;
173
- }, "strip", z.ZodTypeAny, {
174
- type: "system";
175
- id: string;
176
- }, {
177
- type: "system";
178
- id: string;
179
- }>;
180
- disconnectingCaller: z.ZodObject<{
181
- id: z.ZodString;
182
- type: z.ZodEnum<["client", "system", "service"]>;
183
- }, "strip", z.ZodTypeAny, {
184
- type: "client" | "system" | "service";
185
- id: string;
186
- }, {
187
- type: "client" | "system" | "service";
188
- id: string;
189
- }>;
190
- }, "strip", z.ZodTypeAny, {
191
- type: "DISCONNECT";
192
- caller: {
193
- type: "system";
194
- id: string;
195
- };
196
- disconnectingCaller: {
197
- type: "client" | "system" | "service";
198
- id: string;
199
- };
200
- }, {
201
- type: "DISCONNECT";
202
- caller: {
203
- type: "system";
204
- id: string;
205
- };
206
- disconnectingCaller: {
207
- type: "client" | "system" | "service";
208
- id: string;
209
- };
210
- }>, z.ZodObject<{
211
- type: z.ZodLiteral<"RESUME">;
212
- caller: z.ZodObject<{
213
- type: z.ZodLiteral<"system">;
214
- id: z.ZodString;
215
- }, "strip", z.ZodTypeAny, {
216
- type: "system";
217
- id: string;
218
- }, {
219
- type: "system";
220
- id: string;
30
+ type: z.ZodEnum<{
31
+ client: "client";
32
+ system: "system";
33
+ service: "service";
221
34
  }>;
222
- }, "strip", z.ZodTypeAny, {
223
- type: "RESUME";
224
- caller: {
225
- type: "system";
226
- id: string;
227
- };
228
- }, {
229
- type: "RESUME";
230
- caller: {
231
- type: "system";
232
- id: string;
233
- };
234
- }>, z.ZodObject<{
235
- type: z.ZodLiteral<"MIGRATE">;
236
- caller: z.ZodObject<{
237
- type: z.ZodLiteral<"system">;
238
- id: z.ZodString;
239
- }, "strip", z.ZodTypeAny, {
240
- type: "system";
241
- id: string;
242
- }, {
243
- type: "system";
244
- id: string;
245
- }>;
246
- operations: z.ZodArray<z.ZodAny, "many">;
247
- }, "strip", z.ZodTypeAny, {
248
- type: "MIGRATE";
249
- caller: {
250
- type: "system";
251
- id: string;
252
- };
253
- operations: any[];
254
- }, {
255
- type: "MIGRATE";
256
- caller: {
257
- type: "system";
258
- id: string;
259
- };
260
- operations: any[];
261
- }>]>;
35
+ }, z.core.$strip>;
262
36
 
263
37
  type EnvWithDurableObjects = {
264
38
  ACTOR_KIT_SECRET: string;
265
39
  [key: string]: DurableObjectNamespace<ActorServer<any>> | unknown;
266
40
  };
267
- interface ActorServerMethods<TMachine extends BaseActorKitStateMachine> {
41
+ interface ActorServerMethods<TMachine extends AnyStateMachine> {
268
42
  fetch(request: Request): Promise<Response>;
269
43
  spawn(props: {
270
44
  actorType: string;
@@ -283,60 +57,17 @@ interface ActorServerMethods<TMachine extends BaseActorKitStateMachine> {
283
57
  snapshot: CallerSnapshotFrom<TMachine>;
284
58
  }>;
285
59
  }
286
- type ActorServer<TMachine extends AnyActorKitStateMachine> = DurableObject & ActorServerMethods<TMachine>;
60
+ type ActorServer<TMachine extends AnyStateMachine> = DurableObject & ActorServerMethods<TMachine>;
287
61
  type Caller = z.infer<typeof CallerSchema>;
288
62
  type RequestInfo = z.infer<typeof RequestInfoSchema>;
289
63
  type CallerType = "client" | "system" | "service";
290
- type EventObject = {
291
- type: string;
292
- };
293
- type BaseActorKitContext<TPublicProps extends {
294
- [key: string]: unknown;
295
- }, TPrivateProps extends {
296
- [key: string]: unknown;
297
- }> = {
298
- public: TPublicProps;
299
- private: Record<string, TPrivateProps>;
300
- };
301
- type ActorKitStateMachine<TEvent extends BaseActorKitEvent<EnvWithDurableObjects>, TInput extends {
302
- id: string;
303
- caller: Caller;
304
- storage: DurableObjectStorage;
305
- }, TContext extends BaseActorKitContext<any, any> & {
306
- [key: string]: unknown;
307
- }> = StateMachine<TContext, TEvent & EventObject, any, any, any, any, any, any, any, TInput, any, any, any, any>;
308
- type BaseActorKitInput<TEnv = EnvWithDurableObjects> = {
309
- id: string;
310
- caller: Caller;
311
- env: TEnv;
312
- storage: DurableObjectStorage;
313
- };
314
- type WithActorKitInput<TInputProps extends {
315
- [key: string]: unknown;
316
- }, TEnv extends EnvWithDurableObjects> = TInputProps & BaseActorKitInput<TEnv>;
317
- type AnyActorKitStateMachine = ActorKitStateMachine<any, any, any>;
318
- type AnyActorKitEvent = (WithActorKitEvent<AnyEventObject, "client"> | WithActorKitEvent<AnyEventObject, "service"> | ActorKitSystemEvent) & BaseActorKitEvent<EnvWithDurableObjects>;
319
- type AnyActorKitInput = WithActorKitInput<{
320
- [key: string]: unknown;
321
- }, EnvWithDurableObjects> & {
322
- storage: DurableObjectStorage;
323
- };
324
- type AnyActorKitContext = {
325
- public: {
326
- [key: string]: unknown;
327
- };
328
- private: Record<string, {
329
- [key: string]: unknown;
330
- }>;
331
- };
332
- type BaseActorKitStateMachine = ActorKitStateMachine<AnyActorKitEvent, AnyActorKitInput, AnyActorKitContext>;
64
+ type AnyActorKitStateMachine = AnyStateMachine;
333
65
  interface BaseActorKitEvent<TEnv extends EnvWithDurableObjects> {
334
66
  caller: Caller;
335
67
  storage: DurableObjectStorage;
336
68
  requestInfo?: RequestInfo;
337
69
  env: TEnv;
338
70
  }
339
- type ActorKitSystemEvent = z.infer<typeof SystemEventSchema>;
340
71
  type WithActorKitEvent<T extends {
341
72
  type: string;
342
73
  }, C extends CallerType> = T & BaseActorKitEvent<EnvWithDurableObjects> & {
@@ -359,16 +90,16 @@ type CallerSnapshotFrom<TMachine extends AnyStateMachine> = {
359
90
  value: infer V;
360
91
  } ? V : unknown;
361
92
  };
362
- type ClientEventFrom<T extends AnyActorKitStateMachine> = T extends StateMachine<any, infer TEvent, any, any, any, any, any, any, any, any, any, any, any, any> ? TEvent extends WithActorKitEvent<infer E, "client"> ? Omit<E, keyof BaseActorKitEvent<EnvWithDurableObjects>> : never : never;
363
- type ServiceEventFrom<T extends AnyActorKitStateMachine> = T extends StateMachine<any, infer TEvent, any, any, any, any, any, any, any, any, any, any, any, any> ? TEvent extends WithActorKitEvent<infer E, "service"> ? Omit<E, keyof BaseActorKitEvent<EnvWithDurableObjects>> : never : never;
364
- interface MatchesProps<TMachine extends AnyActorKitStateMachine> {
93
+ type ClientEventFrom<T extends AnyStateMachine> = EventFromLogic<T> extends infer TEvent ? TEvent extends WithActorKitEvent<infer E, "client"> ? Omit<E, keyof BaseActorKitEvent<EnvWithDurableObjects>> : Omit<TEvent, keyof BaseActorKitEvent<EnvWithDurableObjects>> : never;
94
+ type ServiceEventFrom<T extends AnyStateMachine> = EventFromLogic<T> extends infer TEvent ? TEvent extends WithActorKitEvent<infer E, "service"> ? Omit<E, keyof BaseActorKitEvent<EnvWithDurableObjects>> : never : never;
95
+ interface MatchesProps<TMachine extends AnyStateMachine> {
365
96
  state: StateValueFrom<TMachine>;
366
97
  and?: StateValueFrom<TMachine>;
367
98
  or?: StateValueFrom<TMachine>;
368
99
  not?: boolean;
369
100
  initialValueOverride?: boolean;
370
101
  }
371
- type ActorKitClient<TMachine extends AnyActorKitStateMachine> = {
102
+ type ActorKitClient<TMachine extends AnyStateMachine> = {
372
103
  connect: () => Promise<void>;
373
104
  disconnect: () => void;
374
105
  send: (event: ClientEventFrom<TMachine>) => void;
@@ -388,7 +119,7 @@ type ActorKitClientProps<TMachine extends AnyActorKitStateMachine> = {
388
119
  onError?: (error: Error) => void;
389
120
  };
390
121
 
391
- declare function createActorKitContext<TMachine extends AnyActorKitStateMachine>(actorType: string): {
122
+ declare function createActorKitContext<TMachine extends AnyStateMachine>(actorType: string): {
392
123
  Provider: React.FC<{
393
124
  children: ReactNode;
394
125
  } & Omit<ActorKitClientProps<TMachine>, "actorType">>;
@@ -414,3 +145,4 @@ declare function createActorKitContext<TMachine extends AnyActorKitStateMachine>
414
145
  };
415
146
 
416
147
  export { createActorKitContext };
148
+ export type { ActorKitClient, BaseActorKitEvent, CallerSnapshotFrom, ClientEventFrom, MatchesProps, ServiceEventFrom };