UNPKG

actor-kit

Version:

Actor Kit is a library for running state machines in Cloudflare Workers, leveraging XState for robust state management. It provides a framework for managing the logic, lifecycle, persistence, synchronization, and access control of actors in a distributed

1 lines 5.34 kB
{"version":3,"file":"createActorKitMockClient-Bqgcb5gz.mjs","names":[],"sources":["../src/createActorKitMockClient.ts"],"sourcesContent":["import { Draft, produce } from \"immer\";\nimport {\n ActorKitClient,\n AnyActorKitStateMachine,\n CallerSnapshotFrom,\n ClientEventFrom,\n} from \"./types\";\n\nexport type ActorKitMockClientProps<TMachine extends AnyActorKitStateMachine> = {\n initialSnapshot: CallerSnapshotFrom<TMachine>;\n onSend?: (event: ClientEventFrom<TMachine>) => void;\n};\n\nexport type ActorKitMockClient<TMachine extends AnyActorKitStateMachine> = ActorKitClient<TMachine> & {\n produce: (recipe: (draft: Draft<CallerSnapshotFrom<TMachine>>) => void) => void;\n};\n\n/**\n * Creates a mock Actor Kit client for testing purposes.\n *\n * @template TMachine - The type of the state machine.\n * @param {ActorKitMockClientProps<TMachine>} props - Configuration options for the mock client.\n * @returns {ActorKitMockClient<TMachine>} An object with methods to interact with the mock actor.\n */\nexport function createActorKitMockClient<TMachine extends AnyActorKitStateMachine>(\n props: ActorKitMockClientProps<TMachine>\n): ActorKitMockClient<TMachine> {\n let currentSnapshot = props.initialSnapshot;\n const listeners: Set<(state: CallerSnapshotFrom<TMachine>) => void> = new Set();\n\n /**\n * Notifies all registered listeners with the current state.\n */\n const notifyListeners = () => {\n listeners.forEach((listener) => listener(currentSnapshot));\n };\n\n /**\n * Updates the state using an Immer producer function.\n * @param {(draft: Draft<CallerSnapshotFrom<TMachine>>) => void} recipe - The state update recipe.\n */\n const produceFn = (recipe: (draft: Draft<CallerSnapshotFrom<TMachine>>) => void) => {\n currentSnapshot = produce(currentSnapshot, recipe);\n notifyListeners();\n };\n\n /**\n * Sends an event to the mock client.\n * @param {ClientEventFrom<TMachine>} event - The event to send.\n */\n const send = (event: ClientEventFrom<TMachine>) => {\n props.onSend?.(event);\n notifyListeners();\n };\n\n /**\n * Retrieves the current state of the mock actor.\n * @returns {CallerSnapshotFrom<TMachine>} The current state.\n */\n const getState = () => currentSnapshot;\n\n /**\n * Subscribes a listener to state changes.\n * @param {(state: CallerSnapshotFrom<TMachine>) => void} listener - The listener function to be called on state changes.\n * @returns {() => void} A function to unsubscribe the listener.\n */\n const subscribe = (listener: (state: CallerSnapshotFrom<TMachine>) => void) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n };\n\n /**\n * Mock connect method.\n * @returns {Promise<void>} A promise that resolves immediately.\n */\n const connect = async () => {\n // Mock implementation, resolves immediately\n return Promise.resolve();\n };\n\n /**\n * Mock disconnect method.\n */\n const disconnect = () => {\n // Mock implementation, does nothing\n };\n\n /**\n * Waits for a state condition to be met.\n * @param {(state: CallerSnapshotFrom<TMachine>) => boolean} predicateFn - Function that returns true when condition is met\n * @param {number} [timeoutMs=5000] - Maximum time to wait in milliseconds\n * @returns {Promise<void>} Resolves when condition is met, rejects on timeout\n */\n const waitFor = async (\n predicateFn: (state: CallerSnapshotFrom<TMachine>) => boolean,\n timeoutMs: number = 5000\n ): Promise<void> => {\n // Check if condition is already met\n if (predicateFn(currentSnapshot)) {\n return Promise.resolve();\n }\n\n return new Promise((resolve, reject) => {\n let timeoutId: number | null = null;\n\n // Set up timeout to reject if condition isn't met in time\n if (timeoutMs > 0) {\n timeoutId = setTimeout(() => {\n unsubscribe();\n reject(new Error(`Timeout waiting for condition after ${timeoutMs}ms`));\n }, timeoutMs);\n }\n\n // Subscribe to state changes\n const unsubscribe = subscribe((state) => {\n if (predicateFn(state)) {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n unsubscribe();\n resolve();\n }\n });\n });\n };\n\n return {\n connect,\n disconnect,\n send,\n getState,\n subscribe,\n produce: produceFn,\n waitFor,\n };\n}\n"],"mappings":";;;;;;;;;AAwBA,SAAgB,yBACd,OAC8B;CAC9B,IAAI,kBAAkB,MAAM;CAC5B,MAAM,4BAAgE,IAAI,KAAK;;;;CAK/E,MAAM,wBAAwB;AAC5B,YAAU,SAAS,aAAa,SAAS,gBAAgB,CAAC;;;;;;CAO5D,MAAM,aAAa,WAAiE;AAClF,oBAAkB,QAAQ,iBAAiB,OAAO;AAClD,mBAAiB;;;;;;CAOnB,MAAM,QAAQ,UAAqC;AACjD,QAAM,SAAS,MAAM;AACrB,mBAAiB;;;;;;CAOnB,MAAM,iBAAiB;;;;;;CAOvB,MAAM,aAAa,aAA4D;AAC7E,YAAU,IAAI,SAAS;AACvB,eAAa;AACX,aAAU,OAAO,SAAS;;;;;;;CAQ9B,MAAM,UAAU,YAAY;AAE1B,SAAO,QAAQ,SAAS;;;;;CAM1B,MAAM,mBAAmB;;;;;;;CAUzB,MAAM,UAAU,OACd,aACA,YAAoB,QACF;AAElB,MAAI,YAAY,gBAAgB,CAC9B,QAAO,QAAQ,SAAS;AAG1B,SAAO,IAAI,SAAS,SAAS,WAAW;GACtC,IAAI,YAA2B;AAG/B,OAAI,YAAY,EACd,aAAY,iBAAiB;AAC3B,iBAAa;AACb,2BAAO,IAAI,MAAM,uCAAuC,UAAU,IAAI,CAAC;MACtE,UAAU;GAIf,MAAM,cAAc,WAAW,UAAU;AACvC,QAAI,YAAY,MAAM,EAAE;AACtB,SAAI,UACF,cAAa,UAAU;AAEzB,kBAAa;AACb,cAAS;;KAEX;IACF;;AAGJ,QAAO;EACL;EACA;EACA;EACA;EACA;EACA,SAAS;EACT;EACD"}