@microfox/ai-worker 1.0.1 → 1.0.3

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts"],"sourcesContent":["/**\n * Client for dispatching background worker jobs.\n *\n * In production, dispatching happens via the workers HTTP API:\n * POST /workers/trigger -> enqueues message to SQS on the workers service side\n *\n * This avoids requiring AWS credentials in your Next.js app.\n */\n\nimport type { ZodType, z } from 'zod';\n\nexport interface DispatchOptions {\n /**\n * Optional webhook callback URL to notify when the job finishes.\n * Only called when provided. Default: no webhook (use job store / MongoDB only).\n */\n webhookUrl?: string;\n /**\n * Controls how dispatch executes.\n * - \"auto\" (default): local inline execution in development unless WORKERS_LOCAL_MODE=false.\n * - \"local\": force inline execution (no SQS).\n * - \"remote\": force SQS/Lambda dispatch even in development.\n */\n mode?: 'auto' | 'local' | 'remote';\n jobId?: string;\n metadata?: Record<string, any>;\n}\n\nexport interface DispatchResult {\n messageId: string;\n status: 'queued';\n jobId: string;\n}\n\nexport interface SerializedContext {\n requestId?: string;\n userId?: string;\n traceId?: string;\n [key: string]: any;\n}\n\n/**\n * Derives the full /workers/trigger URL from env.\n *\n * Preferred env vars:\n * - WORKER_BASE_URL: base URL of the workers service (e.g. https://.../prod)\n * - NEXT_PUBLIC_WORKER_BASE_URL: same, but exposed to the browser\n *\n * Legacy env vars (still supported for backwards compatibility):\n * - WORKERS_TRIGGER_API_URL / NEXT_PUBLIC_WORKERS_TRIGGER_API_URL\n * - WORKERS_CONFIG_API_URL / NEXT_PUBLIC_WORKERS_CONFIG_API_URL\n */\nfunction getWorkersTriggerUrl(): string {\n const raw =\n process.env.WORKER_BASE_URL ||\n process.env.NEXT_PUBLIC_WORKER_BASE_URL ||\n process.env.WORKERS_TRIGGER_API_URL ||\n process.env.NEXT_PUBLIC_WORKERS_TRIGGER_API_URL ||\n process.env.WORKERS_CONFIG_API_URL ||\n process.env.NEXT_PUBLIC_WORKERS_CONFIG_API_URL;\n\n if (!raw) {\n throw new Error(\n 'WORKER_BASE_URL (preferred) or NEXT_PUBLIC_WORKER_BASE_URL is required for background workers'\n );\n }\n\n const url = new URL(raw);\n url.search = '';\n url.hash = '';\n\n const path = url.pathname || '';\n\n // If the user pointed at a specific endpoint, normalize back to the service root.\n url.pathname = path.replace(/\\/?workers\\/(trigger|config)\\/?$/, '');\n\n const basePath = url.pathname.replace(/\\/+$/, '');\n url.pathname = `${basePath}/workers/trigger`.replace(/\\/+$/, '');\n\n return url.toString();\n}\n\n/**\n * Serializes context data for transmission to Lambda.\n * Only serializes safe, JSON-compatible properties.\n */\nfunction serializeContext(ctx: any): SerializedContext {\n const serialized: SerializedContext = {};\n\n if (ctx.requestId) {\n serialized.requestId = ctx.requestId;\n }\n\n // Extract any additional serializable metadata\n if (ctx.metadata && typeof ctx.metadata === 'object') {\n Object.assign(serialized, ctx.metadata);\n }\n\n // Allow custom context serialization via a helper property\n if (ctx._serializeContext && typeof ctx._serializeContext === 'function') {\n const custom = ctx._serializeContext();\n Object.assign(serialized, custom);\n }\n\n return serialized;\n}\n\n/**\n * Dispatches a background worker job to SQS.\n *\n * @param workerId - The ID of the worker to dispatch\n * @param input - The input data for the worker (will be validated against inputSchema)\n * @param inputSchema - Zod schema for input validation\n * @param options - Dispatch options including webhook URL\n * @param ctx - Optional context object (only serializable parts will be sent)\n * @returns Promise resolving to dispatch result with messageId and jobId\n */\nexport async function dispatch<INPUT_SCHEMA extends ZodType<any>>(\n workerId: string,\n input: z.input<INPUT_SCHEMA>,\n inputSchema: INPUT_SCHEMA,\n options: DispatchOptions,\n ctx?: any\n): Promise<DispatchResult> {\n // Validate input against schema\n const validatedInput = inputSchema.parse(input);\n\n // Generate job ID if not provided\n const jobId =\n options.jobId || `job-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n\n // Resolve /workers/trigger endpoint URL\n const triggerUrl = getWorkersTriggerUrl();\n\n // Serialize context (only safe, JSON-compatible parts)\n const serializedContext = ctx ? serializeContext(ctx) : {};\n\n // Job updates use MongoDB only; never pass jobStoreUrl/origin URL.\n const messageBody = {\n workerId,\n jobId,\n input: validatedInput,\n context: serializedContext,\n webhookUrl: options.webhookUrl,\n metadata: options.metadata || {},\n timestamp: new Date().toISOString(),\n };\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n const triggerKey = process.env.WORKERS_TRIGGER_API_KEY;\n if (triggerKey) {\n headers['x-workers-trigger-key'] = triggerKey;\n }\n\n const response = await fetch(triggerUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n workerId,\n body: messageBody,\n }),\n });\n\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n throw new Error(\n `Failed to trigger worker \"${workerId}\": ${response.status} ${response.statusText}${text ? ` - ${text}` : ''}`\n );\n }\n\n const data = (await response.json().catch(() => ({}))) as any;\n const messageId = data?.messageId ? String(data.messageId) : `trigger-${jobId}`;\n\n return {\n messageId,\n status: 'queued',\n jobId,\n };\n}\n\n/**\n * Local development mode: runs the handler immediately in the same process.\n * This bypasses SQS and Lambda for faster iteration during development.\n *\n * @param handler - The worker handler function\n * @param input - The input data\n * @param ctx - The context object\n * @returns The handler result\n */\nexport async function dispatchLocal<INPUT, OUTPUT>(\n handler: (params: { input: INPUT; ctx: any }) => Promise<OUTPUT>,\n input: INPUT,\n ctx?: any\n): Promise<OUTPUT> {\n return handler({ input, ctx: ctx || {} });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoDA,SAAS,uBAA+B;AACtC,QAAM,MACJ,QAAQ,IAAI,mBACZ,QAAQ,IAAI,+BACZ,QAAQ,IAAI,2BACZ,QAAQ,IAAI,uCACZ,QAAQ,IAAI,0BACZ,QAAQ,IAAI;AAEd,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,MAAM,IAAI,IAAI,GAAG;AACvB,MAAI,SAAS;AACb,MAAI,OAAO;AAEX,QAAM,OAAO,IAAI,YAAY;AAG7B,MAAI,WAAW,KAAK,QAAQ,oCAAoC,EAAE;AAElE,QAAM,WAAW,IAAI,SAAS,QAAQ,QAAQ,EAAE;AAChD,MAAI,WAAW,GAAG,QAAQ,mBAAmB,QAAQ,QAAQ,EAAE;AAE/D,SAAO,IAAI,SAAS;AACtB;AAMA,SAAS,iBAAiB,KAA6B;AACrD,QAAM,aAAgC,CAAC;AAEvC,MAAI,IAAI,WAAW;AACjB,eAAW,YAAY,IAAI;AAAA,EAC7B;AAGA,MAAI,IAAI,YAAY,OAAO,IAAI,aAAa,UAAU;AACpD,WAAO,OAAO,YAAY,IAAI,QAAQ;AAAA,EACxC;AAGA,MAAI,IAAI,qBAAqB,OAAO,IAAI,sBAAsB,YAAY;AACxE,UAAM,SAAS,IAAI,kBAAkB;AACrC,WAAO,OAAO,YAAY,MAAM;AAAA,EAClC;AAEA,SAAO;AACT;AAYA,eAAsB,SACpB,UACA,OACA,aACA,SACA,KACyB;AAEzB,QAAM,iBAAiB,YAAY,MAAM,KAAK;AAG9C,QAAM,QACJ,QAAQ,SAAS,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC;AAG/E,QAAM,aAAa,qBAAqB;AAGxC,QAAM,oBAAoB,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAGzD,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP,SAAS;AAAA,IACT,YAAY,QAAQ;AAAA,IACpB,UAAU,QAAQ,YAAY,CAAC;AAAA,IAC/B,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,EACpC;AAEA,QAAM,UAAkC;AAAA,IACtC,gBAAgB;AAAA,EAClB;AACA,QAAM,aAAa,QAAQ,IAAI;AAC/B,MAAI,YAAY;AACd,YAAQ,uBAAuB,IAAI;AAAA,EACrC;AAEA,QAAM,WAAW,MAAM,MAAM,YAAY;AAAA,IACvC,QAAQ;AAAA,IACR;AAAA,IACA,MAAM,KAAK,UAAU;AAAA,MACnB;AAAA,MACA,MAAM;AAAA,IACR,CAAC;AAAA,EACH,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE;AACjD,UAAM,IAAI;AAAA,MACR,6BAA6B,QAAQ,MAAM,SAAS,MAAM,IAAI,SAAS,UAAU,GAAG,OAAO,MAAM,IAAI,KAAK,EAAE;AAAA,IAC9G;AAAA,EACF;AAEA,QAAM,OAAQ,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AACpD,QAAM,YAAY,MAAM,YAAY,OAAO,KAAK,SAAS,IAAI,WAAW,KAAK;AAE7E,SAAO;AAAA,IACL;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,EACF;AACF;AAWA,eAAsB,cACpB,SACA,OACA,KACiB;AACjB,SAAO,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,EAAE,CAAC;AAC1C;","names":[]}
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["/**\n * Client for dispatching background worker jobs.\n *\n * In production, dispatching happens via the workers HTTP API:\n * POST /workers/trigger -> enqueues message to SQS on the workers service side\n *\n * This avoids requiring AWS credentials in your Next.js app.\n */\n\nimport type { ZodType, z } from 'zod';\nimport type { WorkerQueueConfig } from './queue.js';\n\nexport interface WorkerQueueRegistry {\n getQueueById(queueId: string): WorkerQueueConfig | undefined;\n /** (initialInput, previousOutputs) for best DX: derive next input from original request and all prior step outputs. */\n invokeMapInput?: (\n queueId: string,\n stepIndex: number,\n initialInput: unknown,\n previousOutputs: Array<{ stepIndex: number; workerId: string; output: unknown }>\n ) => Promise<unknown> | unknown;\n}\n\nexport interface DispatchOptions {\n /**\n * Optional webhook callback URL to notify when the job finishes.\n * Only called when provided. Default: no webhook (use job store / MongoDB only).\n */\n webhookUrl?: string;\n /**\n * Controls how dispatch executes.\n * - \"auto\" (default): local inline execution in development unless WORKERS_LOCAL_MODE=false.\n * - \"local\": force inline execution (no SQS).\n * - \"remote\": force SQS/Lambda dispatch even in development.\n */\n mode?: 'auto' | 'local' | 'remote';\n jobId?: string;\n metadata?: Record<string, any>;\n /**\n * In-memory queue registry for dispatchQueue. Required when using dispatchQueue.\n * Pass a registry that imports from your .queue.ts definitions (works on Vercel/serverless).\n */\n registry?: WorkerQueueRegistry;\n /**\n * Optional callback to create a queue job record before dispatching.\n * Called with queueJobId (= first worker's jobId), queueId, and firstStep.\n */\n onCreateQueueJob?: (params: {\n queueJobId: string;\n queueId: string;\n firstStep: { workerId: string; workerJobId: string };\n metadata?: Record<string, unknown>;\n }) => Promise<void>;\n}\n\nexport interface DispatchResult {\n messageId: string;\n status: 'queued';\n jobId: string;\n}\n\nexport interface DispatchQueueResult extends DispatchResult {\n queueId: string;\n}\n\nexport interface SerializedContext {\n requestId?: string;\n userId?: string;\n traceId?: string;\n [key: string]: any;\n}\n\n/**\n * Derives the full /workers/trigger URL from env.\n * Exported for use by local dispatchWorker (worker-to-worker in dev).\n * Server-side only; clients should use useWorkflowJob with your app's /api/workflows routes.\n *\n * Env vars:\n * - WORKER_BASE_URL: base URL of the workers service (e.g. https://.../prod)\n * - WORKERS_TRIGGER_API_URL / WORKERS_CONFIG_API_URL: legacy, still supported\n */\nexport function getWorkersTriggerUrl(): string {\n const raw =\n process.env.WORKER_BASE_URL ||\n process.env.WORKERS_TRIGGER_API_URL ||\n process.env.WORKERS_CONFIG_API_URL;\n\n if (!raw) {\n throw new Error(\n 'WORKER_BASE_URL is required for background workers. Set it server-side only.'\n );\n }\n\n const url = new URL(raw);\n url.search = '';\n url.hash = '';\n\n const path = url.pathname || '';\n\n // If the user pointed at a specific endpoint, normalize back to the service root.\n url.pathname = path.replace(/\\/?workers\\/(trigger|config)\\/?$/, '');\n\n const basePath = url.pathname.replace(/\\/+$/, '');\n url.pathname = `${basePath}/workers/trigger`.replace(/\\/+$/, '');\n\n return url.toString();\n}\n\n/**\n * URL for the queue start endpoint (dispatch proxy). Use this so queue starts\n * go through the queue handler Lambda for easier debugging (one log stream per queue).\n */\nexport function getQueueStartUrl(queueId: string): string {\n const raw =\n process.env.WORKER_BASE_URL ||\n process.env.WORKERS_TRIGGER_API_URL ||\n process.env.WORKERS_CONFIG_API_URL;\n\n if (!raw) {\n throw new Error(\n 'WORKER_BASE_URL is required for background workers. Set it server-side only.'\n );\n }\n\n const url = new URL(raw);\n url.search = '';\n url.hash = '';\n\n const path = url.pathname || '';\n url.pathname = path.replace(/\\/?workers\\/(trigger|config)\\/?$/, '');\n const basePath = url.pathname.replace(/\\/+$/, '');\n const safeSegment = encodeURIComponent(queueId);\n url.pathname = `${basePath}/queues/${safeSegment}/start`.replace(/\\/+$/, '');\n\n return url.toString();\n}\n\n/**\n * Serializes context data for transmission to Lambda.\n * Only serializes safe, JSON-compatible properties.\n */\nfunction serializeContext(ctx: any): SerializedContext {\n const serialized: SerializedContext = {};\n\n if (ctx.requestId) {\n serialized.requestId = ctx.requestId;\n }\n\n // Extract any additional serializable metadata\n if (ctx.metadata && typeof ctx.metadata === 'object') {\n Object.assign(serialized, ctx.metadata);\n }\n\n // Allow custom context serialization via a helper property\n if (ctx._serializeContext && typeof ctx._serializeContext === 'function') {\n const custom = ctx._serializeContext();\n Object.assign(serialized, custom);\n }\n\n return serialized;\n}\n\n\n/**\n * Dispatches a background worker job to SQS.\n *\n * @param workerId - The ID of the worker to dispatch\n * @param input - The input data for the worker (will be validated against inputSchema)\n * @param inputSchema - Zod schema for input validation\n * @param options - Dispatch options including webhook URL\n * @param ctx - Optional context object (only serializable parts will be sent)\n * @returns Promise resolving to dispatch result with messageId and jobId\n */\nexport async function dispatch<INPUT_SCHEMA extends ZodType<any>>(\n workerId: string,\n input: z.input<INPUT_SCHEMA>,\n inputSchema: INPUT_SCHEMA,\n options: DispatchOptions,\n ctx?: any\n): Promise<DispatchResult> {\n // Validate input against schema\n const validatedInput = inputSchema.parse(input);\n\n // Generate job ID if not provided\n const jobId =\n options.jobId || `job-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n\n // Resolve /workers/trigger endpoint URL\n const triggerUrl = getWorkersTriggerUrl();\n\n // Serialize context (only safe, JSON-compatible parts)\n const serializedContext = ctx ? serializeContext(ctx) : {};\n\n // Job updates use MongoDB only; never pass jobStoreUrl/origin URL.\n const messageBody = {\n workerId,\n jobId,\n input: validatedInput,\n context: serializedContext,\n webhookUrl: options.webhookUrl,\n metadata: options.metadata || {},\n timestamp: new Date().toISOString(),\n };\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n const triggerKey = process.env.WORKERS_TRIGGER_API_KEY;\n if (triggerKey) {\n headers['x-workers-trigger-key'] = triggerKey;\n }\n\n const response = await fetch(triggerUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n workerId,\n body: messageBody,\n }),\n });\n\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n throw new Error(\n `Failed to trigger worker \"${workerId}\": ${response.status} ${response.statusText}${text ? ` - ${text}` : ''}`\n );\n }\n\n const data = (await response.json().catch(() => ({}))) as any;\n const messageId = data?.messageId ? String(data.messageId) : `trigger-${jobId}`;\n\n return {\n messageId,\n status: 'queued',\n jobId,\n };\n}\n\n/**\n * Dispatch a worker by ID without importing the worker module.\n * Sends to the workers trigger API (WORKER_BASE_URL). No input schema validation at call site.\n *\n * @param workerId - The worker ID (e.g. 'echo', 'data-processor')\n * @param input - Input payload (object or undefined)\n * @param options - Optional jobId, webhookUrl, metadata\n * @param ctx - Optional context (serializable parts sent in the request)\n * @returns Promise resolving to { messageId, status: 'queued', jobId }\n */\nexport async function dispatchWorker(\n workerId: string,\n input?: Record<string, unknown>,\n options: DispatchOptions = {},\n ctx?: any\n): Promise<DispatchResult> {\n const jobId =\n options.jobId || `job-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n const triggerUrl = getWorkersTriggerUrl();\n const serializedContext = ctx ? serializeContext(ctx) : {};\n const messageBody = {\n workerId,\n jobId,\n input: input ?? {},\n context: serializedContext,\n webhookUrl: options.webhookUrl,\n metadata: options.metadata || {},\n timestamp: new Date().toISOString(),\n };\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n const triggerKey = process.env.WORKERS_TRIGGER_API_KEY;\n if (triggerKey) headers['x-workers-trigger-key'] = triggerKey;\n const response = await fetch(triggerUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify({ workerId, body: messageBody }),\n });\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n throw new Error(\n `Failed to trigger worker \"${workerId}\": ${response.status} ${response.statusText}${text ? ` - ${text}` : ''}`\n );\n }\n const data = (await response.json().catch(() => ({}))) as any;\n const messageId = data?.messageId ? String(data.messageId) : `trigger-${jobId}`;\n return { messageId, status: 'queued', jobId };\n}\n\n/**\n * Local development mode: runs the handler immediately in the same process.\n * This bypasses SQS and Lambda for faster iteration during development.\n *\n * @param handler - The worker handler function\n * @param input - The input data\n * @param ctx - The context object\n * @returns The handler result\n */\nexport async function dispatchLocal<INPUT, OUTPUT>(\n handler: (params: { input: INPUT; ctx: any }) => Promise<OUTPUT>,\n input: INPUT,\n ctx?: any\n): Promise<OUTPUT> {\n return handler({ input, ctx: ctx || {} });\n}\n\n/**\n * Dispatches a queue by ID. POSTs to the queue-start API; the queue-start handler creates the queue job.\n * Pass the first worker's input directly (no registry required).\n */\nexport async function dispatchQueue<InitialInput = any>(\n queueId: string,\n initialInput?: InitialInput,\n options: DispatchOptions = {},\n _ctx?: any\n): Promise<DispatchQueueResult> {\n const jobId =\n options.jobId || `job-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n const queueStartUrl = getQueueStartUrl(queueId);\n const normalizedInput =\n initialInput !== null && typeof initialInput === 'object'\n ? (initialInput as Record<string, unknown>)\n : { value: initialInput };\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n const triggerKey = process.env.WORKERS_TRIGGER_API_KEY;\n if (triggerKey) headers['x-workers-trigger-key'] = triggerKey;\n const response = await fetch(queueStartUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n input: normalizedInput,\n initialInput: normalizedInput,\n metadata: options.metadata ?? {},\n jobId,\n ...(options.webhookUrl ? { webhookUrl: options.webhookUrl } : {}),\n }),\n });\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n throw new Error(\n `Failed to start queue \"${queueId}\": ${response.status} ${response.statusText}${text ? ` - ${text}` : ''}`\n );\n }\n const data = (await response.json().catch(() => ({}))) as any;\n const messageId = data?.messageId ?? data?.jobId ?? `queue-${jobId}`;\n return { queueId, messageId, status: 'queued', jobId };\n}\n\n"],"mappings":"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","names":[]}
package/dist/client.mjs CHANGED
@@ -1,10 +1,18 @@
1
1
  import {
2
2
  dispatch,
3
- dispatchLocal
4
- } from "./chunk-FQCZSXDI.mjs";
3
+ dispatchLocal,
4
+ dispatchQueue,
5
+ dispatchWorker,
6
+ getQueueStartUrl,
7
+ getWorkersTriggerUrl
8
+ } from "./chunk-72XGFZCE.mjs";
5
9
  import "./chunk-BJTO5JO5.mjs";
6
10
  export {
7
11
  dispatch,
8
- dispatchLocal
12
+ dispatchLocal,
13
+ dispatchQueue,
14
+ dispatchWorker,
15
+ getQueueStartUrl,
16
+ getWorkersTriggerUrl
9
17
  };
10
18
  //# sourceMappingURL=client.mjs.map
@@ -19,6 +19,25 @@ interface JobStoreUpdate {
19
19
  name?: string;
20
20
  };
21
21
  }
22
+ interface JobRecord {
23
+ jobId: string;
24
+ workerId: string;
25
+ status: 'queued' | 'running' | 'completed' | 'failed';
26
+ input: any;
27
+ output?: any;
28
+ error?: {
29
+ message: string;
30
+ stack?: string;
31
+ };
32
+ metadata?: Record<string, any>;
33
+ internalJobs?: Array<{
34
+ jobId: string;
35
+ workerId: string;
36
+ }>;
37
+ createdAt: string;
38
+ updatedAt: string;
39
+ completedAt?: string;
40
+ }
22
41
  interface JobStore {
23
42
  /**
24
43
  * Update job in job store.
@@ -29,22 +48,50 @@ interface JobStore {
29
48
  * Get current job record from job store.
30
49
  * @returns Job record or null if not found
31
50
  */
32
- get(): Promise<{
51
+ get(): Promise<JobRecord | null>;
52
+ /**
53
+ * Append an internal (child) job to the current job's internalJobs list.
54
+ * Used when this worker dispatches another worker (fire-and-forget or await).
55
+ */
56
+ appendInternalJob?(entry: {
33
57
  jobId: string;
34
58
  workerId: string;
35
- status: 'queued' | 'running' | 'completed' | 'failed';
36
- input: any;
37
- output?: any;
38
- error?: {
39
- message: string;
40
- stack?: string;
41
- };
42
- metadata?: Record<string, any>;
43
- createdAt: string;
44
- updatedAt: string;
45
- completedAt?: string;
46
- } | null>;
59
+ }): Promise<void>;
60
+ /**
61
+ * Get any job by jobId (e.g. to poll child job status when await: true).
62
+ * @returns Job record or null if not found
63
+ */
64
+ getJob?(jobId: string): Promise<JobRecord | null>;
47
65
  }
66
+ /** Max SQS delay in seconds (AWS limit). */
67
+ declare const SQS_MAX_DELAY_SECONDS = 900;
68
+ /** Options for ctx.dispatchWorker (worker-to-worker). */
69
+ interface DispatchWorkerOptions {
70
+ webhookUrl?: string;
71
+ metadata?: Record<string, any>;
72
+ /** Optional job ID for the child job (default: generated). */
73
+ jobId?: string;
74
+ /** If true, poll job store until child completes or fails; otherwise fire-and-forget. */
75
+ await?: boolean;
76
+ pollIntervalMs?: number;
77
+ pollTimeoutMs?: number;
78
+ /**
79
+ * Delay before the child is invoked (fire-and-forget only; ignored when await is true).
80
+ * Uses SQS DelaySeconds (0–900). In local mode, waits this many seconds before sending the trigger request.
81
+ */
82
+ delaySeconds?: number;
83
+ }
84
+ /**
85
+ * Logger provided on ctx with prefixed levels: [INFO], [WARN], [ERROR], [DEBUG].
86
+ * Each method accepts a message and optional data (logged as JSON).
87
+ */
88
+ interface WorkerLogger {
89
+ info(message: string, data?: Record<string, unknown>): void;
90
+ warn(message: string, data?: Record<string, unknown>): void;
91
+ error(message: string, data?: Record<string, unknown>): void;
92
+ debug(message: string, data?: Record<string, unknown>): void;
93
+ }
94
+ declare function createWorkerLogger(jobId: string, workerId: string): WorkerLogger;
48
95
  interface WorkerHandlerParams<INPUT, OUTPUT> {
49
96
  input: INPUT;
50
97
  ctx: {
@@ -56,10 +103,62 @@ interface WorkerHandlerParams<INPUT, OUTPUT> {
56
103
  * Uses MongoDB directly when configured; never HTTP/origin URL.
57
104
  */
58
105
  jobStore?: JobStore;
106
+ /**
107
+ * Logger with prefixed levels: ctx.logger.info(), .warn(), .error(), .debug().
108
+ */
109
+ logger: WorkerLogger;
110
+ /**
111
+ * Dispatch another worker (fire-and-forget or await). Uses WORKER_QUEUE_URL_<SANITIZED_ID> env.
112
+ * Always provided by the runtime (Lambda and local).
113
+ */
114
+ dispatchWorker: (workerId: string, input: unknown, options?: DispatchWorkerOptions) => Promise<{
115
+ jobId: string;
116
+ messageId?: string;
117
+ output?: unknown;
118
+ }>;
59
119
  [key: string]: any;
60
120
  };
61
121
  }
62
122
  type WorkerHandler<INPUT, OUTPUT> = (params: WorkerHandlerParams<INPUT, OUTPUT>) => Promise<OUTPUT>;
123
+ /** Result of getNextStep for queue chaining. */
124
+ interface QueueNextStep {
125
+ workerId: string;
126
+ delaySeconds?: number;
127
+ mapInputFromPrev?: string;
128
+ }
129
+ /** One previous step's output (for mapInputFromPrev context). */
130
+ interface QueueStepOutput {
131
+ stepIndex: number;
132
+ workerId: string;
133
+ output: unknown;
134
+ }
135
+ /** Runtime helpers for queue-aware wrappers (provided by generated registry). */
136
+ interface QueueRuntime {
137
+ getNextStep(queueId: string, stepIndex: number): QueueNextStep | undefined;
138
+ /** Optional: when provided, mapping can use outputs from any previous step. */
139
+ getQueueJob?(queueJobId: string): Promise<{
140
+ steps: Array<{
141
+ workerId: string;
142
+ output?: unknown;
143
+ }>;
144
+ } | null>;
145
+ /** (initialInput, previousOutputs) – previousOutputs includes outputs for steps 0..stepIndex-1 and current step. */
146
+ invokeMapInput?(queueId: string, stepIndex: number, initialInput: unknown, previousOutputs: QueueStepOutput[]): Promise<unknown> | unknown;
147
+ }
148
+ /**
149
+ * Wraps a user handler so that when the job has __workerQueue context (from
150
+ * dispatchQueue or queue cron), it dispatches the next worker in the sequence
151
+ * after the handler completes. Uses literal worker IDs so the CLI env injection
152
+ * picks up WORKER_QUEUE_URL_* for next-step workers.
153
+ */
154
+ declare function wrapHandlerForQueue<INPUT, OUTPUT>(handler: WorkerHandler<INPUT, OUTPUT>, queueRuntime: QueueRuntime): WorkerHandler<INPUT & {
155
+ __workerQueue?: {
156
+ id: string;
157
+ stepIndex: number;
158
+ initialInput: unknown;
159
+ queueJobId?: string;
160
+ };
161
+ }, OUTPUT>;
63
162
  interface SQSMessageBody {
64
163
  workerId: string;
65
164
  jobId: string;
@@ -93,4 +192,4 @@ interface WebhookPayload {
93
192
  */
94
193
  declare function createLambdaHandler<INPUT, OUTPUT>(handler: WorkerHandler<INPUT, OUTPUT>, outputSchema?: ZodType<OUTPUT>): (event: SQSEvent, context: Context) => Promise<void>;
95
194
 
96
- export { type JobStore, type JobStoreUpdate, type SQSMessageBody, type WebhookPayload, type WorkerHandler, type WorkerHandlerParams, createLambdaHandler };
195
+ export { type DispatchWorkerOptions, type JobRecord, type JobStore, type JobStoreUpdate, type QueueNextStep, type QueueRuntime, type QueueStepOutput, type SQSMessageBody, SQS_MAX_DELAY_SECONDS, type WebhookPayload, type WorkerHandler, type WorkerHandlerParams, type WorkerLogger, createLambdaHandler, createWorkerLogger, wrapHandlerForQueue };
package/dist/handler.d.ts CHANGED
@@ -19,6 +19,25 @@ interface JobStoreUpdate {
19
19
  name?: string;
20
20
  };
21
21
  }
22
+ interface JobRecord {
23
+ jobId: string;
24
+ workerId: string;
25
+ status: 'queued' | 'running' | 'completed' | 'failed';
26
+ input: any;
27
+ output?: any;
28
+ error?: {
29
+ message: string;
30
+ stack?: string;
31
+ };
32
+ metadata?: Record<string, any>;
33
+ internalJobs?: Array<{
34
+ jobId: string;
35
+ workerId: string;
36
+ }>;
37
+ createdAt: string;
38
+ updatedAt: string;
39
+ completedAt?: string;
40
+ }
22
41
  interface JobStore {
23
42
  /**
24
43
  * Update job in job store.
@@ -29,22 +48,50 @@ interface JobStore {
29
48
  * Get current job record from job store.
30
49
  * @returns Job record or null if not found
31
50
  */
32
- get(): Promise<{
51
+ get(): Promise<JobRecord | null>;
52
+ /**
53
+ * Append an internal (child) job to the current job's internalJobs list.
54
+ * Used when this worker dispatches another worker (fire-and-forget or await).
55
+ */
56
+ appendInternalJob?(entry: {
33
57
  jobId: string;
34
58
  workerId: string;
35
- status: 'queued' | 'running' | 'completed' | 'failed';
36
- input: any;
37
- output?: any;
38
- error?: {
39
- message: string;
40
- stack?: string;
41
- };
42
- metadata?: Record<string, any>;
43
- createdAt: string;
44
- updatedAt: string;
45
- completedAt?: string;
46
- } | null>;
59
+ }): Promise<void>;
60
+ /**
61
+ * Get any job by jobId (e.g. to poll child job status when await: true).
62
+ * @returns Job record or null if not found
63
+ */
64
+ getJob?(jobId: string): Promise<JobRecord | null>;
47
65
  }
66
+ /** Max SQS delay in seconds (AWS limit). */
67
+ declare const SQS_MAX_DELAY_SECONDS = 900;
68
+ /** Options for ctx.dispatchWorker (worker-to-worker). */
69
+ interface DispatchWorkerOptions {
70
+ webhookUrl?: string;
71
+ metadata?: Record<string, any>;
72
+ /** Optional job ID for the child job (default: generated). */
73
+ jobId?: string;
74
+ /** If true, poll job store until child completes or fails; otherwise fire-and-forget. */
75
+ await?: boolean;
76
+ pollIntervalMs?: number;
77
+ pollTimeoutMs?: number;
78
+ /**
79
+ * Delay before the child is invoked (fire-and-forget only; ignored when await is true).
80
+ * Uses SQS DelaySeconds (0–900). In local mode, waits this many seconds before sending the trigger request.
81
+ */
82
+ delaySeconds?: number;
83
+ }
84
+ /**
85
+ * Logger provided on ctx with prefixed levels: [INFO], [WARN], [ERROR], [DEBUG].
86
+ * Each method accepts a message and optional data (logged as JSON).
87
+ */
88
+ interface WorkerLogger {
89
+ info(message: string, data?: Record<string, unknown>): void;
90
+ warn(message: string, data?: Record<string, unknown>): void;
91
+ error(message: string, data?: Record<string, unknown>): void;
92
+ debug(message: string, data?: Record<string, unknown>): void;
93
+ }
94
+ declare function createWorkerLogger(jobId: string, workerId: string): WorkerLogger;
48
95
  interface WorkerHandlerParams<INPUT, OUTPUT> {
49
96
  input: INPUT;
50
97
  ctx: {
@@ -56,10 +103,62 @@ interface WorkerHandlerParams<INPUT, OUTPUT> {
56
103
  * Uses MongoDB directly when configured; never HTTP/origin URL.
57
104
  */
58
105
  jobStore?: JobStore;
106
+ /**
107
+ * Logger with prefixed levels: ctx.logger.info(), .warn(), .error(), .debug().
108
+ */
109
+ logger: WorkerLogger;
110
+ /**
111
+ * Dispatch another worker (fire-and-forget or await). Uses WORKER_QUEUE_URL_<SANITIZED_ID> env.
112
+ * Always provided by the runtime (Lambda and local).
113
+ */
114
+ dispatchWorker: (workerId: string, input: unknown, options?: DispatchWorkerOptions) => Promise<{
115
+ jobId: string;
116
+ messageId?: string;
117
+ output?: unknown;
118
+ }>;
59
119
  [key: string]: any;
60
120
  };
61
121
  }
62
122
  type WorkerHandler<INPUT, OUTPUT> = (params: WorkerHandlerParams<INPUT, OUTPUT>) => Promise<OUTPUT>;
123
+ /** Result of getNextStep for queue chaining. */
124
+ interface QueueNextStep {
125
+ workerId: string;
126
+ delaySeconds?: number;
127
+ mapInputFromPrev?: string;
128
+ }
129
+ /** One previous step's output (for mapInputFromPrev context). */
130
+ interface QueueStepOutput {
131
+ stepIndex: number;
132
+ workerId: string;
133
+ output: unknown;
134
+ }
135
+ /** Runtime helpers for queue-aware wrappers (provided by generated registry). */
136
+ interface QueueRuntime {
137
+ getNextStep(queueId: string, stepIndex: number): QueueNextStep | undefined;
138
+ /** Optional: when provided, mapping can use outputs from any previous step. */
139
+ getQueueJob?(queueJobId: string): Promise<{
140
+ steps: Array<{
141
+ workerId: string;
142
+ output?: unknown;
143
+ }>;
144
+ } | null>;
145
+ /** (initialInput, previousOutputs) – previousOutputs includes outputs for steps 0..stepIndex-1 and current step. */
146
+ invokeMapInput?(queueId: string, stepIndex: number, initialInput: unknown, previousOutputs: QueueStepOutput[]): Promise<unknown> | unknown;
147
+ }
148
+ /**
149
+ * Wraps a user handler so that when the job has __workerQueue context (from
150
+ * dispatchQueue or queue cron), it dispatches the next worker in the sequence
151
+ * after the handler completes. Uses literal worker IDs so the CLI env injection
152
+ * picks up WORKER_QUEUE_URL_* for next-step workers.
153
+ */
154
+ declare function wrapHandlerForQueue<INPUT, OUTPUT>(handler: WorkerHandler<INPUT, OUTPUT>, queueRuntime: QueueRuntime): WorkerHandler<INPUT & {
155
+ __workerQueue?: {
156
+ id: string;
157
+ stepIndex: number;
158
+ initialInput: unknown;
159
+ queueJobId?: string;
160
+ };
161
+ }, OUTPUT>;
63
162
  interface SQSMessageBody {
64
163
  workerId: string;
65
164
  jobId: string;
@@ -93,4 +192,4 @@ interface WebhookPayload {
93
192
  */
94
193
  declare function createLambdaHandler<INPUT, OUTPUT>(handler: WorkerHandler<INPUT, OUTPUT>, outputSchema?: ZodType<OUTPUT>): (event: SQSEvent, context: Context) => Promise<void>;
95
194
 
96
- export { type JobStore, type JobStoreUpdate, type SQSMessageBody, type WebhookPayload, type WorkerHandler, type WorkerHandlerParams, createLambdaHandler };
195
+ export { type DispatchWorkerOptions, type JobRecord, type JobStore, type JobStoreUpdate, type QueueNextStep, type QueueRuntime, type QueueStepOutput, type SQSMessageBody, SQS_MAX_DELAY_SECONDS, type WebhookPayload, type WorkerHandler, type WorkerHandlerParams, type WorkerLogger, createLambdaHandler, createWorkerLogger, wrapHandlerForQueue };