@methodacting/actor-kit 0.47.0

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.
Files changed (79) hide show
  1. package/LICENSE.md +7 -0
  2. package/README.md +2042 -0
  3. package/dist/browser.d.ts +384 -0
  4. package/dist/browser.js +2 -0
  5. package/dist/browser.js.map +1 -0
  6. package/dist/index.d.ts +644 -0
  7. package/dist/index.js +2 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/react.d.ts +416 -0
  10. package/dist/react.js +2 -0
  11. package/dist/react.js.map +1 -0
  12. package/dist/src/alarms.d.ts +47 -0
  13. package/dist/src/alarms.d.ts.map +1 -0
  14. package/dist/src/browser.d.ts +2 -0
  15. package/dist/src/browser.d.ts.map +1 -0
  16. package/dist/src/constants.d.ts +12 -0
  17. package/dist/src/constants.d.ts.map +1 -0
  18. package/dist/src/createAccessToken.d.ts +9 -0
  19. package/dist/src/createAccessToken.d.ts.map +1 -0
  20. package/dist/src/createActorFetch.d.ts +18 -0
  21. package/dist/src/createActorFetch.d.ts.map +1 -0
  22. package/dist/src/createActorKitClient.d.ts +13 -0
  23. package/dist/src/createActorKitClient.d.ts.map +1 -0
  24. package/dist/src/createActorKitContext.d.ts +29 -0
  25. package/dist/src/createActorKitContext.d.ts.map +1 -0
  26. package/dist/src/createActorKitMockClient.d.ts +11 -0
  27. package/dist/src/createActorKitMockClient.d.ts.map +1 -0
  28. package/dist/src/createActorKitRouter.d.ts +4 -0
  29. package/dist/src/createActorKitRouter.d.ts.map +1 -0
  30. package/dist/src/createMachineServer.d.ts +20 -0
  31. package/dist/src/createMachineServer.d.ts.map +1 -0
  32. package/dist/src/durable-object-system.d.ts +36 -0
  33. package/dist/src/durable-object-system.d.ts.map +1 -0
  34. package/dist/src/index.d.ts +7 -0
  35. package/dist/src/index.d.ts.map +1 -0
  36. package/dist/src/react.d.ts +2 -0
  37. package/dist/src/react.d.ts.map +1 -0
  38. package/dist/src/schemas.d.ts +312 -0
  39. package/dist/src/schemas.d.ts.map +1 -0
  40. package/dist/src/server.d.ts +3 -0
  41. package/dist/src/server.d.ts.map +1 -0
  42. package/dist/src/storage.d.ts +64 -0
  43. package/dist/src/storage.d.ts.map +1 -0
  44. package/dist/src/storybook.d.ts +13 -0
  45. package/dist/src/storybook.d.ts.map +1 -0
  46. package/dist/src/test.d.ts +2 -0
  47. package/dist/src/test.d.ts.map +1 -0
  48. package/dist/src/types.d.ts +181 -0
  49. package/dist/src/types.d.ts.map +1 -0
  50. package/dist/src/utils.d.ts +30 -0
  51. package/dist/src/utils.d.ts.map +1 -0
  52. package/dist/src/withActorKit.d.ts +9 -0
  53. package/dist/src/withActorKit.d.ts.map +1 -0
  54. package/dist/src/worker.d.ts +3 -0
  55. package/dist/src/worker.d.ts.map +1 -0
  56. package/package.json +87 -0
  57. package/src/alarms.ts +237 -0
  58. package/src/browser.ts +1 -0
  59. package/src/constants.ts +31 -0
  60. package/src/createAccessToken.ts +29 -0
  61. package/src/createActorFetch.ts +111 -0
  62. package/src/createActorKitClient.ts +224 -0
  63. package/src/createActorKitContext.tsx +228 -0
  64. package/src/createActorKitMockClient.ts +138 -0
  65. package/src/createActorKitRouter.ts +149 -0
  66. package/src/createMachineServer.ts +844 -0
  67. package/src/durable-object-system.ts +212 -0
  68. package/src/global.d.ts +7 -0
  69. package/src/index.ts +6 -0
  70. package/src/react.ts +1 -0
  71. package/src/schemas.ts +95 -0
  72. package/src/server.ts +3 -0
  73. package/src/storage.ts +404 -0
  74. package/src/storybook.ts +42 -0
  75. package/src/test.ts +1 -0
  76. package/src/types.ts +334 -0
  77. package/src/utils.ts +171 -0
  78. package/src/withActorKit.tsx +103 -0
  79. package/src/worker.ts +2 -0
@@ -0,0 +1,212 @@
1
+ import type { AnyActorRef, AnyEventObject } from "xstate";
2
+ import type { AlarmManager } from "./alarms";
3
+
4
+ /**
5
+ * Serializable data stored with each alarm for XState delayed events
6
+ */
7
+ export interface XStateAlarmData {
8
+ type: "xstate-delay";
9
+ sourceSessionId: string;
10
+ targetSessionId: string;
11
+ event: AnyEventObject;
12
+ scheduledEventId: string;
13
+ alarmId: string;
14
+ [key: string]: unknown; // Index signature for Record<string, unknown> compatibility
15
+ }
16
+
17
+ /**
18
+ * Snapshot of scheduled events for persistence
19
+ */
20
+ export interface ScheduledEventSnapshot {
21
+ sourceSessionId: string;
22
+ targetSessionId: string;
23
+ event: AnyEventObject;
24
+ delay: number;
25
+ id: string;
26
+ startedAt: number;
27
+ }
28
+
29
+ /**
30
+ * Clock interface for compatibility with XState
31
+ */
32
+ export interface Clock {
33
+ setTimeout: (fn: () => void, delay: number) => unknown;
34
+ clearTimeout: (id: unknown) => void;
35
+ }
36
+
37
+ /**
38
+ * Simple no-op clock for XState actors that use alarm-based scheduling
39
+ * This clock doesn't actually schedule anything - delays are handled via alarms
40
+ */
41
+ export const NOOP_CLOCK: Clock = {
42
+ setTimeout: () => Math.random(), // Return a fake ID
43
+ clearTimeout: () => {
44
+ // No-op - alarms manage cancellation
45
+ },
46
+ };
47
+
48
+ /**
49
+ * Map to track scheduled events by their scheduledEventId
50
+ * This is used to look up event data when an alarm fires
51
+ */
52
+ const scheduledEventsMap = new Map<string, ScheduledEventSnapshot>();
53
+
54
+ /**
55
+ * Create an alarm-based scheduler for XState actors
56
+ * This replaces the default setTimeout-based scheduler with one that uses Durable Object alarms
57
+ *
58
+ * @param alarmManager - The alarm manager to schedule alarms with
59
+ * @param system - The XState ActorSystem (used to relay events)
60
+ * @returns A scheduler object with schedule, cancel, and cancelAll methods
61
+ */
62
+ export function createAlarmScheduler(
63
+ alarmManager: AlarmManager,
64
+ system: any
65
+ ): {
66
+ schedule: (
67
+ source: AnyActorRef,
68
+ target: AnyActorRef,
69
+ event: AnyEventObject,
70
+ delay: number,
71
+ id?: string
72
+ ) => void;
73
+ cancel: (source: AnyActorRef, id: string) => void;
74
+ cancelAll: (actorRef: AnyActorRef) => void;
75
+ } {
76
+ return {
77
+ schedule: (
78
+ source: AnyActorRef,
79
+ target: AnyActorRef,
80
+ event: AnyEventObject,
81
+ delay: number,
82
+ id: string = Math.random().toString(36).slice(2)
83
+ ) => {
84
+ const scheduledEventId = `${source.sessionId}.${id}`;
85
+
86
+ // Store the event data for later retrieval
87
+ const snapshot: ScheduledEventSnapshot = {
88
+ sourceSessionId: source.sessionId,
89
+ targetSessionId: target.sessionId,
90
+ event,
91
+ delay,
92
+ id,
93
+ startedAt: Date.now(),
94
+ };
95
+ scheduledEventsMap.set(scheduledEventId, snapshot);
96
+
97
+ // Schedule the alarm
98
+ const alarmId = `xstate-${scheduledEventId}`;
99
+
100
+ alarmManager.schedule({
101
+ id: alarmId,
102
+ type: "xstate-delay",
103
+ scheduledAt: Date.now() + delay,
104
+ payload: {
105
+ type: "xstate-delay",
106
+ sourceSessionId: source.sessionId,
107
+ targetSessionId: target.sessionId,
108
+ event,
109
+ scheduledEventId,
110
+ alarmId,
111
+ },
112
+ }).catch((error) => {
113
+ console.error(`[AlarmScheduler] Error scheduling alarm:`, error);
114
+ scheduledEventsMap.delete(scheduledEventId);
115
+ });
116
+ },
117
+
118
+ cancel: (source: AnyActorRef, id: string) => {
119
+ const scheduledEventId = `${source.sessionId}.${id}`;
120
+
121
+ // Remove from our tracking map
122
+ scheduledEventsMap.delete(scheduledEventId);
123
+
124
+ // Cancel the alarm
125
+ alarmManager.cancel(`xstate-${scheduledEventId}`).catch((error) => {
126
+ console.error(`[AlarmScheduler] Error canceling alarm:`, error);
127
+ });
128
+ },
129
+
130
+ cancelAll: (actorRef: AnyActorRef) => {
131
+ // Find all events for this actor
132
+ const eventsToCancel: string[] = [];
133
+
134
+ for (const [scheduledEventId, snapshot] of scheduledEventsMap.entries()) {
135
+ if (snapshot.sourceSessionId === actorRef.sessionId) {
136
+ eventsToCancel.push(scheduledEventId);
137
+ }
138
+ }
139
+
140
+ // Cancel each event
141
+ for (const scheduledEventId of eventsToCancel) {
142
+ scheduledEventsMap.delete(scheduledEventId);
143
+ alarmManager.cancel(`xstate-${scheduledEventId}`).catch((error) => {
144
+ console.error(`[AlarmScheduler] Error canceling alarm:`, error);
145
+ });
146
+ }
147
+ },
148
+ };
149
+ }
150
+
151
+ /**
152
+ * Handle an XState delayed event alarm
153
+ * This should be called from the Durable Object's alarm() handler
154
+ *
155
+ * @param alarmData - The alarm data from the XState alarm
156
+ * @param actor - The actor to send the event to
157
+ */
158
+ export async function handleXStateAlarm(
159
+ alarmData: XStateAlarmData,
160
+ actor: any
161
+ ): Promise<void> {
162
+ const { scheduledEventId, event } = alarmData;
163
+
164
+ // Remove from tracking map
165
+ scheduledEventsMap.delete(scheduledEventId);
166
+
167
+ // Send the event to the actor
168
+ try {
169
+ // Use the actor's internal _relay method to deliver the event
170
+ if (actor.system && actor.system._relay) {
171
+ actor.system._relay(actor, actor, event);
172
+ } else {
173
+ // Fallback: send directly to the actor
174
+ actor.send(event);
175
+ }
176
+ } catch (error) {
177
+ console.error(`[AlarmScheduler] Error handling XState alarm:`, error);
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Get all scheduled events (useful for debugging/inspection)
183
+ */
184
+ export function getScheduledEvents(): Map<string, ScheduledEventSnapshot> {
185
+ return new Map(scheduledEventsMap);
186
+ }
187
+
188
+ /**
189
+ * Restore scheduled events from storage (called after DO hibernation)
190
+ */
191
+ export function restoreScheduledEvents(
192
+ alarms: Array<{ payload: XStateAlarmData; scheduledAt: number }>
193
+ ): void {
194
+ for (const alarm of alarms) {
195
+ if (alarm.payload.type === "xstate-delay") {
196
+ const { sourceSessionId, targetSessionId, event, scheduledEventId } = alarm.payload;
197
+ const delay = alarm.scheduledAt - Date.now();
198
+
199
+ // Only restore if the alarm is still in the future
200
+ if (delay > 0) {
201
+ scheduledEventsMap.set(scheduledEventId, {
202
+ sourceSessionId,
203
+ targetSessionId,
204
+ event,
205
+ delay,
206
+ id: scheduledEventId.split(".").pop() || scheduledEventId,
207
+ startedAt: alarm.scheduledAt - delay,
208
+ });
209
+ }
210
+ }
211
+ }
212
+ }
@@ -0,0 +1,7 @@
1
+ import type { WebSocket as CloudflareWebSocket } from "@cloudflare/workers-types";
2
+
3
+ declare global {
4
+ interface WebSocket extends CloudflareWebSocket {}
5
+ }
6
+
7
+ export {};
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export * from "./schemas";
2
+ export * from "./types";
3
+ export * from "./constants";
4
+ export * from "./storage";
5
+ export * from "./alarms";
6
+ export * from "./durable-object-system";
package/src/react.ts ADDED
@@ -0,0 +1 @@
1
+ export { createActorKitContext } from "./createActorKitContext";
package/src/schemas.ts ADDED
@@ -0,0 +1,95 @@
1
+ import { z } from "zod";
2
+
3
+ export const BotManagementSchema = z.object({
4
+ corporateProxy: z.boolean(),
5
+ verifiedBot: z.boolean(),
6
+ jsDetection: z.object({
7
+ passed: z.boolean(),
8
+ }),
9
+ staticResource: z.boolean(),
10
+ detectionIds: z.record(z.any()),
11
+ score: z.number(),
12
+ });
13
+
14
+ export const EnvironmentSchema = z.object({
15
+ ACTOR_KIT_SECRET: z.string(),
16
+ ACTOR_KIT_HOST: z.string(),
17
+ });
18
+
19
+ export const RequestInfoSchema = z.object({
20
+ longitude: z.string(),
21
+ latitude: z.string(),
22
+ continent: z.string(),
23
+ country: z.string(),
24
+ city: z.string(),
25
+ timezone: z.string(),
26
+ postalCode: z.string(),
27
+ region: z.string(),
28
+ regionCode: z.string(),
29
+ metroCode: z.string(),
30
+ botManagement: BotManagementSchema,
31
+ });
32
+
33
+ export const CallerSchema = z.object({
34
+ id: z.string(),
35
+ type: z.enum(["client", "system", "service"]),
36
+ });
37
+
38
+ export const AnyEventSchema = z.object({
39
+ type: z.string(),
40
+ });
41
+
42
+ export const SystemEventSchema = z.discriminatedUnion("type", [
43
+ z.object({
44
+ type: z.literal("INITIALIZE"),
45
+ caller: z.object({ type: z.literal("system"), id: z.string() }),
46
+ }),
47
+ z.object({
48
+ type: z.literal("CONNECT"),
49
+ caller: z.object({ type: z.literal("system"), id: z.string() }),
50
+ connectingCaller: CallerSchema,
51
+ }),
52
+ z.object({
53
+ type: z.literal("DISCONNECT"),
54
+ caller: z.object({ type: z.literal("system"), id: z.string() }),
55
+ disconnectingCaller: CallerSchema,
56
+ }),
57
+ z.object({
58
+ type: z.literal("RESUME"),
59
+ caller: z.object({ type: z.literal("system"), id: z.string() }),
60
+ }),
61
+ z.object({
62
+ type: z.literal("MIGRATE"),
63
+ caller: z.object({ type: z.literal("system"), id: z.string() }),
64
+ operations: z.array(z.any()),
65
+ }),
66
+ ]);
67
+
68
+ export const CallerIdTypeSchema = z.enum(["client", "service", "system"]);
69
+
70
+ export const CallerStringSchema = z.string().transform((val, ctx) => {
71
+ if (val === "anonymous") {
72
+ return { type: "client" as const, id: "anonymous" };
73
+ }
74
+
75
+ // Regular expression to validate the UUID format
76
+ const callerTypeParseResult = CallerIdTypeSchema.safeParse(val.split("-")[0]);
77
+ if (!callerTypeParseResult.success) {
78
+ callerTypeParseResult.error.issues.forEach(ctx.addIssue);
79
+ return z.NEVER;
80
+ }
81
+ const type = callerTypeParseResult.data;
82
+
83
+ const id = val.substring(val.indexOf("-") + 1);
84
+ if (z.string().uuid().safeParse(id).success) {
85
+ return { type, id };
86
+ } else {
87
+ // If not valid, add a custom issue
88
+ ctx.addIssue({
89
+ code: z.ZodIssueCode.custom,
90
+ message: `Must be a valid uuid or 'anonymous'. Received '${id}' on value '${val}'.`,
91
+ });
92
+ // Return the special NEVER symbol to indicate a validation failure
93
+ return z.NEVER;
94
+ }
95
+ });
package/src/server.ts ADDED
@@ -0,0 +1,3 @@
1
+ // Export fetch functions to be used on a server.
2
+ export { createAccessToken } from "./createAccessToken";
3
+ export { createActorFetch } from "./createActorFetch";