2024-10-07 11:18:32 -07:00
|
|
|
import {
|
2024-10-10 11:01:38 -07:00
|
|
|
ApplicationError,
|
2024-10-07 11:18:32 -07:00
|
|
|
type CodeExecutionMode,
|
|
|
|
type IExecuteFunctions,
|
|
|
|
type INodeExecutionData,
|
|
|
|
type WorkflowExecuteMode,
|
|
|
|
} from 'n8n-workflow';
|
|
|
|
|
2024-10-10 11:01:38 -07:00
|
|
|
import { isWrappableError, WrappedExecutionError } from './errors/WrappedExecutionError';
|
|
|
|
import { validateNoDisallowedMethodsInRunForEach } from './JsCodeValidator';
|
2024-10-07 11:18:32 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* JS Code execution sandbox that executes the JS code using task runner.
|
|
|
|
*/
|
|
|
|
export class JsTaskRunnerSandbox {
|
|
|
|
constructor(
|
|
|
|
private readonly jsCode: string,
|
|
|
|
private readonly nodeMode: CodeExecutionMode,
|
|
|
|
private readonly workflowMode: WorkflowExecuteMode,
|
|
|
|
private readonly executeFunctions: IExecuteFunctions,
|
|
|
|
) {}
|
|
|
|
|
|
|
|
async runCodeAllItems(): Promise<INodeExecutionData[]> {
|
|
|
|
const itemIndex = 0;
|
|
|
|
|
2024-10-10 11:01:38 -07:00
|
|
|
const executionResult = await this.executeFunctions.startJob<INodeExecutionData[]>(
|
|
|
|
'javascript',
|
|
|
|
{
|
|
|
|
code: this.jsCode,
|
|
|
|
nodeMode: this.nodeMode,
|
|
|
|
workflowMode: this.workflowMode,
|
|
|
|
continueOnFail: this.executeFunctions.continueOnFail(),
|
|
|
|
},
|
|
|
|
itemIndex,
|
|
|
|
);
|
2024-10-07 11:18:32 -07:00
|
|
|
|
2024-10-10 11:01:38 -07:00
|
|
|
return executionResult.ok
|
|
|
|
? executionResult.result
|
|
|
|
: this.throwExecutionError(executionResult.error);
|
2024-10-07 11:18:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async runCodeForEachItem(): Promise<INodeExecutionData[]> {
|
|
|
|
validateNoDisallowedMethodsInRunForEach(this.jsCode, 0);
|
|
|
|
const itemIndex = 0;
|
|
|
|
|
2024-10-10 11:01:38 -07:00
|
|
|
const executionResult = await this.executeFunctions.startJob<INodeExecutionData[]>(
|
|
|
|
'javascript',
|
|
|
|
{
|
|
|
|
code: this.jsCode,
|
|
|
|
nodeMode: this.nodeMode,
|
|
|
|
workflowMode: this.workflowMode,
|
|
|
|
continueOnFail: this.executeFunctions.continueOnFail(),
|
|
|
|
},
|
|
|
|
itemIndex,
|
|
|
|
);
|
|
|
|
|
|
|
|
return executionResult.ok
|
|
|
|
? executionResult.result
|
|
|
|
: this.throwExecutionError(executionResult.error);
|
|
|
|
}
|
|
|
|
|
|
|
|
private throwExecutionError(error: unknown): never {
|
2024-10-29 03:39:31 -07:00
|
|
|
if (error instanceof Error) {
|
|
|
|
throw error;
|
|
|
|
} else if (isWrappableError(error)) {
|
|
|
|
// The error coming from task runner is not an instance of error,
|
|
|
|
// so we need to wrap it in an error instance.
|
2024-10-10 11:01:38 -07:00
|
|
|
throw new WrappedExecutionError(error);
|
|
|
|
}
|
2024-10-07 11:18:32 -07:00
|
|
|
|
2024-10-23 02:13:09 -07:00
|
|
|
throw new ApplicationError(`Unknown error: ${JSON.stringify(error)}`);
|
2024-10-07 11:18:32 -07:00
|
|
|
}
|
|
|
|
}
|