@coji/durably-react 0.6.0 → 0.7.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.
- package/dist/chunk-42AVE35N.js +142 -0
- package/dist/chunk-42AVE35N.js.map +1 -0
- package/dist/client.d.ts +31 -60
- package/dist/client.js +102 -131
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +31 -19
- package/dist/index.js +272 -249
- package/dist/index.js.map +1 -1
- package/dist/types-DY4Y6ggJ.d.ts +111 -0
- package/package.json +2 -2
- package/dist/types-BDUvsa8u.d.ts +0 -67
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/context.tsx","../src/hooks/use-job.ts","../src/hooks/use-run-subscription.ts","../src/hooks/use-job-logs.ts","../src/hooks/use-job-run.ts","../src/hooks/use-runs.ts"],"sourcesContent":["import type { Durably } from '@coji/durably'\nimport { Suspense, createContext, use, useContext, type ReactNode } from 'react'\n\ninterface DurablyContextValue {\n durably: Durably\n}\n\nconst DurablyContext = createContext<DurablyContextValue | null>(null)\n\nexport interface DurablyProviderProps {\n /**\n * Durably instance or Promise that resolves to one.\n * The instance should already be initialized via `await durably.init()`.\n *\n * When passing a Promise, wrap the provider with Suspense or use the fallback prop.\n *\n * @example\n * // With Suspense (recommended)\n * <Suspense fallback={<Loading />}>\n * <DurablyProvider durably={durablyPromise}>\n * <App />\n * </DurablyProvider>\n * </Suspense>\n *\n * @example\n * // With fallback prop\n * <DurablyProvider durably={durablyPromise} fallback={<Loading />}>\n * <App />\n * </DurablyProvider>\n */\n durably: Durably | Promise<Durably>\n /**\n * Fallback to show while waiting for the Durably Promise to resolve.\n * This wraps the provider content in a Suspense boundary automatically.\n */\n fallback?: ReactNode\n children: ReactNode\n}\n\n/**\n * Internal component that uses the `use()` hook to resolve the Promise\n */\nfunction DurablyProviderInner({\n durably: durablyOrPromise,\n children,\n}: Omit<DurablyProviderProps, 'fallback'>) {\n const durably =\n durablyOrPromise instanceof Promise\n ? use(durablyOrPromise)\n : durablyOrPromise\n\n return (\n <DurablyContext.Provider value={{ durably }}>\n {children}\n </DurablyContext.Provider>\n )\n}\n\nexport function DurablyProvider({\n durably,\n fallback,\n children,\n}: DurablyProviderProps) {\n const inner = (\n <DurablyProviderInner durably={durably}>{children}</DurablyProviderInner>\n )\n\n if (fallback !== undefined) {\n return <Suspense fallback={fallback}>{inner}</Suspense>\n }\n\n return inner\n}\n\nexport function useDurably(): DurablyContextValue {\n const context = useContext(DurablyContext)\n if (!context) {\n throw new Error('useDurably must be used within a DurablyProvider')\n }\n return context\n}\n","import type { JobDefinition, JobHandle } from '@coji/durably'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { useDurably } from '../context'\nimport type { LogEntry, Progress, RunStatus } from '../types'\n\nexport interface UseJobOptions {\n /**\n * Initial Run ID to subscribe to (for reconnection scenarios)\n */\n initialRunId?: string\n /**\n * Automatically resume tracking any pending or running job on initialization.\n * If a pending or running run exists for this job, the hook will subscribe to it.\n * @default true\n */\n autoResume?: boolean\n /**\n * Automatically switch to tracking the latest running job when a new run starts.\n * When true, the hook will update to track any new run for this job as soon as it starts running.\n * When false, the hook will only track the run that was triggered or explicitly set.\n * @default true\n */\n followLatest?: boolean\n}\n\nexport interface UseJobResult<TInput, TOutput> {\n /**\n * Trigger the job with the given input\n */\n trigger: (input: TInput) => Promise<{ runId: string }>\n /**\n * Trigger and wait for completion\n */\n triggerAndWait: (input: TInput) => Promise<{ runId: string; output: TOutput }>\n /**\n * Current run status\n */\n status: RunStatus | null\n /**\n * Output from completed run\n */\n output: TOutput | null\n /**\n * Error message from failed run\n */\n error: string | null\n /**\n * Logs collected during execution\n */\n logs: LogEntry[]\n /**\n * Current progress\n */\n progress: Progress | null\n /**\n * Whether a run is currently running\n */\n isRunning: boolean\n /**\n * Whether a run is pending\n */\n isPending: boolean\n /**\n * Whether the run completed successfully\n */\n isCompleted: boolean\n /**\n * Whether the run failed\n */\n isFailed: boolean\n /**\n * Whether the run was cancelled\n */\n isCancelled: boolean\n /**\n * Current run ID\n */\n currentRunId: string | null\n /**\n * Reset all state\n */\n reset: () => void\n}\n\nexport function useJob<\n TName extends string,\n TInput extends Record<string, unknown>,\n // biome-ignore lint/suspicious/noConfusingVoidType: TOutput can be void for jobs without return value\n TOutput extends Record<string, unknown> | void,\n>(\n jobDefinition: JobDefinition<TName, TInput, TOutput>,\n options?: UseJobOptions,\n): UseJobResult<TInput, TOutput> {\n const { durably } = useDurably()\n\n const [status, setStatus] = useState<RunStatus | null>(null)\n const [output, setOutput] = useState<TOutput | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [logs, setLogs] = useState<LogEntry[]>([])\n const [progress, setProgress] = useState<Progress | null>(null)\n const [currentRunId, setCurrentRunId] = useState<string | null>(\n options?.initialRunId ?? null,\n )\n\n const jobHandleRef = useRef<JobHandle<TName, TInput, TOutput> | null>(null)\n // Use ref to track the latest runId for event filtering\n const currentRunIdRef = useRef<string | null>(currentRunId)\n currentRunIdRef.current = currentRunId\n\n // Register job and set up event listeners\n useEffect(() => {\n if (!durably) return\n\n // Register the job (use fixed key for simpler type handling)\n const d = durably.register({\n _job: jobDefinition,\n })\n const jobHandle = d.jobs._job\n jobHandleRef.current = jobHandle\n\n // Subscribe to each event type separately\n const unsubscribes: (() => void)[] = []\n\n unsubscribes.push(\n durably.on('run:start', (event) => {\n // Check if this is a run for our job\n if (event.jobName !== jobDefinition.name) return\n\n // If followLatest is disabled, only update if this is our current run\n if (options?.followLatest === false) {\n if (event.runId !== currentRunIdRef.current) return\n setStatus('running')\n return\n }\n\n // Switch to tracking the running job (followLatest: true, default)\n setCurrentRunId(event.runId)\n currentRunIdRef.current = event.runId\n setStatus('running')\n // Reset output/error when switching to a new run\n setOutput(null)\n setError(null)\n setLogs([])\n setProgress(null)\n }),\n )\n\n unsubscribes.push(\n durably.on('run:complete', (event) => {\n if (event.runId !== currentRunIdRef.current) return\n setStatus('completed')\n setOutput(event.output as TOutput)\n }),\n )\n\n unsubscribes.push(\n durably.on('run:fail', (event) => {\n if (event.runId !== currentRunIdRef.current) return\n setStatus('failed')\n setError(event.error)\n }),\n )\n\n unsubscribes.push(\n durably.on('run:progress', (event) => {\n if (event.runId !== currentRunIdRef.current) return\n setProgress(event.progress)\n }),\n )\n\n unsubscribes.push(\n durably.on('log:write', (event) => {\n if (event.runId !== currentRunIdRef.current) return\n setLogs((prev) => [\n ...prev,\n {\n id: crypto.randomUUID(),\n runId: event.runId,\n stepName: event.stepName,\n level: event.level,\n message: event.message,\n data: event.data,\n timestamp: new Date().toISOString(),\n },\n ])\n }),\n )\n\n // If we have an initialRunId, fetch its current state\n if (options?.initialRunId && currentRunIdRef.current) {\n jobHandle.getRun(currentRunIdRef.current).then((run) => {\n if (run) {\n setStatus(run.status as RunStatus)\n if (run.status === 'completed' && run.output) {\n setOutput(run.output as TOutput)\n }\n if (run.status === 'failed' && run.error) {\n setError(run.error)\n }\n }\n })\n }\n\n // Auto-resume: find any pending or running runs for this job (default: true)\n if (options?.autoResume !== false && !options?.initialRunId) {\n ;(async () => {\n // First check for running runs\n const runningRuns = await jobHandle.getRuns({ status: 'running' })\n if (runningRuns.length > 0) {\n const run = runningRuns[0]\n setCurrentRunId(run.id)\n currentRunIdRef.current = run.id\n setStatus(run.status as RunStatus)\n return\n }\n\n // Then check for pending runs\n const pendingRuns = await jobHandle.getRuns({ status: 'pending' })\n if (pendingRuns.length > 0) {\n const run = pendingRuns[0]\n setCurrentRunId(run.id)\n currentRunIdRef.current = run.id\n setStatus(run.status as RunStatus)\n }\n })()\n }\n\n return () => {\n for (const unsubscribe of unsubscribes) {\n unsubscribe()\n }\n }\n }, [\n durably,\n jobDefinition,\n options?.initialRunId,\n options?.autoResume,\n options?.followLatest,\n ])\n\n // Update state when currentRunId changes (for initialRunId scenario)\n useEffect(() => {\n if (!durably || !currentRunId) return\n\n const jobHandle = jobHandleRef.current\n if (jobHandle && options?.initialRunId) {\n jobHandle.getRun(currentRunId).then((run) => {\n if (run) {\n setStatus(run.status as RunStatus)\n if (run.status === 'completed' && run.output) {\n setOutput(run.output as TOutput)\n }\n if (run.status === 'failed' && run.error) {\n setError(run.error)\n }\n }\n })\n }\n }, [durably, currentRunId, options?.initialRunId])\n\n const trigger = useCallback(\n async (input: TInput): Promise<{ runId: string }> => {\n const jobHandle = jobHandleRef.current\n if (!jobHandle) {\n throw new Error('Job not ready')\n }\n\n // Reset state\n setOutput(null)\n setError(null)\n setLogs([])\n setProgress(null)\n\n const run = await jobHandle.trigger(input)\n setCurrentRunId(run.id)\n currentRunIdRef.current = run.id\n setStatus('pending')\n\n return { runId: run.id }\n },\n [],\n )\n\n const triggerAndWait = useCallback(\n async (input: TInput): Promise<{ runId: string; output: TOutput }> => {\n const jobHandle = jobHandleRef.current\n if (!jobHandle || !durably) {\n throw new Error('Job not ready')\n }\n\n // Reset state\n setOutput(null)\n setError(null)\n setLogs([])\n setProgress(null)\n\n const run = await jobHandle.trigger(input)\n setCurrentRunId(run.id)\n currentRunIdRef.current = run.id\n setStatus('pending')\n\n // Wait for completion\n return new Promise((resolve, reject) => {\n const checkCompletion = async () => {\n const updatedRun = await jobHandle.getRun(run.id)\n if (!updatedRun) {\n reject(new Error('Run not found'))\n return\n }\n\n if (updatedRun.status === 'completed') {\n resolve({ runId: run.id, output: updatedRun.output as TOutput })\n } else if (updatedRun.status === 'failed') {\n reject(new Error(updatedRun.error ?? 'Job failed'))\n } else if (updatedRun.status === 'cancelled') {\n reject(new Error('Job cancelled'))\n } else {\n // Still running, check again\n setTimeout(checkCompletion, 50)\n }\n }\n checkCompletion()\n })\n },\n [durably],\n )\n\n const reset = useCallback(() => {\n setStatus(null)\n setOutput(null)\n setError(null)\n setLogs([])\n setProgress(null)\n setCurrentRunId(null)\n }, [])\n\n return {\n trigger,\n triggerAndWait,\n status,\n output,\n error,\n logs,\n progress,\n isRunning: status === 'running',\n isPending: status === 'pending',\n isCompleted: status === 'completed',\n isFailed: status === 'failed',\n isCancelled: status === 'cancelled',\n currentRunId,\n reset,\n }\n}\n","import type { Durably } from '@coji/durably'\nimport { useEffect, useRef, useState } from 'react'\nimport type { LogEntry, Progress, RunStatus } from '../types'\n\nexport interface RunSubscriptionState<TOutput = unknown> {\n status: RunStatus | null\n output: TOutput | null\n error: string | null\n logs: LogEntry[]\n progress: Progress | null\n}\n\nexport interface UseRunSubscriptionOptions {\n /**\n * Maximum number of logs to keep (0 = unlimited)\n */\n maxLogs?: number\n}\n\nexport interface UseRunSubscriptionResult<\n TOutput = unknown,\n> extends RunSubscriptionState<TOutput> {\n /**\n * Clear all logs\n */\n clearLogs: () => void\n /**\n * Reset all state\n */\n reset: () => void\n}\n\n/**\n * Internal hook for subscribing to run events.\n * Shared by useJob, useJobRun, and useJobLogs.\n */\nexport function useRunSubscription<TOutput = unknown>(\n durably: Durably | null,\n runId: string | null,\n options?: UseRunSubscriptionOptions,\n): UseRunSubscriptionResult<TOutput> {\n const [status, setStatus] = useState<RunStatus | null>(null)\n const [output, setOutput] = useState<TOutput | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [logs, setLogs] = useState<LogEntry[]>([])\n const [progress, setProgress] = useState<Progress | null>(null)\n\n // Use ref to track the latest runId for event filtering\n const runIdRef = useRef<string | null>(runId)\n runIdRef.current = runId\n\n const maxLogs = options?.maxLogs ?? 0\n\n // Subscribe to events\n useEffect(() => {\n if (!durably || !runId) return\n\n const unsubscribes: (() => void)[] = []\n\n unsubscribes.push(\n durably.on('run:start', (event) => {\n if (event.runId !== runIdRef.current) return\n setStatus('running')\n }),\n )\n\n unsubscribes.push(\n durably.on('run:complete', (event) => {\n if (event.runId !== runIdRef.current) return\n setStatus('completed')\n setOutput(event.output as TOutput)\n }),\n )\n\n unsubscribes.push(\n durably.on('run:fail', (event) => {\n if (event.runId !== runIdRef.current) return\n setStatus('failed')\n setError(event.error)\n }),\n )\n\n unsubscribes.push(\n durably.on('run:cancel', (event) => {\n if (event.runId !== runIdRef.current) return\n setStatus('cancelled')\n }),\n )\n\n unsubscribes.push(\n durably.on('run:retry', (event) => {\n if (event.runId !== runIdRef.current) return\n setStatus('pending')\n setError(null)\n }),\n )\n\n unsubscribes.push(\n durably.on('run:progress', (event) => {\n if (event.runId !== runIdRef.current) return\n setProgress(event.progress)\n }),\n )\n\n unsubscribes.push(\n durably.on('log:write', (event) => {\n if (event.runId !== runIdRef.current) return\n setLogs((prev) => {\n const newLog: LogEntry = {\n id: crypto.randomUUID(),\n runId: event.runId,\n stepName: event.stepName,\n level: event.level,\n message: event.message,\n data: event.data,\n timestamp: new Date().toISOString(),\n }\n const newLogs = [...prev, newLog]\n // Apply maxLogs limit if set\n if (maxLogs > 0 && newLogs.length > maxLogs) {\n return newLogs.slice(-maxLogs)\n }\n return newLogs\n })\n }),\n )\n\n return () => {\n for (const unsubscribe of unsubscribes) {\n unsubscribe()\n }\n }\n }, [durably, runId, maxLogs])\n\n const clearLogs = () => {\n setLogs([])\n }\n\n const reset = () => {\n setStatus(null)\n setOutput(null)\n setError(null)\n setLogs([])\n setProgress(null)\n }\n\n return {\n status,\n output,\n error,\n logs,\n progress,\n clearLogs,\n reset,\n }\n}\n","import { useDurably } from '../context'\nimport type { LogEntry } from '../types'\nimport { useRunSubscription } from './use-run-subscription'\n\nexport interface UseJobLogsOptions {\n /**\n * The run ID to subscribe to logs for\n */\n runId: string | null\n /**\n * Maximum number of logs to keep (default: unlimited)\n */\n maxLogs?: number\n}\n\nexport interface UseJobLogsResult {\n /**\n * Logs collected during execution\n */\n logs: LogEntry[]\n /**\n * Clear all logs\n */\n clearLogs: () => void\n}\n\n/**\n * Hook for subscribing to logs from a run.\n * Use this when you only need logs, not full run status.\n */\nexport function useJobLogs(options: UseJobLogsOptions): UseJobLogsResult {\n const { durably } = useDurably()\n const { runId, maxLogs } = options\n\n const subscription = useRunSubscription(durably, runId, { maxLogs })\n\n return {\n logs: subscription.logs,\n clearLogs: subscription.clearLogs,\n }\n}\n","import { useEffect, useRef } from 'react'\nimport { useDurably } from '../context'\nimport type { LogEntry, Progress, RunStatus } from '../types'\nimport { useRunSubscription } from './use-run-subscription'\n\nexport interface UseJobRunOptions {\n /**\n * The run ID to subscribe to\n */\n runId: string | null\n}\n\nexport interface UseJobRunResult<TOutput = unknown> {\n /**\n * Current run status\n */\n status: RunStatus | null\n /**\n * Output from completed run\n */\n output: TOutput | null\n /**\n * Error message from failed run\n */\n error: string | null\n /**\n * Logs collected during execution\n */\n logs: LogEntry[]\n /**\n * Current progress\n */\n progress: Progress | null\n /**\n * Whether a run is currently running\n */\n isRunning: boolean\n /**\n * Whether a run is pending\n */\n isPending: boolean\n /**\n * Whether the run completed successfully\n */\n isCompleted: boolean\n /**\n * Whether the run failed\n */\n isFailed: boolean\n /**\n * Whether the run was cancelled\n */\n isCancelled: boolean\n}\n\n/**\n * Hook for subscribing to an existing run by ID.\n * Use this when you have a runId and want to track its status.\n */\nexport function useJobRun<TOutput = unknown>(\n options: UseJobRunOptions,\n): UseJobRunResult<TOutput> {\n const { durably } = useDurably()\n const { runId } = options\n\n const subscription = useRunSubscription<TOutput>(durably, runId)\n\n // Fetch initial state when runId changes\n const fetchedRef = useRef<Set<string>>(new Set())\n\n useEffect(() => {\n if (!durably || !runId || fetchedRef.current.has(runId)) return\n\n // Mark as fetched to avoid duplicate fetches\n fetchedRef.current.add(runId)\n\n // Try to fetch current run state\n // Note: We need to use internal APIs or polling here\n // For now, we rely on event-based updates\n }, [durably, runId])\n\n return {\n status: subscription.status,\n output: subscription.output,\n error: subscription.error,\n logs: subscription.logs,\n progress: subscription.progress,\n isRunning: subscription.status === 'running',\n isPending: subscription.status === 'pending',\n isCompleted: subscription.status === 'completed',\n isFailed: subscription.status === 'failed',\n isCancelled: subscription.status === 'cancelled',\n }\n}\n","import type { Run } from '@coji/durably'\nimport { useCallback, useEffect, useState } from 'react'\nimport { useDurably } from '../context'\n\nexport interface UseRunsOptions {\n /**\n * Filter by job name\n */\n jobName?: string\n /**\n * Filter by status\n */\n status?: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled'\n /**\n * Number of runs per page\n * @default 10\n */\n pageSize?: number\n /**\n * Subscribe to real-time updates\n * @default true\n */\n realtime?: boolean\n}\n\nexport interface UseRunsResult {\n /**\n * List of runs for the current page\n */\n runs: Run[]\n /**\n * Current page (0-indexed)\n */\n page: number\n /**\n * Whether there are more pages\n */\n hasMore: boolean\n /**\n * Whether data is being loaded\n */\n isLoading: boolean\n /**\n * Go to the next page\n */\n nextPage: () => void\n /**\n * Go to the previous page\n */\n prevPage: () => void\n /**\n * Go to a specific page\n */\n goToPage: (page: number) => void\n /**\n * Refresh the current page\n */\n refresh: () => Promise<void>\n}\n\n/**\n * Hook for listing runs with pagination and real-time updates.\n *\n * @example\n * ```tsx\n * function Dashboard() {\n * const { runs, page, hasMore, nextPage, prevPage, isLoading } = useRuns({\n * pageSize: 20,\n * })\n *\n * return (\n * <div>\n * {runs.map(run => (\n * <div key={run.id}>{run.jobName}: {run.status}</div>\n * ))}\n * <button onClick={prevPage} disabled={page === 0}>Prev</button>\n * <button onClick={nextPage} disabled={!hasMore}>Next</button>\n * </div>\n * )\n * }\n * ```\n */\nexport function useRuns(options?: UseRunsOptions): UseRunsResult {\n const { durably } = useDurably()\n const pageSize = options?.pageSize ?? 10\n const realtime = options?.realtime ?? true\n\n const [runs, setRuns] = useState<Run[]>([])\n const [page, setPage] = useState(0)\n const [hasMore, setHasMore] = useState(false)\n const [isLoading, setIsLoading] = useState(false)\n\n const refresh = useCallback(async () => {\n if (!durably) return\n\n setIsLoading(true)\n try {\n const data = await durably.getRuns({\n jobName: options?.jobName,\n status: options?.status,\n limit: pageSize + 1,\n offset: page * pageSize,\n })\n setHasMore(data.length > pageSize)\n setRuns(data.slice(0, pageSize))\n } finally {\n setIsLoading(false)\n }\n }, [durably, options?.jobName, options?.status, pageSize, page])\n\n // Initial fetch and subscribe to events\n useEffect(() => {\n if (!durably) return\n\n refresh()\n\n if (!realtime) return\n\n const unsubscribes = [\n durably.on('run:trigger', refresh),\n durably.on('run:start', refresh),\n durably.on('run:complete', refresh),\n durably.on('run:fail', refresh),\n durably.on('run:cancel', refresh),\n durably.on('run:retry', refresh),\n durably.on('run:progress', refresh),\n durably.on('step:start', refresh),\n durably.on('step:complete', refresh),\n ]\n\n return () => {\n for (const unsubscribe of unsubscribes) {\n unsubscribe()\n }\n }\n }, [durably, refresh, realtime])\n\n const nextPage = useCallback(() => {\n if (hasMore) {\n setPage((p) => p + 1)\n }\n }, [hasMore])\n\n const prevPage = useCallback(() => {\n setPage((p) => Math.max(0, p - 1))\n }, [])\n\n const goToPage = useCallback((newPage: number) => {\n setPage(Math.max(0, newPage))\n }, [])\n\n return {\n runs,\n page,\n hasMore,\n isLoading,\n nextPage,\n prevPage,\n goToPage,\n refresh,\n }\n}\n"],"mappings":"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","names":["useEffect","useRef","useState","useEffect","useRef","useRef","useEffect","useCallback","useEffect","useState","useState","useCallback","useEffect"]}
|
|
1
|
+
{"version":3,"sources":["../src/context.tsx","../src/hooks/use-job.ts","../src/hooks/use-auto-resume.ts","../src/hooks/use-job-subscription.ts","../src/hooks/use-run-subscription.ts","../src/shared/durably-event-subscriber.ts","../src/hooks/use-job-logs.ts","../src/hooks/use-job-run.ts","../src/hooks/use-runs.ts"],"sourcesContent":["import type { Durably } from '@coji/durably'\nimport { Suspense, createContext, use, useContext, type ReactNode } from 'react'\n\ninterface DurablyContextValue {\n durably: Durably\n}\n\nconst DurablyContext = createContext<DurablyContextValue | null>(null)\n\nexport interface DurablyProviderProps {\n /**\n * Durably instance or Promise that resolves to one.\n * The instance should already be initialized via `await durably.init()`.\n *\n * When passing a Promise, wrap the provider with Suspense or use the fallback prop.\n *\n * @example\n * // With Suspense (recommended)\n * <Suspense fallback={<Loading />}>\n * <DurablyProvider durably={durablyPromise}>\n * <App />\n * </DurablyProvider>\n * </Suspense>\n *\n * @example\n * // With fallback prop\n * <DurablyProvider durably={durablyPromise} fallback={<Loading />}>\n * <App />\n * </DurablyProvider>\n */\n durably: Durably | Promise<Durably>\n /**\n * Fallback to show while waiting for the Durably Promise to resolve.\n * This wraps the provider content in a Suspense boundary automatically.\n */\n fallback?: ReactNode\n children: ReactNode\n}\n\n/**\n * Internal component that uses the `use()` hook to resolve the Promise\n */\nfunction DurablyProviderInner({\n durably: durablyOrPromise,\n children,\n}: Omit<DurablyProviderProps, 'fallback'>) {\n const durably =\n durablyOrPromise instanceof Promise\n ? use(durablyOrPromise)\n : durablyOrPromise\n\n return (\n <DurablyContext.Provider value={{ durably }}>\n {children}\n </DurablyContext.Provider>\n )\n}\n\nexport function DurablyProvider({\n durably,\n fallback,\n children,\n}: DurablyProviderProps) {\n const inner = (\n <DurablyProviderInner durably={durably}>{children}</DurablyProviderInner>\n )\n\n if (fallback !== undefined) {\n return <Suspense fallback={fallback}>{inner}</Suspense>\n }\n\n return inner\n}\n\nexport function useDurably(): DurablyContextValue {\n const context = useContext(DurablyContext)\n if (!context) {\n throw new Error('useDurably must be used within a DurablyProvider')\n }\n return context\n}\n","import type { JobDefinition, JobHandle } from '@coji/durably'\nimport { useCallback, useEffect, useMemo, useRef } from 'react'\nimport { useDurably } from '../context'\nimport type { LogEntry, Progress, RunStatus } from '../types'\nimport { useAutoResume } from './use-auto-resume'\nimport { useJobSubscription } from './use-job-subscription'\n\nexport interface UseJobOptions {\n /**\n * Initial Run ID to subscribe to (for reconnection scenarios)\n */\n initialRunId?: string\n /**\n * Automatically resume tracking any pending or running job on initialization.\n * If a pending or running run exists for this job, the hook will subscribe to it.\n * @default true\n */\n autoResume?: boolean\n /**\n * Automatically switch to tracking the latest running job when a new run starts.\n * When true, the hook will update to track any new run for this job as soon as it starts running.\n * When false, the hook will only track the run that was triggered or explicitly set.\n * @default true\n */\n followLatest?: boolean\n}\n\nexport interface UseJobResult<TInput, TOutput> {\n /**\n * Trigger the job with the given input\n */\n trigger: (input: TInput) => Promise<{ runId: string }>\n /**\n * Trigger and wait for completion\n */\n triggerAndWait: (input: TInput) => Promise<{ runId: string; output: TOutput }>\n /**\n * Current run status\n */\n status: RunStatus | null\n /**\n * Output from completed run\n */\n output: TOutput | null\n /**\n * Error message from failed run\n */\n error: string | null\n /**\n * Logs collected during execution\n */\n logs: LogEntry[]\n /**\n * Current progress\n */\n progress: Progress | null\n /**\n * Whether a run is currently running\n */\n isRunning: boolean\n /**\n * Whether a run is pending\n */\n isPending: boolean\n /**\n * Whether the run completed successfully\n */\n isCompleted: boolean\n /**\n * Whether the run failed\n */\n isFailed: boolean\n /**\n * Whether the run was cancelled\n */\n isCancelled: boolean\n /**\n * Current run ID\n */\n currentRunId: string | null\n /**\n * Reset all state\n */\n reset: () => void\n}\n\nexport function useJob<\n TName extends string,\n TInput extends Record<string, unknown>,\n // biome-ignore lint/suspicious/noConfusingVoidType: TOutput can be void for jobs without return value\n TOutput extends Record<string, unknown> | void,\n>(\n jobDefinition: JobDefinition<TName, TInput, TOutput>,\n options?: UseJobOptions,\n): UseJobResult<TInput, TOutput> {\n const { durably } = useDurably()\n\n const jobHandleRef = useRef<JobHandle<TName, TInput, TOutput> | null>(null)\n\n // Register job\n useEffect(() => {\n if (!durably) return\n\n const d = durably.register({\n _job: jobDefinition,\n })\n jobHandleRef.current = d.jobs._job\n }, [durably, jobDefinition])\n\n // Use the extracted job subscription hook\n const subscription = useJobSubscription<TOutput>(\n durably,\n jobDefinition.name,\n {\n followLatest: options?.followLatest,\n },\n )\n\n // Auto-resume callbacks - stable reference\n const autoResumeCallbacks = useMemo(\n () => ({\n onRunFound: (runId: string, _status: RunStatus) => {\n subscription.setCurrentRunId(runId)\n },\n }),\n [subscription.setCurrentRunId],\n )\n\n // Use the extracted auto-resume hook\n useAutoResume(\n jobHandleRef.current,\n {\n enabled: options?.autoResume,\n initialRunId: options?.initialRunId,\n },\n autoResumeCallbacks,\n )\n\n // Handle initialRunId - set it to start tracking\n useEffect(() => {\n if (!durably || !options?.initialRunId) return\n\n subscription.setCurrentRunId(options.initialRunId)\n }, [durably, options?.initialRunId, subscription.setCurrentRunId])\n\n const trigger = useCallback(\n async (input: TInput): Promise<{ runId: string }> => {\n const jobHandle = jobHandleRef.current\n if (!jobHandle) {\n throw new Error('Job not ready')\n }\n\n // Reset state before triggering\n subscription.reset()\n\n const run = await jobHandle.trigger(input)\n subscription.setCurrentRunId(run.id)\n\n return { runId: run.id }\n },\n [subscription],\n )\n\n const triggerAndWait = useCallback(\n async (input: TInput): Promise<{ runId: string; output: TOutput }> => {\n const jobHandle = jobHandleRef.current\n if (!jobHandle || !durably) {\n throw new Error('Job not ready')\n }\n\n // Reset state before triggering\n subscription.reset()\n\n const run = await jobHandle.trigger(input)\n subscription.setCurrentRunId(run.id)\n\n // Wait for completion by polling\n return new Promise((resolve, reject) => {\n const checkCompletion = async () => {\n const updatedRun = await jobHandle.getRun(run.id)\n if (!updatedRun) {\n reject(new Error('Run not found'))\n return\n }\n\n if (updatedRun.status === 'completed') {\n resolve({ runId: run.id, output: updatedRun.output as TOutput })\n } else if (updatedRun.status === 'failed') {\n reject(new Error(updatedRun.error ?? 'Job failed'))\n } else if (updatedRun.status === 'cancelled') {\n reject(new Error('Job cancelled'))\n } else {\n // Still running, check again\n setTimeout(checkCompletion, 50)\n }\n }\n checkCompletion()\n })\n },\n [durably, subscription],\n )\n\n return {\n trigger,\n triggerAndWait,\n status: subscription.status,\n output: subscription.output,\n error: subscription.error,\n logs: subscription.logs,\n progress: subscription.progress,\n isRunning: subscription.status === 'running',\n isPending: subscription.status === 'pending',\n isCompleted: subscription.status === 'completed',\n isFailed: subscription.status === 'failed',\n isCancelled: subscription.status === 'cancelled',\n currentRunId: subscription.currentRunId,\n reset: subscription.reset,\n }\n}\n","import type { JobHandle } from '@coji/durably'\nimport { useEffect } from 'react'\nimport type { RunStatus } from '../types'\n\nexport interface UseAutoResumeOptions {\n /**\n * Whether to automatically resume tracking pending/running runs\n * @default true\n */\n enabled?: boolean\n /**\n * Skip auto-resume if an initial run ID is provided\n */\n skipIfInitialRunId?: boolean\n /**\n * Initial run ID (if provided, auto-resume is skipped)\n */\n initialRunId?: string\n}\n\nexport interface UseAutoResumeCallbacks {\n /**\n * Called when a run is found to resume\n */\n onRunFound: (runId: string, status: RunStatus) => void\n}\n\n/**\n * Hook that automatically finds and resumes tracking of pending/running runs.\n * Extracted from useJob to separate the auto-resume concern.\n */\nexport function useAutoResume<\n TName extends string,\n TInput extends Record<string, unknown>,\n TOutput,\n>(\n jobHandle: JobHandle<TName, TInput, TOutput> | null,\n options: UseAutoResumeOptions,\n callbacks: UseAutoResumeCallbacks,\n): void {\n const enabled = options.enabled !== false\n const skipIfInitialRunId = options.skipIfInitialRunId !== false\n const initialRunId = options.initialRunId\n\n useEffect(() => {\n if (!jobHandle) return\n if (!enabled) return\n if (skipIfInitialRunId && initialRunId) return\n\n let cancelled = false\n\n const findActiveRun = async () => {\n // First check for running runs\n const runningRuns = await jobHandle.getRuns({ status: 'running' })\n if (cancelled) return\n\n if (runningRuns.length > 0) {\n const run = runningRuns[0]\n callbacks.onRunFound(run.id, run.status as RunStatus)\n return\n }\n\n // Then check for pending runs\n const pendingRuns = await jobHandle.getRuns({ status: 'pending' })\n if (cancelled) return\n\n if (pendingRuns.length > 0) {\n const run = pendingRuns[0]\n callbacks.onRunFound(run.id, run.status as RunStatus)\n }\n }\n\n findActiveRun()\n\n return () => {\n cancelled = true\n }\n }, [jobHandle, enabled, skipIfInitialRunId, initialRunId, callbacks])\n}\n","import type { Durably } from '@coji/durably'\nimport { useCallback, useEffect, useReducer, useRef } from 'react'\nimport {\n initialSubscriptionState,\n subscriptionReducer,\n type SubscriptionAction,\n} from '../shared/subscription-reducer'\nimport type { SubscriptionState } from '../types'\n\nexport interface UseJobSubscriptionOptions {\n /**\n * Automatically switch to tracking the latest running job when a new run starts.\n * @default true\n */\n followLatest?: boolean\n /**\n * Maximum number of logs to keep (0 = unlimited)\n */\n maxLogs?: number\n}\n\nexport interface UseJobSubscriptionResult<\n TOutput = unknown,\n> extends SubscriptionState<TOutput> {\n /**\n * Current run ID being tracked\n */\n currentRunId: string | null\n /**\n * Set the current run ID to track\n */\n setCurrentRunId: (runId: string | null) => void\n /**\n * Clear all logs\n */\n clearLogs: () => void\n /**\n * Reset all state including currentRunId\n */\n reset: () => void\n}\n\n// Extended state for job subscription (includes currentRunId)\ninterface JobSubscriptionState<\n TOutput = unknown,\n> extends SubscriptionState<TOutput> {\n currentRunId: string | null\n}\n\n// Extended actions for job subscription\ntype JobSubscriptionAction<TOutput = unknown> =\n | SubscriptionAction<TOutput>\n | { type: 'set_run_id'; runId: string | null }\n | {\n type: 'switch_to_run'\n runId: string\n }\n\nfunction jobSubscriptionReducer<TOutput = unknown>(\n state: JobSubscriptionState<TOutput>,\n action: JobSubscriptionAction<TOutput>,\n): JobSubscriptionState<TOutput> {\n switch (action.type) {\n case 'set_run_id':\n return { ...state, currentRunId: action.runId }\n\n case 'switch_to_run':\n // Switch to a new run, resetting state\n return {\n ...initialSubscriptionState,\n currentRunId: action.runId,\n status: 'running',\n } as JobSubscriptionState<TOutput>\n\n case 'reset':\n return {\n ...(initialSubscriptionState as SubscriptionState<TOutput>),\n currentRunId: null,\n }\n\n default:\n // Delegate to base subscription reducer\n return {\n ...subscriptionReducer(state, action as SubscriptionAction<TOutput>),\n currentRunId: state.currentRunId,\n }\n }\n}\n\n/**\n * Hook for subscribing to job events with followLatest support.\n * This is a specialized version of useSubscription for job-level tracking.\n */\nexport function useJobSubscription<TOutput = unknown>(\n durably: Durably | null,\n jobName: string,\n options?: UseJobSubscriptionOptions,\n): UseJobSubscriptionResult<TOutput> {\n const initialState: JobSubscriptionState<TOutput> = {\n ...(initialSubscriptionState as SubscriptionState<TOutput>),\n currentRunId: null,\n }\n\n const [state, dispatch] = useReducer(\n jobSubscriptionReducer<TOutput>,\n initialState,\n )\n\n const currentRunIdRef = useRef<string | null>(null)\n currentRunIdRef.current = state.currentRunId\n\n const followLatest = options?.followLatest !== false\n const maxLogs = options?.maxLogs ?? 0\n\n useEffect(() => {\n if (!durably) return\n\n const unsubscribes: (() => void)[] = []\n\n unsubscribes.push(\n durably.on('run:start', (event) => {\n if (event.jobName !== jobName) return\n\n if (followLatest) {\n // Switch to tracking the new run\n dispatch({ type: 'switch_to_run', runId: event.runId })\n currentRunIdRef.current = event.runId\n } else {\n // Only update if this is our current run\n if (event.runId !== currentRunIdRef.current) return\n dispatch({ type: 'run:start' })\n }\n }),\n )\n\n unsubscribes.push(\n durably.on('run:complete', (event) => {\n if (event.runId !== currentRunIdRef.current) return\n dispatch({ type: 'run:complete', output: event.output as TOutput })\n }),\n )\n\n unsubscribes.push(\n durably.on('run:fail', (event) => {\n if (event.runId !== currentRunIdRef.current) return\n dispatch({ type: 'run:fail', error: event.error })\n }),\n )\n\n unsubscribes.push(\n durably.on('run:cancel', (event) => {\n if (event.runId !== currentRunIdRef.current) return\n dispatch({ type: 'run:cancel' })\n }),\n )\n\n unsubscribes.push(\n durably.on('run:retry', (event) => {\n if (event.runId !== currentRunIdRef.current) return\n dispatch({ type: 'run:retry' })\n }),\n )\n\n unsubscribes.push(\n durably.on('run:progress', (event) => {\n if (event.runId !== currentRunIdRef.current) return\n dispatch({ type: 'run:progress', progress: event.progress })\n }),\n )\n\n unsubscribes.push(\n durably.on('log:write', (event) => {\n if (event.runId !== currentRunIdRef.current) return\n dispatch({\n type: 'log:write',\n runId: event.runId,\n stepName: event.stepName,\n level: event.level,\n message: event.message,\n data: event.data,\n maxLogs,\n })\n }),\n )\n\n return () => {\n for (const unsubscribe of unsubscribes) {\n unsubscribe()\n }\n }\n }, [durably, jobName, followLatest, maxLogs])\n\n const setCurrentRunId = useCallback((runId: string | null) => {\n dispatch({ type: 'set_run_id', runId })\n currentRunIdRef.current = runId\n }, [])\n\n const clearLogs = useCallback(() => {\n dispatch({ type: 'clear_logs' })\n }, [])\n\n const reset = useCallback(() => {\n dispatch({ type: 'reset' })\n currentRunIdRef.current = null\n }, [])\n\n return {\n ...state,\n setCurrentRunId,\n clearLogs,\n reset,\n }\n}\n","import type { Durably } from '@coji/durably'\nimport { useMemo } from 'react'\nimport { createDurablyEventSubscriber } from '../shared/durably-event-subscriber'\nimport {\n useSubscription,\n type UseSubscriptionOptions,\n type UseSubscriptionResult,\n} from '../shared/use-subscription'\nimport type { SubscriptionState } from '../types'\n\n/** @deprecated Use SubscriptionState from '../types' instead */\nexport type RunSubscriptionState<TOutput = unknown> = SubscriptionState<TOutput>\n\n/** @deprecated Use UseSubscriptionOptions from '../shared/use-subscription' instead */\nexport type UseRunSubscriptionOptions = UseSubscriptionOptions\n\n/** @deprecated Use UseSubscriptionResult from '../shared/use-subscription' instead */\nexport type UseRunSubscriptionResult<TOutput = unknown> =\n UseSubscriptionResult<TOutput>\n\n/**\n * Internal hook for subscribing to run events via Durably.on().\n * Shared by useJob, useJobRun, and useJobLogs.\n *\n * @deprecated Consider using useSubscription with createDurablyEventSubscriber directly.\n */\nexport function useRunSubscription<TOutput = unknown>(\n durably: Durably | null,\n runId: string | null,\n options?: UseRunSubscriptionOptions,\n): UseRunSubscriptionResult<TOutput> {\n const subscriber = useMemo(\n () => (durably ? createDurablyEventSubscriber(durably) : null),\n [durably],\n )\n\n return useSubscription<TOutput>(subscriber, runId, options)\n}\n","import type { Durably } from '@coji/durably'\nimport type { EventSubscriber, SubscriptionEvent } from './event-subscriber'\n\n/**\n * EventSubscriber implementation using Durably.on() for direct subscriptions.\n * Used in browser environments where Durably instance is available.\n */\nexport function createDurablyEventSubscriber(\n durably: Durably,\n): EventSubscriber {\n return {\n subscribe<TOutput = unknown>(\n runId: string,\n onEvent: (event: SubscriptionEvent<TOutput>) => void,\n ): () => void {\n const unsubscribes: (() => void)[] = []\n\n unsubscribes.push(\n durably.on('run:start', (event) => {\n if (event.runId !== runId) return\n onEvent({ type: 'run:start' })\n }),\n )\n\n unsubscribes.push(\n durably.on('run:complete', (event) => {\n if (event.runId !== runId) return\n onEvent({ type: 'run:complete', output: event.output as TOutput })\n }),\n )\n\n unsubscribes.push(\n durably.on('run:fail', (event) => {\n if (event.runId !== runId) return\n onEvent({ type: 'run:fail', error: event.error })\n }),\n )\n\n unsubscribes.push(\n durably.on('run:cancel', (event) => {\n if (event.runId !== runId) return\n onEvent({ type: 'run:cancel' })\n }),\n )\n\n unsubscribes.push(\n durably.on('run:retry', (event) => {\n if (event.runId !== runId) return\n onEvent({ type: 'run:retry' })\n }),\n )\n\n unsubscribes.push(\n durably.on('run:progress', (event) => {\n if (event.runId !== runId) return\n onEvent({ type: 'run:progress', progress: event.progress })\n }),\n )\n\n unsubscribes.push(\n durably.on('log:write', (event) => {\n if (event.runId !== runId) return\n onEvent({\n type: 'log:write',\n runId: event.runId,\n stepName: event.stepName,\n level: event.level,\n message: event.message,\n data: event.data,\n })\n }),\n )\n\n return () => {\n for (const unsubscribe of unsubscribes) {\n unsubscribe()\n }\n }\n },\n }\n}\n","import { useDurably } from '../context'\nimport type { LogEntry } from '../types'\nimport { useRunSubscription } from './use-run-subscription'\n\nexport interface UseJobLogsOptions {\n /**\n * The run ID to subscribe to logs for\n */\n runId: string | null\n /**\n * Maximum number of logs to keep (default: unlimited)\n */\n maxLogs?: number\n}\n\nexport interface UseJobLogsResult {\n /**\n * Logs collected during execution\n */\n logs: LogEntry[]\n /**\n * Clear all logs\n */\n clearLogs: () => void\n}\n\n/**\n * Hook for subscribing to logs from a run.\n * Use this when you only need logs, not full run status.\n */\nexport function useJobLogs(options: UseJobLogsOptions): UseJobLogsResult {\n const { durably } = useDurably()\n const { runId, maxLogs } = options\n\n const subscription = useRunSubscription(durably, runId, { maxLogs })\n\n return {\n logs: subscription.logs,\n clearLogs: subscription.clearLogs,\n }\n}\n","import { useEffect, useRef } from 'react'\nimport { useDurably } from '../context'\nimport type { LogEntry, Progress, RunStatus } from '../types'\nimport { useRunSubscription } from './use-run-subscription'\n\nexport interface UseJobRunOptions {\n /**\n * The run ID to subscribe to\n */\n runId: string | null\n}\n\nexport interface UseJobRunResult<TOutput = unknown> {\n /**\n * Current run status\n */\n status: RunStatus | null\n /**\n * Output from completed run\n */\n output: TOutput | null\n /**\n * Error message from failed run\n */\n error: string | null\n /**\n * Logs collected during execution\n */\n logs: LogEntry[]\n /**\n * Current progress\n */\n progress: Progress | null\n /**\n * Whether a run is currently running\n */\n isRunning: boolean\n /**\n * Whether a run is pending\n */\n isPending: boolean\n /**\n * Whether the run completed successfully\n */\n isCompleted: boolean\n /**\n * Whether the run failed\n */\n isFailed: boolean\n /**\n * Whether the run was cancelled\n */\n isCancelled: boolean\n}\n\n/**\n * Hook for subscribing to an existing run by ID.\n * Use this when you have a runId and want to track its status.\n */\nexport function useJobRun<TOutput = unknown>(\n options: UseJobRunOptions,\n): UseJobRunResult<TOutput> {\n const { durably } = useDurably()\n const { runId } = options\n\n const subscription = useRunSubscription<TOutput>(durably, runId)\n\n // Fetch initial state when runId changes\n const fetchedRef = useRef<Set<string>>(new Set())\n\n useEffect(() => {\n if (!durably || !runId || fetchedRef.current.has(runId)) return\n\n // Mark as fetched to avoid duplicate fetches\n fetchedRef.current.add(runId)\n\n // Try to fetch current run state\n // Note: We need to use internal APIs or polling here\n // For now, we rely on event-based updates\n }, [durably, runId])\n\n return {\n status: subscription.status,\n output: subscription.output,\n error: subscription.error,\n logs: subscription.logs,\n progress: subscription.progress,\n isRunning: subscription.status === 'running',\n isPending: subscription.status === 'pending',\n isCompleted: subscription.status === 'completed',\n isFailed: subscription.status === 'failed',\n isCancelled: subscription.status === 'cancelled',\n }\n}\n","import type { JobDefinition } from '@coji/durably'\nimport { useCallback, useEffect, useState } from 'react'\nimport { useDurably } from '../context'\nimport { type TypedRun, isJobDefinition } from '../types'\n\n// Re-export TypedRun for convenience\nexport type { TypedRun } from '../types'\n\nexport interface UseRunsOptions {\n /**\n * Filter by job name\n */\n jobName?: string\n /**\n * Filter by status\n */\n status?: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled'\n /**\n * Number of runs per page\n * @default 10\n */\n pageSize?: number\n /**\n * Subscribe to real-time updates\n * @default true\n */\n realtime?: boolean\n}\n\nexport interface UseRunsResult<\n TInput extends Record<string, unknown> = Record<string, unknown>,\n TOutput extends Record<string, unknown> | undefined =\n | Record<string, unknown>\n | undefined,\n> {\n /**\n * List of runs for the current page\n */\n runs: TypedRun<TInput, TOutput>[]\n /**\n * Current page (0-indexed)\n */\n page: number\n /**\n * Whether there are more pages\n */\n hasMore: boolean\n /**\n * Whether data is being loaded\n */\n isLoading: boolean\n /**\n * Go to the next page\n */\n nextPage: () => void\n /**\n * Go to the previous page\n */\n prevPage: () => void\n /**\n * Go to a specific page\n */\n goToPage: (page: number) => void\n /**\n * Refresh the current page\n */\n refresh: () => Promise<void>\n}\n\n/**\n * Hook for listing runs with pagination and real-time updates.\n *\n * @example With generic type parameter (dashboard with multiple job types)\n * ```tsx\n * type DashboardRun = TypedRun<ImportInput, ImportOutput> | TypedRun<SyncInput, SyncOutput>\n *\n * function Dashboard() {\n * const { runs } = useRuns<DashboardRun>({ pageSize: 10 })\n * // runs are typed as DashboardRun[]\n * }\n * ```\n *\n * @example With JobDefinition (single job, auto-filters by jobName)\n * ```tsx\n * const myJob = defineJob({ name: 'my-job', ... })\n *\n * function Dashboard() {\n * const { runs } = useRuns(myJob)\n * // runs[0].output is typed!\n * return <div>{runs[0]?.output?.someField}</div>\n * }\n * ```\n *\n * @example With options only (untyped)\n * ```tsx\n * function Dashboard() {\n * const { runs } = useRuns({ pageSize: 20 })\n * // runs[0].output is unknown\n * }\n * ```\n */\n// Overload 1: With generic type parameter\nexport function useRuns<\n TRun extends TypedRun<\n Record<string, unknown>,\n Record<string, unknown> | undefined\n >,\n>(\n options?: UseRunsOptions,\n): UseRunsResult<\n TRun extends TypedRun<infer I, infer _O> ? I : Record<string, unknown>,\n TRun extends TypedRun<infer _I, infer O> ? O : Record<string, unknown>\n>\n\n// Overload 2: With JobDefinition for type inference (auto-filters by jobName)\nexport function useRuns<\n TName extends string,\n TInput extends Record<string, unknown>,\n TOutput extends Record<string, unknown> | undefined,\n>(\n jobDefinition: JobDefinition<TName, TInput, TOutput>,\n options?: Omit<UseRunsOptions, 'jobName'>,\n): UseRunsResult<TInput, TOutput>\n\n// Overload 3: Without type parameter (untyped, backward compatible)\nexport function useRuns(options?: UseRunsOptions): UseRunsResult\n\n// Implementation\nexport function useRuns<\n TName extends string,\n TInput extends Record<string, unknown>,\n TOutput extends Record<string, unknown> | undefined,\n>(\n jobDefinitionOrOptions?:\n | JobDefinition<TName, TInput, TOutput>\n | UseRunsOptions,\n optionsArg?: Omit<UseRunsOptions, 'jobName'>,\n): UseRunsResult<TInput, TOutput> {\n const { durably } = useDurably()\n\n // Determine if first argument is a JobDefinition using type guard\n const isJob = isJobDefinition(jobDefinitionOrOptions)\n\n const jobName = isJob\n ? jobDefinitionOrOptions.name\n : (jobDefinitionOrOptions as UseRunsOptions | undefined)?.jobName\n\n const options = isJob\n ? optionsArg\n : (jobDefinitionOrOptions as UseRunsOptions | undefined)\n\n const pageSize = options?.pageSize ?? 10\n const realtime = options?.realtime ?? true\n const status = options?.status\n\n const [runs, setRuns] = useState<TypedRun<TInput, TOutput>[]>([])\n const [page, setPage] = useState(0)\n const [hasMore, setHasMore] = useState(false)\n const [isLoading, setIsLoading] = useState(false)\n\n const refresh = useCallback(async () => {\n if (!durably) return\n\n setIsLoading(true)\n try {\n const data = await durably.getRuns({\n jobName,\n status,\n limit: pageSize + 1,\n offset: page * pageSize,\n })\n setHasMore(data.length > pageSize)\n setRuns(data.slice(0, pageSize) as TypedRun<TInput, TOutput>[])\n } finally {\n setIsLoading(false)\n }\n }, [durably, jobName, status, pageSize, page])\n\n // Initial fetch and subscribe to events\n useEffect(() => {\n if (!durably) return\n\n refresh()\n\n if (!realtime) return\n\n const unsubscribes = [\n durably.on('run:trigger', refresh),\n durably.on('run:start', refresh),\n durably.on('run:complete', refresh),\n durably.on('run:fail', refresh),\n durably.on('run:cancel', refresh),\n durably.on('run:retry', refresh),\n durably.on('run:progress', refresh),\n durably.on('step:start', refresh),\n durably.on('step:complete', refresh),\n ]\n\n return () => {\n for (const unsubscribe of unsubscribes) {\n unsubscribe()\n }\n }\n }, [durably, refresh, realtime])\n\n const nextPage = useCallback(() => {\n if (hasMore) {\n setPage((p) => p + 1)\n }\n }, [hasMore])\n\n const prevPage = useCallback(() => {\n setPage((p) => Math.max(0, p - 1))\n }, [])\n\n const goToPage = useCallback((newPage: number) => {\n setPage(Math.max(0, newPage))\n }, [])\n\n return {\n runs,\n page,\n hasMore,\n isLoading,\n nextPage,\n prevPage,\n goToPage,\n refresh,\n }\n}\n"],"mappings":"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","names":["useCallback","useEffect","useRef","useEffect","useEffect","useRef","useEffect","useCallback","useMemo","useMemo","useEffect","useRef","useRef","useEffect","useCallback","useEffect","useCallback","useEffect"]}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { Run, JobDefinition } from '@coji/durably';
|
|
2
|
+
|
|
3
|
+
type InferInput<T> = T extends JobDefinition<string, infer TInput, unknown> ? TInput extends Record<string, unknown> ? TInput : Record<string, unknown> : T extends {
|
|
4
|
+
trigger: (input: infer TInput) => unknown;
|
|
5
|
+
} ? TInput extends Record<string, unknown> ? TInput : Record<string, unknown> : Record<string, unknown>;
|
|
6
|
+
type InferOutput<T> = T extends JobDefinition<string, unknown, infer TOutput> ? TOutput extends Record<string, unknown> ? TOutput : Record<string, unknown> : T extends {
|
|
7
|
+
trigger: (input: unknown) => Promise<{
|
|
8
|
+
output?: infer TOutput;
|
|
9
|
+
}>;
|
|
10
|
+
} ? TOutput extends Record<string, unknown> ? TOutput : Record<string, unknown> : Record<string, unknown>;
|
|
11
|
+
type RunStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
|
|
12
|
+
interface Progress {
|
|
13
|
+
current: number;
|
|
14
|
+
total?: number;
|
|
15
|
+
message?: string;
|
|
16
|
+
}
|
|
17
|
+
interface LogEntry {
|
|
18
|
+
id: string;
|
|
19
|
+
runId: string;
|
|
20
|
+
stepName: string | null;
|
|
21
|
+
level: 'info' | 'warn' | 'error';
|
|
22
|
+
message: string;
|
|
23
|
+
data: unknown;
|
|
24
|
+
timestamp: string;
|
|
25
|
+
}
|
|
26
|
+
type DurablyEvent = {
|
|
27
|
+
type: 'run:start';
|
|
28
|
+
runId: string;
|
|
29
|
+
jobName: string;
|
|
30
|
+
payload: unknown;
|
|
31
|
+
} | {
|
|
32
|
+
type: 'run:complete';
|
|
33
|
+
runId: string;
|
|
34
|
+
jobName: string;
|
|
35
|
+
output: unknown;
|
|
36
|
+
duration: number;
|
|
37
|
+
} | {
|
|
38
|
+
type: 'run:fail';
|
|
39
|
+
runId: string;
|
|
40
|
+
jobName: string;
|
|
41
|
+
error: string;
|
|
42
|
+
} | {
|
|
43
|
+
type: 'run:cancel';
|
|
44
|
+
runId: string;
|
|
45
|
+
jobName: string;
|
|
46
|
+
} | {
|
|
47
|
+
type: 'run:retry';
|
|
48
|
+
runId: string;
|
|
49
|
+
jobName: string;
|
|
50
|
+
} | {
|
|
51
|
+
type: 'run:progress';
|
|
52
|
+
runId: string;
|
|
53
|
+
jobName: string;
|
|
54
|
+
progress: Progress;
|
|
55
|
+
} | {
|
|
56
|
+
type: 'step:start';
|
|
57
|
+
runId: string;
|
|
58
|
+
jobName: string;
|
|
59
|
+
stepName: string;
|
|
60
|
+
stepIndex: number;
|
|
61
|
+
} | {
|
|
62
|
+
type: 'step:complete';
|
|
63
|
+
runId: string;
|
|
64
|
+
jobName: string;
|
|
65
|
+
stepName: string;
|
|
66
|
+
stepIndex: number;
|
|
67
|
+
output: unknown;
|
|
68
|
+
} | {
|
|
69
|
+
type: 'log:write';
|
|
70
|
+
runId: string;
|
|
71
|
+
jobName: string;
|
|
72
|
+
level: 'info' | 'warn' | 'error';
|
|
73
|
+
message: string;
|
|
74
|
+
data: unknown;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* A typed version of Run with generic payload/output types.
|
|
78
|
+
* Used by browser hooks (direct durably access).
|
|
79
|
+
*/
|
|
80
|
+
type TypedRun<TInput extends Record<string, unknown> = Record<string, unknown>, TOutput extends Record<string, unknown> | undefined = Record<string, unknown> | undefined> = Omit<Run, 'payload' | 'output'> & {
|
|
81
|
+
payload: TInput;
|
|
82
|
+
output: TOutput | null;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Run type for client mode (matches server response).
|
|
86
|
+
* Used by client hooks (HTTP/SSE connection).
|
|
87
|
+
*/
|
|
88
|
+
interface ClientRun {
|
|
89
|
+
id: string;
|
|
90
|
+
jobName: string;
|
|
91
|
+
status: RunStatus;
|
|
92
|
+
input: unknown;
|
|
93
|
+
output: unknown | null;
|
|
94
|
+
error: string | null;
|
|
95
|
+
currentStepIndex: number;
|
|
96
|
+
stepCount: number;
|
|
97
|
+
progress: Progress | null;
|
|
98
|
+
createdAt: string;
|
|
99
|
+
startedAt: string | null;
|
|
100
|
+
completedAt: string | null;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* A typed version of ClientRun with generic input/output types.
|
|
104
|
+
* Used by client hooks (HTTP/SSE connection).
|
|
105
|
+
*/
|
|
106
|
+
type TypedClientRun<TInput extends Record<string, unknown> = Record<string, unknown>, TOutput extends Record<string, unknown> | undefined = Record<string, unknown> | undefined> = Omit<ClientRun, 'input' | 'output'> & {
|
|
107
|
+
input: TInput;
|
|
108
|
+
output: TOutput | null;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export type { ClientRun as C, DurablyEvent as D, InferInput as I, LogEntry as L, Progress as P, RunStatus as R, TypedRun as T, InferOutput as a, TypedClientRun as b };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coji/durably-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "React bindings for Durably - step-oriented resumable batch execution",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"typescript": "^5.9.3",
|
|
68
68
|
"vitest": "^4.0.16",
|
|
69
69
|
"zod": "^4.3.4",
|
|
70
|
-
"@coji/durably": "0.
|
|
70
|
+
"@coji/durably": "0.7.0"
|
|
71
71
|
},
|
|
72
72
|
"scripts": {
|
|
73
73
|
"build": "tsup",
|
package/dist/types-BDUvsa8u.d.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
type RunStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
|
|
2
|
-
interface Progress {
|
|
3
|
-
current: number;
|
|
4
|
-
total?: number;
|
|
5
|
-
message?: string;
|
|
6
|
-
}
|
|
7
|
-
interface LogEntry {
|
|
8
|
-
id: string;
|
|
9
|
-
runId: string;
|
|
10
|
-
stepName: string | null;
|
|
11
|
-
level: 'info' | 'warn' | 'error';
|
|
12
|
-
message: string;
|
|
13
|
-
data: unknown;
|
|
14
|
-
timestamp: string;
|
|
15
|
-
}
|
|
16
|
-
type DurablyEvent = {
|
|
17
|
-
type: 'run:start';
|
|
18
|
-
runId: string;
|
|
19
|
-
jobName: string;
|
|
20
|
-
payload: unknown;
|
|
21
|
-
} | {
|
|
22
|
-
type: 'run:complete';
|
|
23
|
-
runId: string;
|
|
24
|
-
jobName: string;
|
|
25
|
-
output: unknown;
|
|
26
|
-
duration: number;
|
|
27
|
-
} | {
|
|
28
|
-
type: 'run:fail';
|
|
29
|
-
runId: string;
|
|
30
|
-
jobName: string;
|
|
31
|
-
error: string;
|
|
32
|
-
} | {
|
|
33
|
-
type: 'run:cancel';
|
|
34
|
-
runId: string;
|
|
35
|
-
jobName: string;
|
|
36
|
-
} | {
|
|
37
|
-
type: 'run:retry';
|
|
38
|
-
runId: string;
|
|
39
|
-
jobName: string;
|
|
40
|
-
} | {
|
|
41
|
-
type: 'run:progress';
|
|
42
|
-
runId: string;
|
|
43
|
-
jobName: string;
|
|
44
|
-
progress: Progress;
|
|
45
|
-
} | {
|
|
46
|
-
type: 'step:start';
|
|
47
|
-
runId: string;
|
|
48
|
-
jobName: string;
|
|
49
|
-
stepName: string;
|
|
50
|
-
stepIndex: number;
|
|
51
|
-
} | {
|
|
52
|
-
type: 'step:complete';
|
|
53
|
-
runId: string;
|
|
54
|
-
jobName: string;
|
|
55
|
-
stepName: string;
|
|
56
|
-
stepIndex: number;
|
|
57
|
-
output: unknown;
|
|
58
|
-
} | {
|
|
59
|
-
type: 'log:write';
|
|
60
|
-
runId: string;
|
|
61
|
-
jobName: string;
|
|
62
|
-
level: 'info' | 'warn' | 'error';
|
|
63
|
-
message: string;
|
|
64
|
-
data: unknown;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
export type { DurablyEvent as D, LogEntry as L, Progress as P, RunStatus as R };
|