@camunda8/orchestration-cluster-api 10.0.0-alpha.44 → 10.0.0-alpha.45

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.
@@ -43,8 +43,84 @@ function toModuleSpecifier(handlerModule) {
43
43
  return isPath ? (0, import_node_url.pathToFileURL)((0, import_node_path.resolve)(handlerModule)).href : handlerModule;
44
44
  }
45
45
 
46
- // src/runtime/threadWorkerEntry.ts
46
+ // src/runtime/threadJobProxy.ts
47
47
  var JobActionReceipt = "JOB_ACTION_RECEIPT";
48
+ function createJobProxy(jobData, client) {
49
+ const acknowledged = { value: false };
50
+ const ack = () => {
51
+ acknowledged.value = true;
52
+ job.acknowledged = true;
53
+ };
54
+ const job = { ...jobData };
55
+ job.complete = async (variables = {}, result) => {
56
+ ack();
57
+ job._completionAction = {
58
+ method: "completeJob",
59
+ args: [
60
+ {
61
+ variables,
62
+ jobKey: jobData.jobKey,
63
+ ...result !== void 0 && { result },
64
+ ...jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}
65
+ }
66
+ ]
67
+ };
68
+ return JobActionReceipt;
69
+ };
70
+ job.fail = async (reason) => {
71
+ ack();
72
+ job._completionAction = {
73
+ method: "failJob",
74
+ args: [
75
+ {
76
+ ...reason,
77
+ jobKey: jobData.jobKey,
78
+ ...jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}
79
+ }
80
+ ]
81
+ };
82
+ return JobActionReceipt;
83
+ };
84
+ job.error = async (error) => {
85
+ ack();
86
+ job._completionAction = {
87
+ method: "throwJobError",
88
+ args: [
89
+ {
90
+ ...error,
91
+ jobKey: jobData.jobKey,
92
+ ...jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}
93
+ }
94
+ ]
95
+ };
96
+ return JobActionReceipt;
97
+ };
98
+ job.cancelWorkflow = async () => {
99
+ ack();
100
+ job._completionAction = {
101
+ method: "cancelProcessInstance",
102
+ args: [{ processInstanceKey: jobData.processInstanceKey }]
103
+ };
104
+ return JobActionReceipt;
105
+ };
106
+ job.ignore = async () => {
107
+ ack();
108
+ return JobActionReceipt;
109
+ };
110
+ job.modifyJobTimeout = ({ newTimeoutMs }) => client.updateJob({
111
+ changeset: { timeout: newTimeoutMs },
112
+ jobKey: jobData.jobKey,
113
+ ...jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}
114
+ });
115
+ job.modifyRetries = ({ retries }) => client.updateJob({
116
+ changeset: { retries },
117
+ jobKey: jobData.jobKey,
118
+ ...jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}
119
+ });
120
+ return job;
121
+ }
122
+
123
+ // src/runtime/threadWorkerEntry.ts
48
124
  if (!import_node_worker_threads.parentPort) {
49
125
  throw new Error("threadWorkerEntry must run inside a worker_threads Worker");
50
126
  }
@@ -101,52 +177,5 @@ import_node_worker_threads.parentPort.on("message", async (msg) => {
101
177
  }
102
178
  }
103
179
  });
104
- function createJobProxy(jobData, client) {
105
- const acknowledged = { value: false };
106
- const ack = () => {
107
- acknowledged.value = true;
108
- job.acknowledged = true;
109
- };
110
- const job = { ...jobData };
111
- job.complete = async (variables = {}, result) => {
112
- ack();
113
- job._completionAction = {
114
- method: "completeJob",
115
- args: [{ variables, jobKey: jobData.jobKey, ...result !== void 0 && { result } }]
116
- };
117
- return JobActionReceipt;
118
- };
119
- job.fail = async (reason) => {
120
- ack();
121
- job._completionAction = {
122
- method: "failJob",
123
- args: [{ ...reason, jobKey: jobData.jobKey }]
124
- };
125
- return JobActionReceipt;
126
- };
127
- job.error = async (error) => {
128
- ack();
129
- job._completionAction = {
130
- method: "throwJobError",
131
- args: [{ ...error, jobKey: jobData.jobKey }]
132
- };
133
- return JobActionReceipt;
134
- };
135
- job.cancelWorkflow = async () => {
136
- ack();
137
- job._completionAction = {
138
- method: "cancelProcessInstance",
139
- args: [{ processInstanceKey: jobData.processInstanceKey }]
140
- };
141
- return JobActionReceipt;
142
- };
143
- job.ignore = async () => {
144
- ack();
145
- return JobActionReceipt;
146
- };
147
- job.modifyJobTimeout = ({ newTimeoutMs }) => client.updateJob({ changeset: { timeout: newTimeoutMs }, jobKey: jobData.jobKey });
148
- job.modifyRetries = ({ retries }) => client.updateJob({ changeset: { retries }, jobKey: jobData.jobKey });
149
- return job;
150
- }
151
180
  import_node_worker_threads.parentPort.postMessage({ type: "ready" });
152
181
  //# sourceMappingURL=threadWorkerEntry.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/runtime/threadWorkerEntry.ts","../src/runtime/clientProxy.ts","../src/runtime/moduleSpecifier.ts"],"sourcesContent":["/**\n * Worker thread entry point for the shared ThreadPool.\n *\n * Each thread in the pool runs this script. It:\n * 1. Waits for job messages on parentPort\n * 2. Dynamically imports and caches the handler module per handlerModule path\n * 3. Creates a client proxy + job proxy per job\n * 4. Calls the handler, sends back the result\n *\n * Threads are generic — the handler module is specified per-job, not per-thread.\n * Handlers are cached by module path so each import happens only once per thread.\n */\nimport { parentPort } from 'node:worker_threads';\nimport type { JobResult as ApiJobResult } from '../gen/types.gen';\nimport { createClientProxy } from './clientProxy.ts';\nimport { toModuleSpecifier } from './moduleSpecifier.ts';\n\n// Inline the JobActionReceipt constant to avoid importing the full SDK dependency chain\n// (jobWorker.ts → ../gen/CamundaClient → entire SDK) in the worker thread.\nconst JobActionReceipt = 'JOB_ACTION_RECEIPT' as const;\n\nif (!parentPort) {\n throw new Error('threadWorkerEntry must run inside a worker_threads Worker');\n}\n\ninterface JobMessage {\n type: 'job';\n /** Unique ID for this job dispatch (correlates response) */\n taskId: string;\n /** Serialized job data (plain object, no methods) */\n jobData: Record<string, unknown>;\n /** Handler module path — resolved per job, cached per thread */\n handlerModule: string;\n}\n\ninterface JobResult {\n type: 'job-result';\n taskId: string;\n ok: boolean;\n error?: string;\n /** When the handler acknowledged the job via complete/fail/error,\n * the action is captured here for the main thread to execute. */\n completionAction?: {\n method: string;\n args: unknown[];\n };\n}\n\n/** Cache of loaded handlers keyed by module path. Each thread loads a handler once per unique path. */\nconst handlerCache = new Map<string, (job: any, client: any) => Promise<any>>();\n\nasync function loadHandler(\n handlerModule: string\n): Promise<(job: any, client: any) => Promise<any>> {\n const cached = handlerCache.get(handlerModule);\n if (cached) return cached;\n\n const mod = await import(toModuleSpecifier(handlerModule));\n const handler = mod.default ?? mod.handler;\n if (typeof handler !== 'function') {\n throw new Error(\n `Threaded handler module '${handlerModule}' must export a default function or named 'handler' export`\n );\n }\n handlerCache.set(handlerModule, handler);\n return handler;\n}\n\nparentPort.on('message', async (msg: JobMessage & { clientPort?: any }) => {\n if (msg.type !== 'job') return;\n\n const { taskId, jobData, handlerModule, clientPort } = msg as JobMessage & {\n clientPort: import('node:worker_threads').MessagePort;\n };\n\n try {\n const handlerFn = await loadHandler(handlerModule);\n\n // Create a client proxy for this job's MessagePort\n const clientProxy = createClientProxy(clientPort);\n\n // Build a job-like object with proxied action methods\n const job = createJobProxy(jobData, clientProxy);\n\n await handlerFn(job, clientProxy);\n\n // If the handler never acknowledged the job (no complete/fail/error/ignore),\n // treat it as an error so the broker can retry rather than silently dropping it.\n if (!job.acknowledged) {\n const result: JobResult = {\n type: 'job-result',\n taskId,\n ok: false,\n error:\n `Handler for '${handlerModule}' returned without acknowledging the job. ` +\n 'Call job.complete(), job.fail(), job.error(), or job.ignore().',\n };\n parentPort!.postMessage(result);\n return;\n }\n\n const result: JobResult = {\n type: 'job-result',\n taskId,\n ok: true,\n completionAction: job._completionAction || undefined,\n };\n parentPort!.postMessage(result);\n } catch (err: any) {\n const result: JobResult = {\n type: 'job-result',\n taskId,\n ok: false,\n error: err?.message || String(err),\n };\n parentPort!.postMessage(result);\n } finally {\n // Close this job's client port\n if (clientPort && typeof clientPort.close === 'function') {\n clientPort.close();\n }\n }\n});\n\n/**\n * Build a job object with action methods that proxy through the client.\n * The job data is plain serialized data from the main thread.\n * Action methods (complete, fail, error, etc.) call back to the main thread client.\n */\nfunction createJobProxy(jobData: Record<string, unknown>, client: any): any {\n const acknowledged = { value: false };\n const ack = () => {\n acknowledged.value = true;\n job.acknowledged = true;\n };\n\n const job: any = { ...jobData };\n\n /**\n * Completion actions (complete/fail/error/cancelWorkflow) are stored as intent\n * rather than proxied through the MessagePort. The thread returns immediately,\n * and the main thread executes the API call asynchronously. This keeps threads\n * free for CPU work instead of blocking on I/O round-trips.\n */\n\n job.complete = async (variables: Record<string, unknown> = {}, result?: ApiJobResult) => {\n ack();\n job._completionAction = {\n method: 'completeJob',\n args: [{ variables, jobKey: jobData.jobKey, ...(result !== undefined && { result }) }],\n };\n return JobActionReceipt;\n };\n\n job.fail = async (reason: any) => {\n ack();\n job._completionAction = {\n method: 'failJob',\n args: [{ ...reason, jobKey: jobData.jobKey }],\n };\n return JobActionReceipt;\n };\n\n job.error = async (error: any) => {\n ack();\n job._completionAction = {\n method: 'throwJobError',\n args: [{ ...error, jobKey: jobData.jobKey }],\n };\n return JobActionReceipt;\n };\n\n job.cancelWorkflow = async () => {\n ack();\n job._completionAction = {\n method: 'cancelProcessInstance',\n args: [{ processInstanceKey: jobData.processInstanceKey }],\n };\n return JobActionReceipt;\n };\n\n job.ignore = async () => {\n ack();\n return JobActionReceipt;\n };\n\n // Non-completion actions still proxy through the client (rare, need response)\n job.modifyJobTimeout = ({ newTimeoutMs }: { newTimeoutMs: number }) =>\n client.updateJob({ changeset: { timeout: newTimeoutMs }, jobKey: jobData.jobKey });\n\n job.modifyRetries = ({ retries }: { retries: number }) =>\n client.updateJob({ changeset: { retries }, jobKey: jobData.jobKey });\n\n return job;\n}\n\n// Signal ready\nparentPort.postMessage({ type: 'ready' });\n","/**\n * Client proxy for worker_threads: allows threaded job handlers to call\n * CamundaClient methods transparently via MessagePort.\n *\n * Main thread side: installClientCallHandler(port, client)\n * Worker thread side: createClientProxy(port) → CamundaClient-shaped proxy\n */\n\nimport type { MessagePort } from 'node:worker_threads';\nimport type { CamundaClient } from '../gen/CamundaClient';\n\n// Wire protocol\nexport interface ClientCallMessage {\n type: 'client-call';\n callId: string;\n method: string;\n args: unknown[];\n}\n\nexport interface ClientCallResult {\n type: 'client-call-result';\n callId: string;\n result?: unknown;\n error?: string;\n}\n\n/** Fallback UUID generator for runtimes where globalThis.crypto.randomUUID is unavailable. */\nlet _counter = 0;\nfunction fallbackUUID(): string {\n // biome-ignore lint/plugin: correlation-id entropy, not cadence\n return `${Date.now().toString(36)}-${(++_counter).toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\n/**\n * Create a Proxy that looks like CamundaClient but forwards every method call\n * over a MessagePort to the main thread. Runs inside a worker thread.\n */\nexport function createClientProxy(port: MessagePort): CamundaClient {\n return new Proxy({} as CamundaClient, {\n get(_, method: string) {\n // Ignore symbol properties and common non-method accesses\n if (typeof method === 'symbol') return undefined;\n if (method === 'then') return undefined; // Prevent Proxy from being treated as thenable\n if (method === 'toJSON') return undefined;\n\n return (...args: unknown[]) => {\n const callId = globalThis.crypto?.randomUUID\n ? globalThis.crypto.randomUUID()\n : fallbackUUID();\n const msg: ClientCallMessage = { type: 'client-call', callId, method, args };\n port.postMessage(msg);\n return new Promise<unknown>((resolve, reject) => {\n const handler = (reply: ClientCallResult) => {\n if (reply.type !== 'client-call-result' || reply.callId !== callId) return;\n port.off('message', handler);\n if (reply.error !== undefined) {\n reject(new Error(reply.error));\n } else {\n resolve(reply.result);\n }\n };\n port.on('message', handler);\n });\n };\n },\n });\n}\n\n/**\n * Install a message handler on a MessagePort (main thread side) that\n * receives client-call messages from a worker thread and executes them\n * on the real CamundaClient instance.\n */\nexport function installClientCallHandler(port: MessagePort, client: CamundaClient): void {\n port.on('message', async (msg: ClientCallMessage) => {\n if (msg.type !== 'client-call') return;\n try {\n const fn = (client as any)[msg.method];\n if (typeof fn !== 'function') {\n throw new Error(`CamundaClient has no method '${msg.method}'`);\n }\n const result = await fn.apply(client, msg.args);\n const reply: ClientCallResult = { type: 'client-call-result', callId: msg.callId, result };\n port.postMessage(reply);\n } catch (err: any) {\n const reply: ClientCallResult = {\n type: 'client-call-result',\n callId: msg.callId,\n error: err?.message || String(err),\n };\n port.postMessage(reply);\n }\n });\n}\n","import { resolve as resolvePath } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\n/**\n * Turn a handler module reference into a specifier `import()` accepts.\n *\n * Bare specifiers (`@scope/pkg`, `my-handlers`) are passed through so normal package\n * resolution applies. Anything path-shaped is resolved against the working directory and\n * converted to a `file:` URL.\n *\n * The conversion must go through `pathToFileURL`. Hand-building the URL breaks on Windows\n * in three separate ways: `file://C:/...` puts the drive letter in the *host* rather than\n * the path, backslashes are not URL-legal and need escaping, and a bare `C:\\...` handed to\n * `new URL()` parses `C:` as the scheme — which is what produces \"Only URLs with a scheme\n * in: file, data, and node are supported by the default ESM loader\".\n */\nexport function toModuleSpecifier(handlerModule: string): string {\n const isPath =\n handlerModule.startsWith('.') ||\n handlerModule.startsWith('/') ||\n /^[a-zA-Z]:[\\\\/]/.test(handlerModule);\n\n return isPath ? pathToFileURL(resolvePath(handlerModule)).href : handlerModule;\n}\n"],"mappings":"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","names":["resolvePath","result"]}
1
+ {"version":3,"sources":["../src/runtime/threadWorkerEntry.ts","../src/runtime/clientProxy.ts","../src/runtime/moduleSpecifier.ts","../src/runtime/threadJobProxy.ts"],"sourcesContent":["/**\n * Worker thread entry point for the shared ThreadPool.\n *\n * Each thread in the pool runs this script. It:\n * 1. Waits for job messages on parentPort\n * 2. Dynamically imports and caches the handler module per handlerModule path\n * 3. Creates a client proxy + job proxy per job\n * 4. Calls the handler, sends back the result\n *\n * Threads are generic — the handler module is specified per-job, not per-thread.\n * Handlers are cached by module path so each import happens only once per thread.\n */\nimport { parentPort } from 'node:worker_threads';\nimport { createClientProxy } from './clientProxy.ts';\nimport { toModuleSpecifier } from './moduleSpecifier.ts';\nimport { createJobProxy } from './threadJobProxy.ts';\n\nif (!parentPort) {\n throw new Error('threadWorkerEntry must run inside a worker_threads Worker');\n}\n\ninterface JobMessage {\n type: 'job';\n /** Unique ID for this job dispatch (correlates response) */\n taskId: string;\n /** Serialized job data (plain object, no methods) */\n jobData: Record<string, unknown>;\n /** Handler module path — resolved per job, cached per thread */\n handlerModule: string;\n}\n\ninterface JobResult {\n type: 'job-result';\n taskId: string;\n ok: boolean;\n error?: string;\n /** When the handler acknowledged the job via complete/fail/error,\n * the action is captured here for the main thread to execute. */\n completionAction?: {\n method: string;\n args: unknown[];\n };\n}\n\n/** Cache of loaded handlers keyed by module path. Each thread loads a handler once per unique path. */\nconst handlerCache = new Map<string, (job: any, client: any) => Promise<any>>();\n\nasync function loadHandler(\n handlerModule: string\n): Promise<(job: any, client: any) => Promise<any>> {\n const cached = handlerCache.get(handlerModule);\n if (cached) return cached;\n\n const mod = await import(toModuleSpecifier(handlerModule));\n const handler = mod.default ?? mod.handler;\n if (typeof handler !== 'function') {\n throw new Error(\n `Threaded handler module '${handlerModule}' must export a default function or named 'handler' export`\n );\n }\n handlerCache.set(handlerModule, handler);\n return handler;\n}\n\nparentPort.on('message', async (msg: JobMessage & { clientPort?: any }) => {\n if (msg.type !== 'job') return;\n\n const { taskId, jobData, handlerModule, clientPort } = msg as JobMessage & {\n clientPort: import('node:worker_threads').MessagePort;\n };\n\n try {\n const handlerFn = await loadHandler(handlerModule);\n\n // Create a client proxy for this job's MessagePort\n const clientProxy = createClientProxy(clientPort);\n\n // Build a job-like object with proxied action methods\n const job = createJobProxy(jobData, clientProxy);\n\n await handlerFn(job, clientProxy);\n\n // If the handler never acknowledged the job (no complete/fail/error/ignore),\n // treat it as an error so the broker can retry rather than silently dropping it.\n if (!job.acknowledged) {\n const result: JobResult = {\n type: 'job-result',\n taskId,\n ok: false,\n error:\n `Handler for '${handlerModule}' returned without acknowledging the job. ` +\n 'Call job.complete(), job.fail(), job.error(), or job.ignore().',\n };\n parentPort!.postMessage(result);\n return;\n }\n\n const result: JobResult = {\n type: 'job-result',\n taskId,\n ok: true,\n completionAction: job._completionAction || undefined,\n };\n parentPort!.postMessage(result);\n } catch (err: any) {\n const result: JobResult = {\n type: 'job-result',\n taskId,\n ok: false,\n error: err?.message || String(err),\n };\n parentPort!.postMessage(result);\n } finally {\n // Close this job's client port\n if (clientPort && typeof clientPort.close === 'function') {\n clientPort.close();\n }\n }\n});\n\n// Signal ready\nparentPort.postMessage({ type: 'ready' });\n","/**\n * Client proxy for worker_threads: allows threaded job handlers to call\n * CamundaClient methods transparently via MessagePort.\n *\n * Main thread side: installClientCallHandler(port, client)\n * Worker thread side: createClientProxy(port) → CamundaClient-shaped proxy\n */\n\nimport type { MessagePort } from 'node:worker_threads';\nimport type { CamundaClient } from '../gen/CamundaClient';\n\n// Wire protocol\nexport interface ClientCallMessage {\n type: 'client-call';\n callId: string;\n method: string;\n args: unknown[];\n}\n\nexport interface ClientCallResult {\n type: 'client-call-result';\n callId: string;\n result?: unknown;\n error?: string;\n}\n\n/** Fallback UUID generator for runtimes where globalThis.crypto.randomUUID is unavailable. */\nlet _counter = 0;\nfunction fallbackUUID(): string {\n // biome-ignore lint/plugin: correlation-id entropy, not cadence\n return `${Date.now().toString(36)}-${(++_counter).toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\n/**\n * Create a Proxy that looks like CamundaClient but forwards every method call\n * over a MessagePort to the main thread. Runs inside a worker thread.\n */\nexport function createClientProxy(port: MessagePort): CamundaClient {\n return new Proxy({} as CamundaClient, {\n get(_, method: string) {\n // Ignore symbol properties and common non-method accesses\n if (typeof method === 'symbol') return undefined;\n if (method === 'then') return undefined; // Prevent Proxy from being treated as thenable\n if (method === 'toJSON') return undefined;\n\n return (...args: unknown[]) => {\n const callId = globalThis.crypto?.randomUUID\n ? globalThis.crypto.randomUUID()\n : fallbackUUID();\n const msg: ClientCallMessage = { type: 'client-call', callId, method, args };\n port.postMessage(msg);\n return new Promise<unknown>((resolve, reject) => {\n const handler = (reply: ClientCallResult) => {\n if (reply.type !== 'client-call-result' || reply.callId !== callId) return;\n port.off('message', handler);\n if (reply.error !== undefined) {\n reject(new Error(reply.error));\n } else {\n resolve(reply.result);\n }\n };\n port.on('message', handler);\n });\n };\n },\n });\n}\n\n/**\n * Install a message handler on a MessagePort (main thread side) that\n * receives client-call messages from a worker thread and executes them\n * on the real CamundaClient instance.\n */\nexport function installClientCallHandler(port: MessagePort, client: CamundaClient): void {\n port.on('message', async (msg: ClientCallMessage) => {\n if (msg.type !== 'client-call') return;\n try {\n const fn = (client as any)[msg.method];\n if (typeof fn !== 'function') {\n throw new Error(`CamundaClient has no method '${msg.method}'`);\n }\n const result = await fn.apply(client, msg.args);\n const reply: ClientCallResult = { type: 'client-call-result', callId: msg.callId, result };\n port.postMessage(reply);\n } catch (err: any) {\n const reply: ClientCallResult = {\n type: 'client-call-result',\n callId: msg.callId,\n error: err?.message || String(err),\n };\n port.postMessage(reply);\n }\n });\n}\n","import { resolve as resolvePath } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\n/**\n * Turn a handler module reference into a specifier `import()` accepts.\n *\n * Bare specifiers (`@scope/pkg`, `my-handlers`) are passed through so normal package\n * resolution applies. Anything path-shaped is resolved against the working directory and\n * converted to a `file:` URL.\n *\n * The conversion must go through `pathToFileURL`. Hand-building the URL breaks on Windows\n * in three separate ways: `file://C:/...` puts the drive letter in the *host* rather than\n * the path, backslashes are not URL-legal and need escaping, and a bare `C:\\...` handed to\n * `new URL()` parses `C:` as the scheme — which is what produces \"Only URLs with a scheme\n * in: file, data, and node are supported by the default ESM loader\".\n */\nexport function toModuleSpecifier(handlerModule: string): string {\n const isPath =\n handlerModule.startsWith('.') ||\n handlerModule.startsWith('/') ||\n /^[a-zA-Z]:[\\\\/]/.test(handlerModule);\n\n return isPath ? pathToFileURL(resolvePath(handlerModule)).href : handlerModule;\n}\n","/**\n * Build a job object with action methods that proxy through the client, used by\n * the threaded worker entry point (`threadWorkerEntry.ts`).\n *\n * Kept in its own module — separate from the worker-thread bootstrap, which\n * throws on import outside a `worker_threads` Worker — so the proxy's behaviour\n * (in particular that EVERY job action forwards the activation `leaseToken` back\n * to the main-thread client) is unit-testable directly, without spinning up a\n * real worker thread.\n *\n * The job data is plain serialized data from the main thread. Completion actions\n * (complete/fail/error/cancelWorkflow) are captured as intent on\n * `job._completionAction` and executed by the main thread; the non-completion\n * actions (modifyJobTimeout/modifyRetries) proxy straight through the client.\n */\nimport type { JobResult as ApiJobResult } from '../gen/types.gen';\n\n// Inline the JobActionReceipt constant to avoid importing the full SDK dependency\n// chain (jobWorker.ts → ../gen/CamundaClient → entire SDK) into the worker thread.\nconst JobActionReceipt = 'JOB_ACTION_RECEIPT' as const;\n\nexport function createJobProxy(jobData: Record<string, unknown>, client: any): any {\n const acknowledged = { value: false };\n const ack = () => {\n acknowledged.value = true;\n job.acknowledged = true;\n };\n\n const job: any = { ...jobData };\n\n /**\n * Completion actions (complete/fail/error/cancelWorkflow) are stored as intent\n * rather than proxied through the MessagePort. The thread returns immediately,\n * and the main thread executes the API call asynchronously. This keeps threads\n * free for CPU work instead of blocking on I/O round-trips.\n */\n\n job.complete = async (variables: Record<string, unknown> = {}, result?: ApiJobResult) => {\n ack();\n job._completionAction = {\n method: 'completeJob',\n args: [\n {\n variables,\n jobKey: jobData.jobKey,\n ...(result !== undefined && { result }),\n ...(jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}),\n },\n ],\n };\n return JobActionReceipt;\n };\n\n job.fail = async (reason: any) => {\n ack();\n job._completionAction = {\n method: 'failJob',\n args: [\n {\n ...reason,\n jobKey: jobData.jobKey,\n ...(jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}),\n },\n ],\n };\n return JobActionReceipt;\n };\n\n job.error = async (error: any) => {\n ack();\n job._completionAction = {\n method: 'throwJobError',\n args: [\n {\n ...error,\n jobKey: jobData.jobKey,\n ...(jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}),\n },\n ],\n };\n return JobActionReceipt;\n };\n\n job.cancelWorkflow = async () => {\n ack();\n job._completionAction = {\n method: 'cancelProcessInstance',\n args: [{ processInstanceKey: jobData.processInstanceKey }],\n };\n return JobActionReceipt;\n };\n\n job.ignore = async () => {\n ack();\n return JobActionReceipt;\n };\n\n // Non-completion actions still proxy through the client (rare, need response)\n job.modifyJobTimeout = ({ newTimeoutMs }: { newTimeoutMs: number }) =>\n client.updateJob({\n changeset: { timeout: newTimeoutMs },\n jobKey: jobData.jobKey,\n ...(jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}),\n });\n\n job.modifyRetries = ({ retries }: { retries: number }) =>\n client.updateJob({\n changeset: { retries },\n jobKey: jobData.jobKey,\n ...(jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}),\n });\n\n return job;\n}\n"],"mappings":"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","names":["resolvePath","result"]}
@@ -41,8 +41,84 @@ function toModuleSpecifier(handlerModule) {
41
41
  return isPath ? pathToFileURL(resolvePath(handlerModule)).href : handlerModule;
42
42
  }
43
43
 
44
- // src/runtime/threadWorkerEntry.ts
44
+ // src/runtime/threadJobProxy.ts
45
45
  var JobActionReceipt = "JOB_ACTION_RECEIPT";
46
+ function createJobProxy(jobData, client) {
47
+ const acknowledged = { value: false };
48
+ const ack = () => {
49
+ acknowledged.value = true;
50
+ job.acknowledged = true;
51
+ };
52
+ const job = { ...jobData };
53
+ job.complete = async (variables = {}, result) => {
54
+ ack();
55
+ job._completionAction = {
56
+ method: "completeJob",
57
+ args: [
58
+ {
59
+ variables,
60
+ jobKey: jobData.jobKey,
61
+ ...result !== void 0 && { result },
62
+ ...jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}
63
+ }
64
+ ]
65
+ };
66
+ return JobActionReceipt;
67
+ };
68
+ job.fail = async (reason) => {
69
+ ack();
70
+ job._completionAction = {
71
+ method: "failJob",
72
+ args: [
73
+ {
74
+ ...reason,
75
+ jobKey: jobData.jobKey,
76
+ ...jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}
77
+ }
78
+ ]
79
+ };
80
+ return JobActionReceipt;
81
+ };
82
+ job.error = async (error) => {
83
+ ack();
84
+ job._completionAction = {
85
+ method: "throwJobError",
86
+ args: [
87
+ {
88
+ ...error,
89
+ jobKey: jobData.jobKey,
90
+ ...jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}
91
+ }
92
+ ]
93
+ };
94
+ return JobActionReceipt;
95
+ };
96
+ job.cancelWorkflow = async () => {
97
+ ack();
98
+ job._completionAction = {
99
+ method: "cancelProcessInstance",
100
+ args: [{ processInstanceKey: jobData.processInstanceKey }]
101
+ };
102
+ return JobActionReceipt;
103
+ };
104
+ job.ignore = async () => {
105
+ ack();
106
+ return JobActionReceipt;
107
+ };
108
+ job.modifyJobTimeout = ({ newTimeoutMs }) => client.updateJob({
109
+ changeset: { timeout: newTimeoutMs },
110
+ jobKey: jobData.jobKey,
111
+ ...jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}
112
+ });
113
+ job.modifyRetries = ({ retries }) => client.updateJob({
114
+ changeset: { retries },
115
+ jobKey: jobData.jobKey,
116
+ ...jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}
117
+ });
118
+ return job;
119
+ }
120
+
121
+ // src/runtime/threadWorkerEntry.ts
46
122
  if (!parentPort) {
47
123
  throw new Error("threadWorkerEntry must run inside a worker_threads Worker");
48
124
  }
@@ -99,52 +175,5 @@ parentPort.on("message", async (msg) => {
99
175
  }
100
176
  }
101
177
  });
102
- function createJobProxy(jobData, client) {
103
- const acknowledged = { value: false };
104
- const ack = () => {
105
- acknowledged.value = true;
106
- job.acknowledged = true;
107
- };
108
- const job = { ...jobData };
109
- job.complete = async (variables = {}, result) => {
110
- ack();
111
- job._completionAction = {
112
- method: "completeJob",
113
- args: [{ variables, jobKey: jobData.jobKey, ...result !== void 0 && { result } }]
114
- };
115
- return JobActionReceipt;
116
- };
117
- job.fail = async (reason) => {
118
- ack();
119
- job._completionAction = {
120
- method: "failJob",
121
- args: [{ ...reason, jobKey: jobData.jobKey }]
122
- };
123
- return JobActionReceipt;
124
- };
125
- job.error = async (error) => {
126
- ack();
127
- job._completionAction = {
128
- method: "throwJobError",
129
- args: [{ ...error, jobKey: jobData.jobKey }]
130
- };
131
- return JobActionReceipt;
132
- };
133
- job.cancelWorkflow = async () => {
134
- ack();
135
- job._completionAction = {
136
- method: "cancelProcessInstance",
137
- args: [{ processInstanceKey: jobData.processInstanceKey }]
138
- };
139
- return JobActionReceipt;
140
- };
141
- job.ignore = async () => {
142
- ack();
143
- return JobActionReceipt;
144
- };
145
- job.modifyJobTimeout = ({ newTimeoutMs }) => client.updateJob({ changeset: { timeout: newTimeoutMs }, jobKey: jobData.jobKey });
146
- job.modifyRetries = ({ retries }) => client.updateJob({ changeset: { retries }, jobKey: jobData.jobKey });
147
- return job;
148
- }
149
178
  parentPort.postMessage({ type: "ready" });
150
179
  //# sourceMappingURL=threadWorkerEntry.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/runtime/threadWorkerEntry.ts","../src/runtime/clientProxy.ts","../src/runtime/moduleSpecifier.ts"],"sourcesContent":["/**\n * Worker thread entry point for the shared ThreadPool.\n *\n * Each thread in the pool runs this script. It:\n * 1. Waits for job messages on parentPort\n * 2. Dynamically imports and caches the handler module per handlerModule path\n * 3. Creates a client proxy + job proxy per job\n * 4. Calls the handler, sends back the result\n *\n * Threads are generic — the handler module is specified per-job, not per-thread.\n * Handlers are cached by module path so each import happens only once per thread.\n */\nimport { parentPort } from 'node:worker_threads';\nimport type { JobResult as ApiJobResult } from '../gen/types.gen';\nimport { createClientProxy } from './clientProxy.ts';\nimport { toModuleSpecifier } from './moduleSpecifier.ts';\n\n// Inline the JobActionReceipt constant to avoid importing the full SDK dependency chain\n// (jobWorker.ts → ../gen/CamundaClient → entire SDK) in the worker thread.\nconst JobActionReceipt = 'JOB_ACTION_RECEIPT' as const;\n\nif (!parentPort) {\n throw new Error('threadWorkerEntry must run inside a worker_threads Worker');\n}\n\ninterface JobMessage {\n type: 'job';\n /** Unique ID for this job dispatch (correlates response) */\n taskId: string;\n /** Serialized job data (plain object, no methods) */\n jobData: Record<string, unknown>;\n /** Handler module path — resolved per job, cached per thread */\n handlerModule: string;\n}\n\ninterface JobResult {\n type: 'job-result';\n taskId: string;\n ok: boolean;\n error?: string;\n /** When the handler acknowledged the job via complete/fail/error,\n * the action is captured here for the main thread to execute. */\n completionAction?: {\n method: string;\n args: unknown[];\n };\n}\n\n/** Cache of loaded handlers keyed by module path. Each thread loads a handler once per unique path. */\nconst handlerCache = new Map<string, (job: any, client: any) => Promise<any>>();\n\nasync function loadHandler(\n handlerModule: string\n): Promise<(job: any, client: any) => Promise<any>> {\n const cached = handlerCache.get(handlerModule);\n if (cached) return cached;\n\n const mod = await import(toModuleSpecifier(handlerModule));\n const handler = mod.default ?? mod.handler;\n if (typeof handler !== 'function') {\n throw new Error(\n `Threaded handler module '${handlerModule}' must export a default function or named 'handler' export`\n );\n }\n handlerCache.set(handlerModule, handler);\n return handler;\n}\n\nparentPort.on('message', async (msg: JobMessage & { clientPort?: any }) => {\n if (msg.type !== 'job') return;\n\n const { taskId, jobData, handlerModule, clientPort } = msg as JobMessage & {\n clientPort: import('node:worker_threads').MessagePort;\n };\n\n try {\n const handlerFn = await loadHandler(handlerModule);\n\n // Create a client proxy for this job's MessagePort\n const clientProxy = createClientProxy(clientPort);\n\n // Build a job-like object with proxied action methods\n const job = createJobProxy(jobData, clientProxy);\n\n await handlerFn(job, clientProxy);\n\n // If the handler never acknowledged the job (no complete/fail/error/ignore),\n // treat it as an error so the broker can retry rather than silently dropping it.\n if (!job.acknowledged) {\n const result: JobResult = {\n type: 'job-result',\n taskId,\n ok: false,\n error:\n `Handler for '${handlerModule}' returned without acknowledging the job. ` +\n 'Call job.complete(), job.fail(), job.error(), or job.ignore().',\n };\n parentPort!.postMessage(result);\n return;\n }\n\n const result: JobResult = {\n type: 'job-result',\n taskId,\n ok: true,\n completionAction: job._completionAction || undefined,\n };\n parentPort!.postMessage(result);\n } catch (err: any) {\n const result: JobResult = {\n type: 'job-result',\n taskId,\n ok: false,\n error: err?.message || String(err),\n };\n parentPort!.postMessage(result);\n } finally {\n // Close this job's client port\n if (clientPort && typeof clientPort.close === 'function') {\n clientPort.close();\n }\n }\n});\n\n/**\n * Build a job object with action methods that proxy through the client.\n * The job data is plain serialized data from the main thread.\n * Action methods (complete, fail, error, etc.) call back to the main thread client.\n */\nfunction createJobProxy(jobData: Record<string, unknown>, client: any): any {\n const acknowledged = { value: false };\n const ack = () => {\n acknowledged.value = true;\n job.acknowledged = true;\n };\n\n const job: any = { ...jobData };\n\n /**\n * Completion actions (complete/fail/error/cancelWorkflow) are stored as intent\n * rather than proxied through the MessagePort. The thread returns immediately,\n * and the main thread executes the API call asynchronously. This keeps threads\n * free for CPU work instead of blocking on I/O round-trips.\n */\n\n job.complete = async (variables: Record<string, unknown> = {}, result?: ApiJobResult) => {\n ack();\n job._completionAction = {\n method: 'completeJob',\n args: [{ variables, jobKey: jobData.jobKey, ...(result !== undefined && { result }) }],\n };\n return JobActionReceipt;\n };\n\n job.fail = async (reason: any) => {\n ack();\n job._completionAction = {\n method: 'failJob',\n args: [{ ...reason, jobKey: jobData.jobKey }],\n };\n return JobActionReceipt;\n };\n\n job.error = async (error: any) => {\n ack();\n job._completionAction = {\n method: 'throwJobError',\n args: [{ ...error, jobKey: jobData.jobKey }],\n };\n return JobActionReceipt;\n };\n\n job.cancelWorkflow = async () => {\n ack();\n job._completionAction = {\n method: 'cancelProcessInstance',\n args: [{ processInstanceKey: jobData.processInstanceKey }],\n };\n return JobActionReceipt;\n };\n\n job.ignore = async () => {\n ack();\n return JobActionReceipt;\n };\n\n // Non-completion actions still proxy through the client (rare, need response)\n job.modifyJobTimeout = ({ newTimeoutMs }: { newTimeoutMs: number }) =>\n client.updateJob({ changeset: { timeout: newTimeoutMs }, jobKey: jobData.jobKey });\n\n job.modifyRetries = ({ retries }: { retries: number }) =>\n client.updateJob({ changeset: { retries }, jobKey: jobData.jobKey });\n\n return job;\n}\n\n// Signal ready\nparentPort.postMessage({ type: 'ready' });\n","/**\n * Client proxy for worker_threads: allows threaded job handlers to call\n * CamundaClient methods transparently via MessagePort.\n *\n * Main thread side: installClientCallHandler(port, client)\n * Worker thread side: createClientProxy(port) → CamundaClient-shaped proxy\n */\n\nimport type { MessagePort } from 'node:worker_threads';\nimport type { CamundaClient } from '../gen/CamundaClient';\n\n// Wire protocol\nexport interface ClientCallMessage {\n type: 'client-call';\n callId: string;\n method: string;\n args: unknown[];\n}\n\nexport interface ClientCallResult {\n type: 'client-call-result';\n callId: string;\n result?: unknown;\n error?: string;\n}\n\n/** Fallback UUID generator for runtimes where globalThis.crypto.randomUUID is unavailable. */\nlet _counter = 0;\nfunction fallbackUUID(): string {\n // biome-ignore lint/plugin: correlation-id entropy, not cadence\n return `${Date.now().toString(36)}-${(++_counter).toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\n/**\n * Create a Proxy that looks like CamundaClient but forwards every method call\n * over a MessagePort to the main thread. Runs inside a worker thread.\n */\nexport function createClientProxy(port: MessagePort): CamundaClient {\n return new Proxy({} as CamundaClient, {\n get(_, method: string) {\n // Ignore symbol properties and common non-method accesses\n if (typeof method === 'symbol') return undefined;\n if (method === 'then') return undefined; // Prevent Proxy from being treated as thenable\n if (method === 'toJSON') return undefined;\n\n return (...args: unknown[]) => {\n const callId = globalThis.crypto?.randomUUID\n ? globalThis.crypto.randomUUID()\n : fallbackUUID();\n const msg: ClientCallMessage = { type: 'client-call', callId, method, args };\n port.postMessage(msg);\n return new Promise<unknown>((resolve, reject) => {\n const handler = (reply: ClientCallResult) => {\n if (reply.type !== 'client-call-result' || reply.callId !== callId) return;\n port.off('message', handler);\n if (reply.error !== undefined) {\n reject(new Error(reply.error));\n } else {\n resolve(reply.result);\n }\n };\n port.on('message', handler);\n });\n };\n },\n });\n}\n\n/**\n * Install a message handler on a MessagePort (main thread side) that\n * receives client-call messages from a worker thread and executes them\n * on the real CamundaClient instance.\n */\nexport function installClientCallHandler(port: MessagePort, client: CamundaClient): void {\n port.on('message', async (msg: ClientCallMessage) => {\n if (msg.type !== 'client-call') return;\n try {\n const fn = (client as any)[msg.method];\n if (typeof fn !== 'function') {\n throw new Error(`CamundaClient has no method '${msg.method}'`);\n }\n const result = await fn.apply(client, msg.args);\n const reply: ClientCallResult = { type: 'client-call-result', callId: msg.callId, result };\n port.postMessage(reply);\n } catch (err: any) {\n const reply: ClientCallResult = {\n type: 'client-call-result',\n callId: msg.callId,\n error: err?.message || String(err),\n };\n port.postMessage(reply);\n }\n });\n}\n","import { resolve as resolvePath } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\n/**\n * Turn a handler module reference into a specifier `import()` accepts.\n *\n * Bare specifiers (`@scope/pkg`, `my-handlers`) are passed through so normal package\n * resolution applies. Anything path-shaped is resolved against the working directory and\n * converted to a `file:` URL.\n *\n * The conversion must go through `pathToFileURL`. Hand-building the URL breaks on Windows\n * in three separate ways: `file://C:/...` puts the drive letter in the *host* rather than\n * the path, backslashes are not URL-legal and need escaping, and a bare `C:\\...` handed to\n * `new URL()` parses `C:` as the scheme — which is what produces \"Only URLs with a scheme\n * in: file, data, and node are supported by the default ESM loader\".\n */\nexport function toModuleSpecifier(handlerModule: string): string {\n const isPath =\n handlerModule.startsWith('.') ||\n handlerModule.startsWith('/') ||\n /^[a-zA-Z]:[\\\\/]/.test(handlerModule);\n\n return isPath ? pathToFileURL(resolvePath(handlerModule)).href : handlerModule;\n}\n"],"mappings":"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","names":["result"]}
1
+ {"version":3,"sources":["../src/runtime/threadWorkerEntry.ts","../src/runtime/clientProxy.ts","../src/runtime/moduleSpecifier.ts","../src/runtime/threadJobProxy.ts"],"sourcesContent":["/**\n * Worker thread entry point for the shared ThreadPool.\n *\n * Each thread in the pool runs this script. It:\n * 1. Waits for job messages on parentPort\n * 2. Dynamically imports and caches the handler module per handlerModule path\n * 3. Creates a client proxy + job proxy per job\n * 4. Calls the handler, sends back the result\n *\n * Threads are generic — the handler module is specified per-job, not per-thread.\n * Handlers are cached by module path so each import happens only once per thread.\n */\nimport { parentPort } from 'node:worker_threads';\nimport { createClientProxy } from './clientProxy.ts';\nimport { toModuleSpecifier } from './moduleSpecifier.ts';\nimport { createJobProxy } from './threadJobProxy.ts';\n\nif (!parentPort) {\n throw new Error('threadWorkerEntry must run inside a worker_threads Worker');\n}\n\ninterface JobMessage {\n type: 'job';\n /** Unique ID for this job dispatch (correlates response) */\n taskId: string;\n /** Serialized job data (plain object, no methods) */\n jobData: Record<string, unknown>;\n /** Handler module path — resolved per job, cached per thread */\n handlerModule: string;\n}\n\ninterface JobResult {\n type: 'job-result';\n taskId: string;\n ok: boolean;\n error?: string;\n /** When the handler acknowledged the job via complete/fail/error,\n * the action is captured here for the main thread to execute. */\n completionAction?: {\n method: string;\n args: unknown[];\n };\n}\n\n/** Cache of loaded handlers keyed by module path. Each thread loads a handler once per unique path. */\nconst handlerCache = new Map<string, (job: any, client: any) => Promise<any>>();\n\nasync function loadHandler(\n handlerModule: string\n): Promise<(job: any, client: any) => Promise<any>> {\n const cached = handlerCache.get(handlerModule);\n if (cached) return cached;\n\n const mod = await import(toModuleSpecifier(handlerModule));\n const handler = mod.default ?? mod.handler;\n if (typeof handler !== 'function') {\n throw new Error(\n `Threaded handler module '${handlerModule}' must export a default function or named 'handler' export`\n );\n }\n handlerCache.set(handlerModule, handler);\n return handler;\n}\n\nparentPort.on('message', async (msg: JobMessage & { clientPort?: any }) => {\n if (msg.type !== 'job') return;\n\n const { taskId, jobData, handlerModule, clientPort } = msg as JobMessage & {\n clientPort: import('node:worker_threads').MessagePort;\n };\n\n try {\n const handlerFn = await loadHandler(handlerModule);\n\n // Create a client proxy for this job's MessagePort\n const clientProxy = createClientProxy(clientPort);\n\n // Build a job-like object with proxied action methods\n const job = createJobProxy(jobData, clientProxy);\n\n await handlerFn(job, clientProxy);\n\n // If the handler never acknowledged the job (no complete/fail/error/ignore),\n // treat it as an error so the broker can retry rather than silently dropping it.\n if (!job.acknowledged) {\n const result: JobResult = {\n type: 'job-result',\n taskId,\n ok: false,\n error:\n `Handler for '${handlerModule}' returned without acknowledging the job. ` +\n 'Call job.complete(), job.fail(), job.error(), or job.ignore().',\n };\n parentPort!.postMessage(result);\n return;\n }\n\n const result: JobResult = {\n type: 'job-result',\n taskId,\n ok: true,\n completionAction: job._completionAction || undefined,\n };\n parentPort!.postMessage(result);\n } catch (err: any) {\n const result: JobResult = {\n type: 'job-result',\n taskId,\n ok: false,\n error: err?.message || String(err),\n };\n parentPort!.postMessage(result);\n } finally {\n // Close this job's client port\n if (clientPort && typeof clientPort.close === 'function') {\n clientPort.close();\n }\n }\n});\n\n// Signal ready\nparentPort.postMessage({ type: 'ready' });\n","/**\n * Client proxy for worker_threads: allows threaded job handlers to call\n * CamundaClient methods transparently via MessagePort.\n *\n * Main thread side: installClientCallHandler(port, client)\n * Worker thread side: createClientProxy(port) → CamundaClient-shaped proxy\n */\n\nimport type { MessagePort } from 'node:worker_threads';\nimport type { CamundaClient } from '../gen/CamundaClient';\n\n// Wire protocol\nexport interface ClientCallMessage {\n type: 'client-call';\n callId: string;\n method: string;\n args: unknown[];\n}\n\nexport interface ClientCallResult {\n type: 'client-call-result';\n callId: string;\n result?: unknown;\n error?: string;\n}\n\n/** Fallback UUID generator for runtimes where globalThis.crypto.randomUUID is unavailable. */\nlet _counter = 0;\nfunction fallbackUUID(): string {\n // biome-ignore lint/plugin: correlation-id entropy, not cadence\n return `${Date.now().toString(36)}-${(++_counter).toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\n/**\n * Create a Proxy that looks like CamundaClient but forwards every method call\n * over a MessagePort to the main thread. Runs inside a worker thread.\n */\nexport function createClientProxy(port: MessagePort): CamundaClient {\n return new Proxy({} as CamundaClient, {\n get(_, method: string) {\n // Ignore symbol properties and common non-method accesses\n if (typeof method === 'symbol') return undefined;\n if (method === 'then') return undefined; // Prevent Proxy from being treated as thenable\n if (method === 'toJSON') return undefined;\n\n return (...args: unknown[]) => {\n const callId = globalThis.crypto?.randomUUID\n ? globalThis.crypto.randomUUID()\n : fallbackUUID();\n const msg: ClientCallMessage = { type: 'client-call', callId, method, args };\n port.postMessage(msg);\n return new Promise<unknown>((resolve, reject) => {\n const handler = (reply: ClientCallResult) => {\n if (reply.type !== 'client-call-result' || reply.callId !== callId) return;\n port.off('message', handler);\n if (reply.error !== undefined) {\n reject(new Error(reply.error));\n } else {\n resolve(reply.result);\n }\n };\n port.on('message', handler);\n });\n };\n },\n });\n}\n\n/**\n * Install a message handler on a MessagePort (main thread side) that\n * receives client-call messages from a worker thread and executes them\n * on the real CamundaClient instance.\n */\nexport function installClientCallHandler(port: MessagePort, client: CamundaClient): void {\n port.on('message', async (msg: ClientCallMessage) => {\n if (msg.type !== 'client-call') return;\n try {\n const fn = (client as any)[msg.method];\n if (typeof fn !== 'function') {\n throw new Error(`CamundaClient has no method '${msg.method}'`);\n }\n const result = await fn.apply(client, msg.args);\n const reply: ClientCallResult = { type: 'client-call-result', callId: msg.callId, result };\n port.postMessage(reply);\n } catch (err: any) {\n const reply: ClientCallResult = {\n type: 'client-call-result',\n callId: msg.callId,\n error: err?.message || String(err),\n };\n port.postMessage(reply);\n }\n });\n}\n","import { resolve as resolvePath } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\n/**\n * Turn a handler module reference into a specifier `import()` accepts.\n *\n * Bare specifiers (`@scope/pkg`, `my-handlers`) are passed through so normal package\n * resolution applies. Anything path-shaped is resolved against the working directory and\n * converted to a `file:` URL.\n *\n * The conversion must go through `pathToFileURL`. Hand-building the URL breaks on Windows\n * in three separate ways: `file://C:/...` puts the drive letter in the *host* rather than\n * the path, backslashes are not URL-legal and need escaping, and a bare `C:\\...` handed to\n * `new URL()` parses `C:` as the scheme — which is what produces \"Only URLs with a scheme\n * in: file, data, and node are supported by the default ESM loader\".\n */\nexport function toModuleSpecifier(handlerModule: string): string {\n const isPath =\n handlerModule.startsWith('.') ||\n handlerModule.startsWith('/') ||\n /^[a-zA-Z]:[\\\\/]/.test(handlerModule);\n\n return isPath ? pathToFileURL(resolvePath(handlerModule)).href : handlerModule;\n}\n","/**\n * Build a job object with action methods that proxy through the client, used by\n * the threaded worker entry point (`threadWorkerEntry.ts`).\n *\n * Kept in its own module — separate from the worker-thread bootstrap, which\n * throws on import outside a `worker_threads` Worker — so the proxy's behaviour\n * (in particular that EVERY job action forwards the activation `leaseToken` back\n * to the main-thread client) is unit-testable directly, without spinning up a\n * real worker thread.\n *\n * The job data is plain serialized data from the main thread. Completion actions\n * (complete/fail/error/cancelWorkflow) are captured as intent on\n * `job._completionAction` and executed by the main thread; the non-completion\n * actions (modifyJobTimeout/modifyRetries) proxy straight through the client.\n */\nimport type { JobResult as ApiJobResult } from '../gen/types.gen';\n\n// Inline the JobActionReceipt constant to avoid importing the full SDK dependency\n// chain (jobWorker.ts → ../gen/CamundaClient → entire SDK) into the worker thread.\nconst JobActionReceipt = 'JOB_ACTION_RECEIPT' as const;\n\nexport function createJobProxy(jobData: Record<string, unknown>, client: any): any {\n const acknowledged = { value: false };\n const ack = () => {\n acknowledged.value = true;\n job.acknowledged = true;\n };\n\n const job: any = { ...jobData };\n\n /**\n * Completion actions (complete/fail/error/cancelWorkflow) are stored as intent\n * rather than proxied through the MessagePort. The thread returns immediately,\n * and the main thread executes the API call asynchronously. This keeps threads\n * free for CPU work instead of blocking on I/O round-trips.\n */\n\n job.complete = async (variables: Record<string, unknown> = {}, result?: ApiJobResult) => {\n ack();\n job._completionAction = {\n method: 'completeJob',\n args: [\n {\n variables,\n jobKey: jobData.jobKey,\n ...(result !== undefined && { result }),\n ...(jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}),\n },\n ],\n };\n return JobActionReceipt;\n };\n\n job.fail = async (reason: any) => {\n ack();\n job._completionAction = {\n method: 'failJob',\n args: [\n {\n ...reason,\n jobKey: jobData.jobKey,\n ...(jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}),\n },\n ],\n };\n return JobActionReceipt;\n };\n\n job.error = async (error: any) => {\n ack();\n job._completionAction = {\n method: 'throwJobError',\n args: [\n {\n ...error,\n jobKey: jobData.jobKey,\n ...(jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}),\n },\n ],\n };\n return JobActionReceipt;\n };\n\n job.cancelWorkflow = async () => {\n ack();\n job._completionAction = {\n method: 'cancelProcessInstance',\n args: [{ processInstanceKey: jobData.processInstanceKey }],\n };\n return JobActionReceipt;\n };\n\n job.ignore = async () => {\n ack();\n return JobActionReceipt;\n };\n\n // Non-completion actions still proxy through the client (rare, need response)\n job.modifyJobTimeout = ({ newTimeoutMs }: { newTimeoutMs: number }) =>\n client.updateJob({\n changeset: { timeout: newTimeoutMs },\n jobKey: jobData.jobKey,\n ...(jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}),\n });\n\n job.modifyRetries = ({ retries }: { retries: number }) =>\n client.updateJob({\n changeset: { retries },\n jobKey: jobData.jobKey,\n ...(jobData.leaseToken != null ? { leaseToken: jobData.leaseToken } : {}),\n });\n\n return job;\n}\n"],"mappings":"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","names":["result"]}
@@ -9,15 +9,6 @@ var zAgentDefinitionTypeEnum = z.enum([
9
9
  ]).register(z.globalRegistry, {
10
10
  description: "The kind of agent an agent definition describes."
11
11
  });
12
- var zAgentTool = z.object({
13
- name: z.string().register(z.globalRegistry, {
14
- description: "The tool name as visible to the LLM."
15
- }),
16
- description: z.string().nullable(),
17
- elementId: z.string().nullable()
18
- }).register(z.globalRegistry, {
19
- description: "A tool available to the agent."
20
- });
21
12
  var zAgentInstanceMetrics = z.object({
22
13
  inputTokens: z.coerce.number().int().min(-9223372036854776e3, { error: "Invalid value: Expected int64 to be >= -9223372036854775808" }).max(9223372036854776e3, { error: "Invalid value: Expected int64 to be <= 9223372036854775807" }).register(z.globalRegistry, {
23
14
  description: "Total input tokens consumed across all model calls."
@@ -117,18 +108,6 @@ var zAgentInstanceMessageContentTypeEnum = z.enum([
117
108
  ]).register(z.globalRegistry, {
118
109
  description: "The content type discriminator for a history item content block."
119
110
  });
120
- var zAgentInstanceToolCall = z.object({
121
- toolCallId: z.string().register(z.globalRegistry, {
122
- description: "The LLM-assigned tool call ID. Correlates ASSISTANT items to their matching TOOL_RESULT items."
123
- }),
124
- toolName: z.string().register(z.globalRegistry, {
125
- description: "The LLM-visible tool name."
126
- }),
127
- elementId: z.string().nullable(),
128
- arguments: z.record(z.string(), z.unknown()).nullable()
129
- }).register(z.globalRegistry, {
130
- description: "A tool call associated with a history item. Used in both ASSISTANT and TOOL_RESULT items.\n"
131
- });
132
111
  var zAgentInstanceHistoryItemMetricsRequest = z.object({
133
112
  inputTokens: z.coerce.number().int().min(-9223372036854776e3, { error: "Invalid value: Expected int64 to be >= -9223372036854775808" }).max(9223372036854776e3, { error: "Invalid value: Expected int64 to be <= 9223372036854775807" }).nullish(),
134
113
  outputTokens: z.coerce.number().int().min(-9223372036854776e3, { error: "Invalid value: Expected int64 to be >= -9223372036854775808" }).max(9223372036854776e3, { error: "Invalid value: Expected int64 to be <= 9223372036854775807" }).nullish(),
@@ -1841,9 +1820,7 @@ var zGroupFilterFields = z.object({
1841
1820
  description: "Group filter request"
1842
1821
  });
1843
1822
  var zGroupFilter = zGroupFilterFields.and(z.object({
1844
- $or: z.array(zGroupFilterFields).register(z.globalRegistry, {
1845
- description: 'Defines a list of alternative filter groups combined using OR logic. Each object in the array is evaluated independently, and the filter matches if any one of them is satisfied.\n\nTop-level fields and the `$or` clause are combined using AND logic \u2014 meaning: (top-level filters) AND (any of the `$or` filters) must match.\n<br>\n<em>Example:</em>\n\n```json\n{\n "$or": [\n { "groupId": "group-1" },\n { "groupId": "group-2" }\n ]\n}\n```\nThis matches groups whose <code>groupId</code> is <em>group-1</em> or <em>group-2</em>.\n<br>\n<p>Note: Using complex <code>$or</code> conditions may impact performance, use with caution in high-volume environments.\n'
1846
- }).optional()
1823
+ $or: z.array(zGroupFilterFields).nullish()
1847
1824
  }));
1848
1825
  var zProcessDefinitionId = z.string().min(1).regex(/^[\p{L}_][\p{L}\p{N}_\-\.]*$/u).register(z.globalRegistry, {
1849
1826
  description: "Id of a process definition, from the model. Only ids of process definitions that are deployed are useful."
@@ -1851,6 +1828,27 @@ var zProcessDefinitionId = z.string().min(1).regex(/^[\p{L}_][\p{L}\p{N}_\-\.]*$
1851
1828
  var zElementId = z.string().register(z.globalRegistry, {
1852
1829
  description: "The model-defined id of an element."
1853
1830
  });
1831
+ var zAgentTool = z.object({
1832
+ name: z.string().register(z.globalRegistry, {
1833
+ description: "The tool name as visible to the LLM."
1834
+ }),
1835
+ description: z.string().nullable(),
1836
+ elementId: zElementId.nullable()
1837
+ }).register(z.globalRegistry, {
1838
+ description: "A tool available to the agent."
1839
+ });
1840
+ var zAgentInstanceToolCall = z.object({
1841
+ toolCallId: z.string().register(z.globalRegistry, {
1842
+ description: "The LLM-assigned tool call ID. Correlates ASSISTANT items to their matching TOOL_RESULT items."
1843
+ }),
1844
+ toolName: z.string().register(z.globalRegistry, {
1845
+ description: "The LLM-visible tool name."
1846
+ }),
1847
+ elementId: zElementId.nullable(),
1848
+ arguments: z.record(z.string(), z.unknown()).nullable()
1849
+ }).register(z.globalRegistry, {
1850
+ description: "A tool call associated with a history item. Used in both ASSISTANT and TOOL_RESULT items.\n"
1851
+ });
1854
1852
  var zProcessInstanceModificationMoveBatchOperationInstruction = z.object({
1855
1853
  sourceElementId: zElementId,
1856
1854
  targetElementId: zElementId
@@ -2872,7 +2870,7 @@ var zActivatedJobResult = z.object({
2872
2870
  priority: z.int().min(-2147483648, { error: "Invalid value: Expected int32 to be >= -2147483648" }).max(2147483647, { error: "Invalid value: Expected int32 to be <= 2147483647" }).register(z.globalRegistry, {
2873
2871
  description: "The priority of the job. Higher values indicate higher priority. Jobs created before 8.10 have no stored priority; the API returns 0 for such jobs.\n"
2874
2872
  }),
2875
- leaseToken: zJobLeaseToken.nullable()
2873
+ leaseToken: zJobLeaseToken.nullish()
2876
2874
  });
2877
2875
  var zJobActivationResult = z.object({
2878
2876
  jobs: z.array(zActivatedJobResult).register(z.globalRegistry, {
@@ -3720,9 +3718,7 @@ var zMappingRuleFilterFields = z.object({
3720
3718
  description: "Mapping rule search filter fields."
3721
3719
  });
3722
3720
  var zMappingRuleFilter = zMappingRuleFilterFields.and(z.object({
3723
- $or: z.array(zMappingRuleFilterFields).register(z.globalRegistry, {
3724
- description: 'Defines a list of alternative filter groups combined using OR logic. Each object in the array is evaluated independently, and the filter matches if any one of them is satisfied.\n\nTop-level fields and the `$or` clause are combined using AND logic \u2014 meaning: (top-level filters) AND (any of the `$or` filters) must match.\n<br>\n<em>Example:</em>\n\n```json\n{\n "$or": [\n { "mappingRuleId": "rule-1" },\n { "mappingRuleId": "rule-2" }\n ]\n}\n```\nThis matches mapping rules whose <code>mappingRuleId</code> is <em>rule-1</em> or <em>rule-2</em>.\n<br>\n<p>Note: Using complex <code>$or</code> conditions may impact performance, use with caution in high-volume environments.\n'
3725
- }).optional()
3721
+ $or: z.array(zMappingRuleFilterFields).nullish()
3726
3722
  }));
3727
3723
  var zMessageCorrelationRequest = z.object({
3728
3724
  name: z.string().register(z.globalRegistry, {
@@ -3856,9 +3852,7 @@ var zCorrelatedMessageSubscriptionResult = z.object({
3856
3852
  correlationTime: z.iso.datetime().register(z.globalRegistry, {
3857
3853
  description: "The time when the message was correlated."
3858
3854
  }),
3859
- elementId: z.string().register(z.globalRegistry, {
3860
- description: "The element ID that received the message."
3861
- }),
3855
+ elementId: zElementId,
3862
3856
  elementInstanceKey: zElementInstanceKey.nullable(),
3863
3857
  messageKey: zMessageKey,
3864
3858
  messageName: z.string().register(z.globalRegistry, {
@@ -4406,9 +4400,7 @@ var zRoleFilterFields = z.object({
4406
4400
  description: "Role filter request"
4407
4401
  });
4408
4402
  var zRoleFilter = zRoleFilterFields.and(z.object({
4409
- $or: z.array(zRoleFilterFields).register(z.globalRegistry, {
4410
- description: 'Defines a list of alternative filter groups combined using OR logic. Each object in the array is evaluated independently, and the filter matches if any one of them is satisfied.\n\nTop-level fields and the `$or` clause are combined using AND logic \u2014 meaning: (top-level filters) AND (any of the `$or` filters) must match.\n<br>\n<em>Example:</em>\n\n```json\n{\n "name": "Admin",\n "$or": [\n { "roleId": "role-1" },\n { "roleId": "role-2" }\n ]\n}\n```\nThis matches roles that:\n\n<ul style="padding-left: 20px; margin-left: 20px;">\n <li style="list-style-type: disc;">have name equal to <em>Admin</em></li>\n <li style="list-style-type: disc;">and match either:\n <ul style="padding-left: 20px; margin-left: 20px;">\n <li style="list-style-type: circle;"><code>roleId</code> is <em>role-1</em>, or</li>\n <li style="list-style-type: circle;"><code>roleId</code> is <em>role-2</em></li>\n </ul>\n </li>\n</ul>\n<br>\n<p>Note: Using complex <code>$or</code> conditions may impact performance, use with caution in high-volume environments.\n'
4411
- }).optional()
4403
+ $or: z.array(zRoleFilterFields).nullish()
4412
4404
  }));
4413
4405
  var zRoleUserResult = z.object({
4414
4406
  username: zUsername
@@ -5825,9 +5817,7 @@ var zUserFilterFields = z.object({
5825
5817
  description: "User search filter fields."
5826
5818
  });
5827
5819
  var zUserFilter = zUserFilterFields.and(z.object({
5828
- $or: z.array(zUserFilterFields).register(z.globalRegistry, {
5829
- description: 'Defines a list of alternative filter groups combined using OR logic. Each object in the array is evaluated independently, and the filter matches if any one of them is satisfied.\n\nTop-level fields and the `$or` clause are combined using AND logic \u2014 meaning: (top-level filters) AND (any of the `$or` filters) must match.\n<br>\n<em>Example:</em>\n\n```json\n{\n "$or": [\n { "username": "user-1" },\n { "username": "user-2" }\n ]\n}\n```\nThis matches users whose <code>username</code> is <em>user-1</em> or <em>user-2</em>.\n<br>\n<p>Note: Using complex <code>$or</code> conditions may impact performance, use with caution in high-volume environments.\n'
5830
- }).optional()
5820
+ $or: z.array(zUserFilterFields).nullish()
5831
5821
  }));
5832
5822
  var zUserSearchQueryRequest = zSearchQueryRequest.and(z.object({
5833
5823
  sort: z.array(zUserSearchQuerySortRequest).register(z.globalRegistry, {
@@ -9516,4 +9506,4 @@ export {
9516
9506
  zWaitStateTypeFilterProperty,
9517
9507
  zWebappComponent
9518
9508
  };
9519
- //# sourceMappingURL=zod.gen-SZTQQ6VL.js.map
9509
+ //# sourceMappingURL=zod.gen-A3RZUVR4.js.map