@microfox/ai-worker 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,167 @@
1
+ import { ZodType, z } from 'zod';
2
+
3
+ /**
4
+ * Queue definition and context types for worker queues.
5
+ *
6
+ * These types are used at code-time by .queue.ts files and at runtime
7
+ * by the client and generated registry/queue wrappers.
8
+ */
9
+ interface WorkerQueueStep {
10
+ /** Worker ID for this step. Must match an existing worker id. */
11
+ workerId: string;
12
+ /**
13
+ * Optional delay (in seconds) before this step is executed.
14
+ * Implemented via SQS DelaySeconds (0–900).
15
+ */
16
+ delaySeconds?: number;
17
+ /**
18
+ * Optional name of a mapping function exported from the .queue.ts file
19
+ * that derives this step's input from the previous step's output and
20
+ * the original initial input.
21
+ */
22
+ mapInputFromPrev?: string;
23
+ }
24
+ interface WorkerQueueConfig<InitialInput = any, StepOutput = any> {
25
+ /** Stable queue identifier, e.g. "cost-usage". */
26
+ id: string;
27
+ /** Ordered list of workers forming the queue. */
28
+ steps: WorkerQueueStep[];
29
+ /**
30
+ * Optional schedule for the queue (cron or rate).
31
+ * When set, the CLI generates a queue-starter Lambda triggered by this schedule.
32
+ * Example: 'cron(0 3 * * ? *)' for daily at 03:00 UTC.
33
+ */
34
+ schedule?: string | {
35
+ rate: string;
36
+ enabled?: boolean;
37
+ input?: Record<string, any>;
38
+ };
39
+ _initialInputType?: InitialInput;
40
+ _stepOutputType?: StepOutput;
41
+ }
42
+ /**
43
+ * Queue execution context that is embedded into job input/metadata so
44
+ * queue-aware wrappers can determine where they are in the queue.
45
+ */
46
+ interface WorkerQueueContext<InitialInput = any> {
47
+ id: string;
48
+ stepIndex: number;
49
+ initialInput: InitialInput;
50
+ /** Queue job ID (same as first worker's jobId) for tracking progress. */
51
+ queueJobId?: string;
52
+ }
53
+ /**
54
+ * Identity helper for defining worker queues in .queue.ts files.
55
+ * This is primarily for type safety and CLI discovery.
56
+ */
57
+ declare function defineWorkerQueue<T extends WorkerQueueConfig>(config: T): T;
58
+
59
+ /**
60
+ * Client for dispatching background worker jobs.
61
+ *
62
+ * In production, dispatching happens via the workers HTTP API:
63
+ * POST /workers/trigger -> enqueues message to SQS on the workers service side
64
+ *
65
+ * This avoids requiring AWS credentials in your Next.js app.
66
+ */
67
+
68
+ interface WorkerQueueRegistry {
69
+ getQueueById(queueId: string): WorkerQueueConfig | undefined;
70
+ invokeMapInput?: (queueId: string, stepIndex: number, prevOutput: unknown, initialInput: unknown) => Promise<unknown> | unknown;
71
+ }
72
+ interface DispatchOptions {
73
+ /**
74
+ * Optional webhook callback URL to notify when the job finishes.
75
+ * Only called when provided. Default: no webhook (use job store / MongoDB only).
76
+ */
77
+ webhookUrl?: string;
78
+ /**
79
+ * Controls how dispatch executes.
80
+ * - "auto" (default): local inline execution in development unless WORKERS_LOCAL_MODE=false.
81
+ * - "local": force inline execution (no SQS).
82
+ * - "remote": force SQS/Lambda dispatch even in development.
83
+ */
84
+ mode?: 'auto' | 'local' | 'remote';
85
+ jobId?: string;
86
+ metadata?: Record<string, any>;
87
+ /**
88
+ * In-memory queue registry for dispatchQueue. Required when using dispatchQueue.
89
+ * Pass a registry that imports from your .queue.ts definitions (works on Vercel/serverless).
90
+ */
91
+ registry?: WorkerQueueRegistry;
92
+ /**
93
+ * Optional callback to create a queue job record before dispatching.
94
+ * Called with queueJobId (= first worker's jobId), queueId, and firstStep.
95
+ */
96
+ onCreateQueueJob?: (params: {
97
+ queueJobId: string;
98
+ queueId: string;
99
+ firstStep: {
100
+ workerId: string;
101
+ workerJobId: string;
102
+ };
103
+ metadata?: Record<string, unknown>;
104
+ }) => Promise<void>;
105
+ }
106
+ interface DispatchResult {
107
+ messageId: string;
108
+ status: 'queued';
109
+ jobId: string;
110
+ }
111
+ interface DispatchQueueResult extends DispatchResult {
112
+ queueId: string;
113
+ }
114
+ interface SerializedContext {
115
+ requestId?: string;
116
+ userId?: string;
117
+ traceId?: string;
118
+ [key: string]: any;
119
+ }
120
+ /**
121
+ * Derives the full /workers/trigger URL from env.
122
+ * Exported for use by local dispatchWorker (worker-to-worker in dev).
123
+ *
124
+ * Preferred env vars:
125
+ * - WORKER_BASE_URL: base URL of the workers service (e.g. https://.../prod)
126
+ * - NEXT_PUBLIC_WORKER_BASE_URL: same, but exposed to the browser
127
+ *
128
+ * Legacy env vars (still supported for backwards compatibility):
129
+ * - WORKERS_TRIGGER_API_URL / NEXT_PUBLIC_WORKERS_TRIGGER_API_URL
130
+ * - WORKERS_CONFIG_API_URL / NEXT_PUBLIC_WORKERS_CONFIG_API_URL
131
+ */
132
+ declare function getWorkersTriggerUrl(): string;
133
+ /**
134
+ * Dispatches a background worker job to SQS.
135
+ *
136
+ * @param workerId - The ID of the worker to dispatch
137
+ * @param input - The input data for the worker (will be validated against inputSchema)
138
+ * @param inputSchema - Zod schema for input validation
139
+ * @param options - Dispatch options including webhook URL
140
+ * @param ctx - Optional context object (only serializable parts will be sent)
141
+ * @returns Promise resolving to dispatch result with messageId and jobId
142
+ */
143
+ declare function dispatch<INPUT_SCHEMA extends ZodType<any>>(workerId: string, input: z.input<INPUT_SCHEMA>, inputSchema: INPUT_SCHEMA, options: DispatchOptions, ctx?: any): Promise<DispatchResult>;
144
+ /**
145
+ * Local development mode: runs the handler immediately in the same process.
146
+ * This bypasses SQS and Lambda for faster iteration during development.
147
+ *
148
+ * @param handler - The worker handler function
149
+ * @param input - The input data
150
+ * @param ctx - The context object
151
+ * @returns The handler result
152
+ */
153
+ declare function dispatchLocal<INPUT, OUTPUT>(handler: (params: {
154
+ input: INPUT;
155
+ ctx: any;
156
+ }) => Promise<OUTPUT>, input: INPUT, ctx?: any): Promise<OUTPUT>;
157
+ /**
158
+ * Dispatches a queue by ID, using a generated registry of .queue.ts
159
+ * definitions to determine the first worker and initial input mapping.
160
+ *
161
+ * This API intentionally mirrors the ergonomics of dispatching a single
162
+ * worker, but under the hood it embeds queue context into the job input
163
+ * so queue-aware wrappers can chain subsequent steps.
164
+ */
165
+ declare function dispatchQueue<InitialInput = any>(queueId: string, initialInput: InitialInput, options?: DispatchOptions, ctx?: any): Promise<DispatchQueueResult>;
166
+
167
+ export { type DispatchOptions as D, type SerializedContext as S, type WorkerQueueRegistry as W, type DispatchResult as a, type DispatchQueueResult as b, dispatchLocal as c, dispatch as d, dispatchQueue as e, type WorkerQueueStep as f, getWorkersTriggerUrl as g, type WorkerQueueConfig as h, type WorkerQueueContext as i, defineWorkerQueue as j };
package/dist/client.d.mts CHANGED
@@ -1,64 +1,2 @@
1
- import { ZodType, z } from 'zod';
2
-
3
- /**
4
- * Client for dispatching background worker jobs.
5
- *
6
- * In production, dispatching happens via the workers HTTP API:
7
- * POST /workers/trigger -> enqueues message to SQS on the workers service side
8
- *
9
- * This avoids requiring AWS credentials in your Next.js app.
10
- */
11
-
12
- interface DispatchOptions {
13
- /**
14
- * Optional webhook callback URL to notify when the job finishes.
15
- * Only called when provided. Default: no webhook (use job store / MongoDB only).
16
- */
17
- webhookUrl?: string;
18
- /**
19
- * Controls how dispatch executes.
20
- * - "auto" (default): local inline execution in development unless WORKERS_LOCAL_MODE=false.
21
- * - "local": force inline execution (no SQS).
22
- * - "remote": force SQS/Lambda dispatch even in development.
23
- */
24
- mode?: 'auto' | 'local' | 'remote';
25
- jobId?: string;
26
- metadata?: Record<string, any>;
27
- }
28
- interface DispatchResult {
29
- messageId: string;
30
- status: 'queued';
31
- jobId: string;
32
- }
33
- interface SerializedContext {
34
- requestId?: string;
35
- userId?: string;
36
- traceId?: string;
37
- [key: string]: any;
38
- }
39
- /**
40
- * Dispatches a background worker job to SQS.
41
- *
42
- * @param workerId - The ID of the worker to dispatch
43
- * @param input - The input data for the worker (will be validated against inputSchema)
44
- * @param inputSchema - Zod schema for input validation
45
- * @param options - Dispatch options including webhook URL
46
- * @param ctx - Optional context object (only serializable parts will be sent)
47
- * @returns Promise resolving to dispatch result with messageId and jobId
48
- */
49
- declare function dispatch<INPUT_SCHEMA extends ZodType<any>>(workerId: string, input: z.input<INPUT_SCHEMA>, inputSchema: INPUT_SCHEMA, options: DispatchOptions, ctx?: any): Promise<DispatchResult>;
50
- /**
51
- * Local development mode: runs the handler immediately in the same process.
52
- * This bypasses SQS and Lambda for faster iteration during development.
53
- *
54
- * @param handler - The worker handler function
55
- * @param input - The input data
56
- * @param ctx - The context object
57
- * @returns The handler result
58
- */
59
- declare function dispatchLocal<INPUT, OUTPUT>(handler: (params: {
60
- input: INPUT;
61
- ctx: any;
62
- }) => Promise<OUTPUT>, input: INPUT, ctx?: any): Promise<OUTPUT>;
63
-
64
- export { type DispatchOptions, type DispatchResult, type SerializedContext, dispatch, dispatchLocal };
1
+ import 'zod';
2
+ export { D as DispatchOptions, b as DispatchQueueResult, a as DispatchResult, S as SerializedContext, W as WorkerQueueRegistry, d as dispatch, c as dispatchLocal, e as dispatchQueue, g as getWorkersTriggerUrl } from './client-D25XR0V8.mjs';
package/dist/client.d.ts CHANGED
@@ -1,64 +1,2 @@
1
- import { ZodType, z } from 'zod';
2
-
3
- /**
4
- * Client for dispatching background worker jobs.
5
- *
6
- * In production, dispatching happens via the workers HTTP API:
7
- * POST /workers/trigger -> enqueues message to SQS on the workers service side
8
- *
9
- * This avoids requiring AWS credentials in your Next.js app.
10
- */
11
-
12
- interface DispatchOptions {
13
- /**
14
- * Optional webhook callback URL to notify when the job finishes.
15
- * Only called when provided. Default: no webhook (use job store / MongoDB only).
16
- */
17
- webhookUrl?: string;
18
- /**
19
- * Controls how dispatch executes.
20
- * - "auto" (default): local inline execution in development unless WORKERS_LOCAL_MODE=false.
21
- * - "local": force inline execution (no SQS).
22
- * - "remote": force SQS/Lambda dispatch even in development.
23
- */
24
- mode?: 'auto' | 'local' | 'remote';
25
- jobId?: string;
26
- metadata?: Record<string, any>;
27
- }
28
- interface DispatchResult {
29
- messageId: string;
30
- status: 'queued';
31
- jobId: string;
32
- }
33
- interface SerializedContext {
34
- requestId?: string;
35
- userId?: string;
36
- traceId?: string;
37
- [key: string]: any;
38
- }
39
- /**
40
- * Dispatches a background worker job to SQS.
41
- *
42
- * @param workerId - The ID of the worker to dispatch
43
- * @param input - The input data for the worker (will be validated against inputSchema)
44
- * @param inputSchema - Zod schema for input validation
45
- * @param options - Dispatch options including webhook URL
46
- * @param ctx - Optional context object (only serializable parts will be sent)
47
- * @returns Promise resolving to dispatch result with messageId and jobId
48
- */
49
- declare function dispatch<INPUT_SCHEMA extends ZodType<any>>(workerId: string, input: z.input<INPUT_SCHEMA>, inputSchema: INPUT_SCHEMA, options: DispatchOptions, ctx?: any): Promise<DispatchResult>;
50
- /**
51
- * Local development mode: runs the handler immediately in the same process.
52
- * This bypasses SQS and Lambda for faster iteration during development.
53
- *
54
- * @param handler - The worker handler function
55
- * @param input - The input data
56
- * @param ctx - The context object
57
- * @returns The handler result
58
- */
59
- declare function dispatchLocal<INPUT, OUTPUT>(handler: (params: {
60
- input: INPUT;
61
- ctx: any;
62
- }) => Promise<OUTPUT>, input: INPUT, ctx?: any): Promise<OUTPUT>;
63
-
64
- export { type DispatchOptions, type DispatchResult, type SerializedContext, dispatch, dispatchLocal };
1
+ import 'zod';
2
+ export { D as DispatchOptions, b as DispatchQueueResult, a as DispatchResult, S as SerializedContext, W as WorkerQueueRegistry, d as dispatch, c as dispatchLocal, e as dispatchQueue, g as getWorkersTriggerUrl } from './client-D25XR0V8.js';
package/dist/client.js CHANGED
@@ -21,7 +21,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var client_exports = {};
22
22
  __export(client_exports, {
23
23
  dispatch: () => dispatch,
24
- dispatchLocal: () => dispatchLocal
24
+ dispatchLocal: () => dispatchLocal,
25
+ dispatchQueue: () => dispatchQueue,
26
+ getWorkersTriggerUrl: () => getWorkersTriggerUrl
25
27
  });
26
28
  module.exports = __toCommonJS(client_exports);
27
29
  function getWorkersTriggerUrl() {
@@ -100,9 +102,112 @@ async function dispatch(workerId, input, inputSchema, options, ctx) {
100
102
  async function dispatchLocal(handler, input, ctx) {
101
103
  return handler({ input, ctx: ctx || {} });
102
104
  }
105
+ async function dispatchQueue(queueId, initialInput, options = {}, ctx) {
106
+ const registry = options.registry;
107
+ if (!registry?.getQueueById) {
108
+ throw new Error(
109
+ "dispatchQueue requires options.registry with getQueueById. Use getQueueRegistry() from your workflows registry (e.g. app/api/workflows/registry/workers) and pass { registry: await getQueueRegistry() }."
110
+ );
111
+ }
112
+ const { getQueueById, invokeMapInput } = registry;
113
+ const queue = getQueueById(queueId);
114
+ if (!queue) {
115
+ throw new Error(`Worker queue "${queueId}" not found in registry`);
116
+ }
117
+ if (!queue.steps || queue.steps.length === 0) {
118
+ throw new Error(`Worker queue "${queueId}" has no steps defined`);
119
+ }
120
+ const stepIndex = 0;
121
+ const firstStep = queue.steps[stepIndex];
122
+ const firstWorkerId = firstStep.workerId;
123
+ if (!firstWorkerId) {
124
+ throw new Error(
125
+ `Worker queue "${queueId}" has an invalid first step (missing workerId)`
126
+ );
127
+ }
128
+ let firstInput = initialInput;
129
+ if (firstStep.mapInputFromPrev && typeof invokeMapInput === "function") {
130
+ firstInput = await invokeMapInput(
131
+ queueId,
132
+ stepIndex,
133
+ void 0,
134
+ initialInput
135
+ );
136
+ }
137
+ const jobId = options.jobId || `job-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
138
+ const queueContext = {
139
+ id: queueId,
140
+ stepIndex,
141
+ initialInput,
142
+ queueJobId: jobId
143
+ };
144
+ if (options.onCreateQueueJob) {
145
+ try {
146
+ await options.onCreateQueueJob({
147
+ queueJobId: jobId,
148
+ queueId,
149
+ firstStep: { workerId: firstWorkerId, workerJobId: jobId },
150
+ metadata: options.metadata
151
+ });
152
+ } catch (err) {
153
+ console.warn("[dispatchQueue] onCreateQueueJob failed:", err?.message ?? err);
154
+ }
155
+ }
156
+ const normalizedFirstInput = firstInput !== null && typeof firstInput === "object" ? firstInput : { value: firstInput };
157
+ const inputWithQueue = {
158
+ ...normalizedFirstInput,
159
+ __workerQueue: queueContext
160
+ };
161
+ const metadataWithQueue = {
162
+ ...options.metadata || {},
163
+ __workerQueue: queueContext
164
+ };
165
+ const triggerUrl = getWorkersTriggerUrl();
166
+ const serializedContext = ctx ? serializeContext(ctx) : {};
167
+ const messageBody = {
168
+ workerId: firstWorkerId,
169
+ jobId,
170
+ input: inputWithQueue,
171
+ context: serializedContext,
172
+ webhookUrl: options.webhookUrl,
173
+ metadata: metadataWithQueue,
174
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
175
+ };
176
+ const headers = {
177
+ "Content-Type": "application/json"
178
+ };
179
+ const triggerKey = process.env.WORKERS_TRIGGER_API_KEY;
180
+ if (triggerKey) {
181
+ headers["x-workers-trigger-key"] = triggerKey;
182
+ }
183
+ const response = await fetch(triggerUrl, {
184
+ method: "POST",
185
+ headers,
186
+ body: JSON.stringify({
187
+ workerId: firstWorkerId,
188
+ body: messageBody
189
+ })
190
+ });
191
+ if (!response.ok) {
192
+ const text = await response.text().catch(() => "");
193
+ throw new Error(
194
+ `Failed to trigger queue "${queueId}" (worker "${firstWorkerId}"): ${response.status} ${response.statusText}${text ? ` - ${text}` : ""}`
195
+ );
196
+ }
197
+ const data = await response.json().catch(() => ({}));
198
+ const messageId = data?.messageId ? String(data.messageId) : `trigger-${jobId}`;
199
+ return {
200
+ queueId,
201
+ messageId,
202
+ status: "queued",
203
+ jobId
204
+ };
205
+ }
103
206
  // Annotate the CommonJS export names for ESM import in node:
104
207
  0 && (module.exports = {
105
208
  dispatch,
106
- dispatchLocal
209
+ dispatchLocal,
210
+ dispatchQueue,
211
+ getWorkersTriggerUrl
107
212
  });
108
213
  //# sourceMappingURL=client.js.map
@@ -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, WorkerQueueContext } from './queue.js';\n\nexport interface WorkerQueueRegistry {\n getQueueById(queueId: string): WorkerQueueConfig | undefined;\n invokeMapInput?: (\n queueId: string,\n stepIndex: number,\n prevOutput: unknown,\n initialInput: 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 *\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 */\nexport function 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/**\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\n/**\n * Dispatches a queue by ID, using a generated registry of .queue.ts\n * definitions to determine the first worker and initial input mapping.\n *\n * This API intentionally mirrors the ergonomics of dispatching a single\n * worker, but under the hood it embeds queue context into the job input\n * so queue-aware wrappers can chain subsequent steps.\n */\nexport async function dispatchQueue<InitialInput = any>(\n queueId: string,\n initialInput: InitialInput,\n options: DispatchOptions = {},\n ctx?: any\n): Promise<DispatchQueueResult> {\n const registry = options.registry;\n if (!registry?.getQueueById) {\n throw new Error(\n 'dispatchQueue requires options.registry with getQueueById. ' +\n 'Use getQueueRegistry() from your workflows registry (e.g. app/api/workflows/registry/workers) and pass { registry: await getQueueRegistry() }.'\n );\n }\n const { getQueueById, invokeMapInput } = registry;\n const queue = getQueueById(queueId);\n\n if (!queue) {\n throw new Error(`Worker queue \"${queueId}\" not found in registry`);\n }\n\n if (!queue.steps || queue.steps.length === 0) {\n throw new Error(`Worker queue \"${queueId}\" has no steps defined`);\n }\n\n const stepIndex = 0;\n const firstStep = queue.steps[stepIndex];\n const firstWorkerId = firstStep.workerId;\n\n if (!firstWorkerId) {\n throw new Error(\n `Worker queue \"${queueId}\" has an invalid first step (missing workerId)`\n );\n }\n\n // Compute the first step's input:\n // - If a mapping function is configured and the registry exposes invokeMapInput,\n // use it (prevOutput is undefined for the first step).\n // - Otherwise, default to the initial input.\n let firstInput: unknown = initialInput;\n if (firstStep.mapInputFromPrev && typeof invokeMapInput === 'function') {\n firstInput = await invokeMapInput(\n queueId,\n stepIndex,\n undefined,\n initialInput\n );\n }\n\n const jobId =\n options.jobId ||\n `job-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n\n const queueContext: WorkerQueueContext<InitialInput> = {\n id: queueId,\n stepIndex,\n initialInput,\n queueJobId: jobId,\n };\n\n // Create queue job record if callback provided (for progress tracking)\n if (options.onCreateQueueJob) {\n try {\n await options.onCreateQueueJob({\n queueJobId: jobId,\n queueId,\n firstStep: { workerId: firstWorkerId, workerJobId: jobId },\n metadata: options.metadata as Record<string, unknown> | undefined,\n });\n } catch (err: any) {\n console.warn('[dispatchQueue] onCreateQueueJob failed:', err?.message ?? err);\n }\n }\n\n // Embed queue context into the worker input under a reserved key.\n const normalizedFirstInput =\n firstInput !== null && typeof firstInput === 'object'\n ? (firstInput as Record<string, any>)\n : { value: firstInput };\n\n const inputWithQueue = {\n ...normalizedFirstInput,\n __workerQueue: queueContext,\n };\n\n const metadataWithQueue = {\n ...(options.metadata || {}),\n __workerQueue: queueContext,\n };\n\n const triggerUrl = getWorkersTriggerUrl();\n const serializedContext = ctx ? serializeContext(ctx) : {};\n\n const messageBody = {\n workerId: firstWorkerId,\n jobId,\n input: inputWithQueue,\n context: serializedContext,\n webhookUrl: options.webhookUrl,\n metadata: metadataWithQueue,\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: firstWorkerId,\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 queue \"${queueId}\" (worker \"${firstWorkerId}\"): ` +\n `${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 queueId,\n messageId,\n status: 'queued',\n jobId,\n };\n}\n\n"],"mappings":"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","names":[]}
package/dist/client.mjs CHANGED
@@ -1,10 +1,14 @@
1
1
  import {
2
2
  dispatch,
3
- dispatchLocal
4
- } from "./chunk-FQCZSXDI.mjs";
3
+ dispatchLocal,
4
+ dispatchQueue,
5
+ getWorkersTriggerUrl
6
+ } from "./chunk-BJPQY2NJ.mjs";
5
7
  import "./chunk-BJTO5JO5.mjs";
6
8
  export {
7
9
  dispatch,
8
- dispatchLocal
10
+ dispatchLocal,
11
+ dispatchQueue,
12
+ getWorkersTriggerUrl
9
13
  };
10
14
  //# 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,21 +48,38 @@ 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>;
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;
47
83
  }
48
84
  interface WorkerHandlerParams<INPUT, OUTPUT> {
49
85
  input: INPUT;
@@ -56,10 +92,43 @@ interface WorkerHandlerParams<INPUT, OUTPUT> {
56
92
  * Uses MongoDB directly when configured; never HTTP/origin URL.
57
93
  */
58
94
  jobStore?: JobStore;
95
+ /**
96
+ * Dispatch another worker (fire-and-forget or await). Uses WORKER_QUEUE_URL_<SANITIZED_ID> env.
97
+ * Always provided by the runtime (Lambda and local).
98
+ */
99
+ dispatchWorker: (workerId: string, input: unknown, options?: DispatchWorkerOptions) => Promise<{
100
+ jobId: string;
101
+ messageId?: string;
102
+ output?: unknown;
103
+ }>;
59
104
  [key: string]: any;
60
105
  };
61
106
  }
62
107
  type WorkerHandler<INPUT, OUTPUT> = (params: WorkerHandlerParams<INPUT, OUTPUT>) => Promise<OUTPUT>;
108
+ /** Result of getNextStep for queue chaining. */
109
+ interface QueueNextStep {
110
+ workerId: string;
111
+ delaySeconds?: number;
112
+ mapInputFromPrev?: string;
113
+ }
114
+ /** Runtime helpers for queue-aware wrappers (provided by generated registry). */
115
+ interface QueueRuntime {
116
+ getNextStep(queueId: string, stepIndex: number): QueueNextStep | undefined;
117
+ invokeMapInput?(queueId: string, stepIndex: number, prevOutput: unknown, initialInput: unknown): Promise<unknown> | unknown;
118
+ }
119
+ /**
120
+ * Wraps a user handler so that when the job has __workerQueue context (from
121
+ * dispatchQueue or queue cron), it dispatches the next worker in the sequence
122
+ * after the handler completes. Uses literal worker IDs so the CLI env injection
123
+ * picks up WORKER_QUEUE_URL_* for next-step workers.
124
+ */
125
+ declare function wrapHandlerForQueue<INPUT, OUTPUT>(handler: WorkerHandler<INPUT, OUTPUT>, queueRuntime: QueueRuntime): WorkerHandler<INPUT & {
126
+ __workerQueue?: {
127
+ id: string;
128
+ stepIndex: number;
129
+ initialInput: unknown;
130
+ };
131
+ }, OUTPUT>;
63
132
  interface SQSMessageBody {
64
133
  workerId: string;
65
134
  jobId: string;
@@ -93,4 +162,4 @@ interface WebhookPayload {
93
162
  */
94
163
  declare function createLambdaHandler<INPUT, OUTPUT>(handler: WorkerHandler<INPUT, OUTPUT>, outputSchema?: ZodType<OUTPUT>): (event: SQSEvent, context: Context) => Promise<void>;
95
164
 
96
- export { type JobStore, type JobStoreUpdate, type SQSMessageBody, type WebhookPayload, type WorkerHandler, type WorkerHandlerParams, createLambdaHandler };
165
+ export { type DispatchWorkerOptions, type JobRecord, type JobStore, type JobStoreUpdate, type QueueNextStep, type QueueRuntime, type SQSMessageBody, SQS_MAX_DELAY_SECONDS, type WebhookPayload, type WorkerHandler, type WorkerHandlerParams, createLambdaHandler, wrapHandlerForQueue };