@meetploy/emulator 1.13.1 → 1.14.1

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.
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Ploy Dev Dashboard</title>
7
- <script type="module" crossorigin src="/assets/main-DKimSd85.js"></script>
7
+ <script type="module" crossorigin src="/assets/main-DTpABleT.js"></script>
8
8
  <link rel="stylesheet" crossorigin href="/assets/main-kKaL2zMb.css">
9
9
  </head>
10
10
  <body>
@@ -1 +1 @@
1
- export declare const WORKFLOW_RUNTIME_CODE = "\ninterface WorkflowExecution {\n id: string;\n status: \"pending\" | \"running\" | \"completed\" | \"failed\" | \"cancelled\";\n result?: unknown;\n error?: string;\n}\n\ninterface Workflow<TInput = unknown> {\n trigger: (input: TInput) => Promise<{ executionId: string }>;\n getExecution: (executionId: string) => Promise<WorkflowExecution>;\n cancel: (executionId: string) => Promise<void>;\n}\n\nexport function initializeWorkflow<TInput = unknown>(\n workflowName: string,\n serviceUrl: string\n): Workflow<TInput> {\n return {\n async trigger(input: TInput): Promise<{ executionId: string }> {\n const response = await fetch(serviceUrl + \"/workflow/trigger\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ workflowName, input }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\"Workflow trigger failed: \" + errorText);\n }\n\n const result = await response.json();\n if (!result.success) {\n throw new Error(result.error || \"Workflow trigger failed\");\n }\n\n return { executionId: result.executionId };\n },\n\n async getExecution(executionId: string): Promise<WorkflowExecution> {\n const response = await fetch(serviceUrl + \"/workflow/status\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ executionId }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\"Workflow status failed: \" + errorText);\n }\n\n const result = await response.json();\n if (!result.success) {\n throw new Error(result.error || \"Workflow status failed\");\n }\n\n const exec = result.execution;\n return {\n id: exec.id,\n status: exec.status,\n result: exec.output,\n error: exec.error,\n };\n },\n\n async cancel(executionId: string): Promise<void> {\n const response = await fetch(serviceUrl + \"/workflow/cancel\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ executionId }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\"Workflow cancel failed: \" + errorText);\n }\n\n const result = await response.json();\n if (!result.success) {\n throw new Error(result.error || \"Workflow cancel failed\");\n }\n },\n };\n}\n\ninterface WorkflowStepContext {\n run: <T>(stepName: string, fn: () => T | Promise<T>, options?: { retries?: number }) => Promise<T>;\n sleep: (durationMs: number) => Promise<void>;\n}\n\ninterface WorkflowContext<TInput = unknown, TEnv = unknown> {\n input: TInput;\n env: TEnv;\n step: WorkflowStepContext;\n}\n\nexport function createStepContext(executionId: string, serviceUrl: string): WorkflowStepContext {\n let stepIndex = 0;\n\n return {\n async run<T>(stepName: string, fn: () => T | Promise<T>, options?: { retries?: number }): Promise<T> {\n const currentStepIndex = stepIndex++;\n const maxRetries = options?.retries ?? 0;\n\n const startResponse = await fetch(serviceUrl + \"/workflow/step/start\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ executionId, stepName, stepIndex: currentStepIndex }),\n });\n\n if (!startResponse.ok) {\n const errorText = await startResponse.text();\n throw new Error(\"Failed to start step: \" + errorText);\n }\n\n const startResult = await startResponse.json();\n\n if (startResult.alreadyCompleted) {\n return startResult.output as T;\n }\n\n const startTime = Date.now();\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const result = await fn();\n const durationMs = Date.now() - startTime;\n\n await fetch(serviceUrl + \"/workflow/step/complete\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ executionId, stepName, output: result, durationMs }),\n });\n\n return result;\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n if (attempt < maxRetries) {\n await new Promise((resolve) => setTimeout(resolve, Math.min(1000 * Math.pow(2, attempt), 30000)));\n }\n }\n }\n\n const durationMs = Date.now() - startTime;\n await fetch(serviceUrl + \"/workflow/step/fail\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ executionId, stepName, error: lastError?.message || \"Step execution failed\", durationMs }),\n });\n\n throw lastError;\n },\n\n async sleep(durationMs: number): Promise<void> {\n const stepName = \"__sleep_\" + stepIndex++;\n\n await fetch(serviceUrl + \"/workflow/step/start\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ executionId, stepName, stepIndex: stepIndex - 1 }),\n });\n\n await new Promise((resolve) => setTimeout(resolve, durationMs));\n\n await fetch(serviceUrl + \"/workflow/step/complete\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ executionId, stepName, output: { sleptMs: durationMs }, durationMs }),\n });\n },\n };\n}\n\nexport async function executeWorkflow<TInput, TOutput, TEnv>(\n executionId: string,\n workflowFn: (context: WorkflowContext<TInput, TEnv>) => Promise<TOutput>,\n input: TInput,\n env: TEnv,\n serviceUrl: string\n): Promise<TOutput> {\n const step = createStepContext(executionId, serviceUrl);\n const context: WorkflowContext<TInput, TEnv> = { input, env, step };\n\n try {\n const output = await workflowFn(context);\n\n await fetch(serviceUrl + \"/workflow/complete\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ executionId, output }),\n });\n\n return output;\n } catch (error) {\n await fetch(serviceUrl + \"/workflow/fail\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ executionId, error: error instanceof Error ? error.message : String(error) }),\n });\n\n throw error;\n }\n}\n";
1
+ export declare const WORKFLOW_RUNTIME_CODE = "\ninterface WorkflowExecution {\n id: string;\n status: \"pending\" | \"running\" | \"completed\" | \"failed\" | \"cancelled\";\n result?: unknown;\n error?: string;\n}\n\ninterface Workflow<TInput = unknown> {\n trigger: (input: TInput) => Promise<{ executionId: string }>;\n getExecution: (executionId: string) => Promise<WorkflowExecution>;\n cancel: (executionId: string) => Promise<void>;\n}\n\nexport function initializeWorkflow<TInput = unknown>(\n workflowName: string,\n serviceUrl: string\n): Workflow<TInput> {\n return {\n async trigger(input: TInput): Promise<{ executionId: string }> {\n const response = await fetch(serviceUrl + \"/workflow/trigger\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ workflowName, input }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\"Workflow trigger failed: \" + errorText);\n }\n\n const result = await response.json();\n if (!result.success) {\n throw new Error(result.error || \"Workflow trigger failed\");\n }\n\n return { executionId: result.executionId };\n },\n\n async getExecution(executionId: string): Promise<WorkflowExecution> {\n const response = await fetch(serviceUrl + \"/workflow/status\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ executionId }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\"Workflow status failed: \" + errorText);\n }\n\n const result = await response.json();\n if (!result.success) {\n throw new Error(result.error || \"Workflow status failed\");\n }\n\n const exec = result.execution;\n return {\n id: exec.id,\n status: exec.status,\n result: exec.output,\n error: exec.error,\n };\n },\n\n async cancel(executionId: string): Promise<void> {\n const response = await fetch(serviceUrl + \"/workflow/cancel\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ executionId }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\"Workflow cancel failed: \" + errorText);\n }\n\n const result = await response.json();\n if (!result.success) {\n throw new Error(result.error || \"Workflow cancel failed\");\n }\n },\n };\n}\n\ninterface WorkflowStepContext {\n run: <T>(stepName: string, fn: () => T | Promise<T>, options?: { retries?: number }) => Promise<T>;\n sleep: (durationMs: number) => Promise<void>;\n}\n\ninterface WorkflowContext<TInput = unknown, TEnv = unknown> {\n input: TInput;\n env: TEnv;\n step: WorkflowStepContext;\n}\n\nexport function createStepContext(executionId: string, serviceUrl: string): WorkflowStepContext {\n let stepIndex = 0;\n\n return {\n async run<T>(stepName: string, fn: () => T | Promise<T>, options?: { retries?: number }): Promise<T> {\n const currentStepIndex = stepIndex++;\n const maxRetries = options?.retries ?? 0;\n\n const startResponse = await fetch(serviceUrl + \"/workflow/step/start\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ executionId, stepName, stepIndex: currentStepIndex }),\n });\n\n if (!startResponse.ok) {\n const errorText = await startResponse.text();\n throw new Error(\"Failed to start step: \" + errorText);\n }\n\n const startResult = await startResponse.json();\n\n if (startResult.alreadyCompleted) {\n return startResult.output as T;\n }\n\n const startTime = Date.now();\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const result = await fn();\n const durationMs = Date.now() - startTime;\n\n await fetch(serviceUrl + \"/workflow/step/complete\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ executionId, stepName, output: result, durationMs }),\n });\n\n return result;\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n if (attempt < maxRetries) {\n await new Promise((resolve) => setTimeout(resolve, Math.min(1000 * Math.pow(2, attempt), 30000)));\n }\n }\n }\n\n const durationMs = Date.now() - startTime;\n await fetch(serviceUrl + \"/workflow/step/fail\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ executionId, stepName, error: lastError?.message || \"Step execution failed\", durationMs }),\n });\n\n throw lastError;\n },\n\n async sleep(durationMs: number): Promise<void> {\n const stepName = \"__sleep_\" + stepIndex++;\n\n await fetch(serviceUrl + \"/workflow/step/start\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ executionId, stepName, stepIndex: stepIndex - 1 }),\n });\n\n await new Promise((resolve) => setTimeout(resolve, durationMs));\n\n await fetch(serviceUrl + \"/workflow/step/complete\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ executionId, stepName, output: { sleptMs: durationMs }, durationMs }),\n });\n },\n };\n}\n\nexport async function executeWorkflow<TInput, TOutput, TEnv>(\n executionId: string,\n workflowFn: (context: WorkflowContext<TInput, TEnv>) => Promise<TOutput>,\n input: TInput,\n env: TEnv,\n serviceUrl: string,\n onError?: (error: Error, context: WorkflowContext<TInput, TEnv>) => Promise<void>\n): Promise<TOutput> {\n const step = createStepContext(executionId, serviceUrl);\n const context: WorkflowContext<TInput, TEnv> = { input, env, step };\n\n try {\n const output = await workflowFn(context);\n\n await fetch(serviceUrl + \"/workflow/complete\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ executionId, output }),\n });\n\n return output;\n } catch (error) {\n if (onError) {\n try {\n const err = error instanceof Error ? error : new Error(String(error));\n await onError(err, context);\n } catch (onErrorError) {\n console.error(\"Workflow onError handler threw:\", onErrorError);\n }\n }\n\n await fetch(serviceUrl + \"/workflow/fail\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ executionId, error: error instanceof Error ? error.message : String(error) }),\n });\n\n throw error;\n }\n}\n";
@@ -177,7 +177,8 @@ export async function executeWorkflow<TInput, TOutput, TEnv>(
177
177
  workflowFn: (context: WorkflowContext<TInput, TEnv>) => Promise<TOutput>,
178
178
  input: TInput,
179
179
  env: TEnv,
180
- serviceUrl: string
180
+ serviceUrl: string,
181
+ onError?: (error: Error, context: WorkflowContext<TInput, TEnv>) => Promise<void>
181
182
  ): Promise<TOutput> {
182
183
  const step = createStepContext(executionId, serviceUrl);
183
184
  const context: WorkflowContext<TInput, TEnv> = { input, env, step };
@@ -193,6 +194,15 @@ export async function executeWorkflow<TInput, TOutput, TEnv>(
193
194
 
194
195
  return output;
195
196
  } catch (error) {
197
+ if (onError) {
198
+ try {
199
+ const err = error instanceof Error ? error : new Error(String(error));
200
+ await onError(err, context);
201
+ } catch (onErrorError) {
202
+ console.error("Workflow onError handler threw:", onErrorError);
203
+ }
204
+ }
205
+
196
206
  await fetch(serviceUrl + "/workflow/fail", {
197
207
  method: "POST",
198
208
  headers: { "Content-Type": "application/json" },
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-runtime.js","sourceRoot":"","sources":["../../src/runtime/workflow-runtime.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4MpC,CAAC"}
1
+ {"version":3,"file":"workflow-runtime.js","sourceRoot":"","sources":["../../src/runtime/workflow-runtime.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsNpC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meetploy/emulator",
3
- "version": "1.13.1",
3
+ "version": "1.14.1",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",