2023-01-27 03:22:44 -08:00
import type {
2022-10-13 05:28:02 -07:00
IExecuteFunctions ,
INodeExecutionData ,
INodeType ,
INodeTypeDescription ,
} from 'n8n-workflow' ;
import { getSandboxContext , Sandbox } from './Sandbox' ;
import { standardizeOutput } from './utils' ;
import type { CodeNodeMode } from './utils' ;
export class Code implements INodeType {
description : INodeTypeDescription = {
displayName : 'Code' ,
name : 'code' ,
icon : 'fa:code' ,
group : [ 'transform' ] ,
version : 1 ,
description : 'Run custom JavaScript code' ,
defaults : {
name : 'Code' ,
color : '#FF9922' ,
} ,
inputs : [ 'main' ] ,
outputs : [ 'main' ] ,
parameterPane : 'wide' ,
properties : [
{
displayName : 'Mode' ,
name : 'mode' ,
type : 'options' ,
noDataExpression : true ,
options : [
{
name : 'Run Once for All Items' ,
value : 'runOnceForAllItems' ,
description : 'Run this code only once, no matter how many input items there are' ,
} ,
{
name : 'Run Once for Each Item' ,
value : 'runOnceForEachItem' ,
description : 'Run this code as many times as there are input items' ,
} ,
] ,
default : 'runOnceForAllItems' ,
} ,
{
displayName : 'JavaScript' ,
name : 'jsCode' ,
typeOptions : {
editor : 'codeNodeEditor' ,
} ,
type : 'string' ,
default : '' , // set by component
description :
'JavaScript code to execute.<br><br>Tip: You can use luxon vars like <code>$today</code> for dates and <code>$jmespath</code> for querying JSON structures. <a href="https://docs.n8n.io/nodes/n8n-nodes-base.function">Learn more</a>.' ,
noDataExpression : true ,
} ,
{
displayName :
'Type <code>$</code> for a list of <a target="_blank" href="https://docs.n8n.io/code-examples/methods-variables-reference/">special vars/methods</a>. Debug by using <code>console.log()</code> statements and viewing their output in the browser console.' ,
name : 'notice' ,
type : 'notice' ,
default : '' ,
} ,
] ,
} ;
async execute ( this : IExecuteFunctions ) {
const nodeMode = this . getNodeParameter ( 'mode' , 0 ) as CodeNodeMode ;
const workflowMode = this . getMode ( ) ;
// ----------------------------------
// runOnceForAllItems
// ----------------------------------
if ( nodeMode === 'runOnceForAllItems' ) {
const jsCodeAllItems = this . getNodeParameter ( 'jsCode' , 0 ) as string ;
const context = getSandboxContext . call ( this ) ;
2022-11-10 07:29:41 -08:00
context . items = context . $input . all ( ) ;
2023-04-19 04:09:46 -07:00
const sandbox = new Sandbox ( context , jsCodeAllItems , workflowMode , this . helpers ) ;
2022-10-13 05:28:02 -07:00
if ( workflowMode === 'manual' ) {
sandbox . on ( 'console.log' , this . sendMessageToUI ) ;
}
2023-04-19 04:09:46 -07:00
let result : INodeExecutionData [ ] ;
2022-10-13 05:28:02 -07:00
try {
2023-04-19 04:09:46 -07:00
result = await sandbox . runCodeAllItems ( ) ;
2022-10-13 05:28:02 -07:00
} catch ( error ) {
if ( ! this . continueOnFail ( ) ) return Promise . reject ( error ) ;
2023-04-19 04:09:46 -07:00
result = [ { json : { error : error.message } } ] ;
2022-10-13 05:28:02 -07:00
}
2023-04-19 04:09:46 -07:00
for ( const item of result ) {
2022-10-13 05:28:02 -07:00
standardizeOutput ( item . json ) ;
}
2023-04-19 04:09:46 -07:00
return this . prepareOutputData ( result ) ;
2022-10-13 05:28:02 -07:00
}
// ----------------------------------
// runOnceForEachItem
// ----------------------------------
const returnData : INodeExecutionData [ ] = [ ] ;
2023-04-19 04:09:46 -07:00
const items = this . getInputData ( ) ;
2022-10-13 05:28:02 -07:00
2023-04-19 04:09:46 -07:00
for ( let index = 0 ; index < items . length ; index ++ ) {
2022-10-13 05:28:02 -07:00
const jsCodeEachItem = this . getNodeParameter ( 'jsCode' , index ) as string ;
const context = getSandboxContext . call ( this , index ) ;
2022-11-10 07:29:41 -08:00
context . item = context . $input . item ;
2023-04-19 04:09:46 -07:00
const sandbox = new Sandbox ( context , jsCodeEachItem , workflowMode , this . helpers ) ;
2022-10-13 05:28:02 -07:00
if ( workflowMode === 'manual' ) {
sandbox . on ( 'console.log' , this . sendMessageToUI ) ;
}
2023-04-19 04:09:46 -07:00
let result : INodeExecutionData | undefined ;
2022-10-13 05:28:02 -07:00
try {
2023-04-19 04:09:46 -07:00
result = await sandbox . runCodeEachItem ( index ) ;
2022-10-13 05:28:02 -07:00
} catch ( error ) {
if ( ! this . continueOnFail ( ) ) return Promise . reject ( error ) ;
returnData . push ( { json : { error : error.message } } ) ;
}
2023-04-19 04:09:46 -07:00
if ( result ) {
2022-10-13 05:28:02 -07:00
returnData . push ( {
2023-04-19 04:09:46 -07:00
json : standardizeOutput ( result . json ) ,
2022-10-13 05:28:02 -07:00
pairedItem : { item : index } ,
2023-04-19 04:09:46 -07:00
. . . ( result . binary && { binary : result.binary } ) ,
2022-10-13 05:28:02 -07:00
} ) ;
}
}
return this . prepareOutputData ( returnData ) ;
}
}