2023-01-27 03:22:44 -08:00
import type { IExecuteFunctions } from 'n8n-core' ;
import type {
2022-12-09 04:39:06 -08:00
INodeExecutionData ,
INodeType ,
INodeTypeDescription ,
IPairedItemData ,
} from 'n8n-workflow' ;
2023-01-27 03:22:44 -08:00
import { deepCopy } from 'n8n-workflow' ;
2019-06-23 03:35:23 -07:00
export class SplitInBatches implements INodeType {
description : INodeTypeDescription = {
displayName : 'Split In Batches' ,
name : 'splitInBatches' ,
2019-07-26 02:27:46 -07:00
icon : 'fa:th-large' ,
2019-06-23 03:35:23 -07:00
group : [ 'organization' ] ,
version : 1 ,
2021-07-03 05:40:16 -07:00
description : 'Split data into batches and iterate over each batch' ,
2019-06-23 03:35:23 -07:00
defaults : {
feat(editor): Node creator actions (#4696)
* WIP: Node Actions List UI
* WIP: Recommended Actions and preseting of fields
* WIP: Resource category
* :art: Moved actions categorisation to the server
* :label: Add missing INodeAction type
* :sparkles: Improve SSR categorisation, fix adding of mixed actions
* :recycle: Refactor CategorizedItems to composition api, style fixes
* WIP: Adding multiple nodes
* :recycle: Refactor rest of the NodeCreator component to composition API, conver globalLinkActions to composable
* :sparkles: Allow actions dragging, fix search and refactor passing of actions to categorized items
* :lipstick: Fix node actions title
* Migrate to the pinia store, add posthog feature and various fixes
* :bug: Fix filtering of trigger actions when not merged
* fix: N8N-5439 — Do not use simple node item when at NodeHelperPanel root
* :bug: Design review fixes
* :bug: Fix disabling of merged actions
* Fix trigger root filtering
* :sparkles: Allow for custom node actions parser, introduce hubspot parser
* :bug: Fix initial node params validation, fix position of second added node
* :bug: Introduce operations category, removed canvas node names overrride, fix API actions display and prevent dragging of action nodes
* :sparkles: Prevent NDV auto-open feature flag
* :bug: Inject recommened action for trigger nodes without actions
* Refactored NodeCreatorNode to Storybook, change filtering of merged nodes for the trigger helper panel, minor fixes
* Improve rendering of app nodes and animation
* Cleanup, any only enable accordion transition on triggerhelperpanel
* Hide node creator scrollbars in Firefox
* Minor styles fixes
* Do not copy the array in rendering method
* Removed unused props
* Fix memory leak
* Fix categorisation of regular nodes with a single resource
* Implement telemetry calls for node actions
* Move categorization to FE
* Fix client side actions categorisation
* Skip custom action show
* Only load tooltip for NodeIcon if necessary
* Fix lodash startCase import
* Remove lodash.startcase
* Cleanup
* Fix node creator autofocus on "tab"
* Prevent posthog getFeatureFlag from crashing
* Debugging preview env search issues
* Remove logs
* Make sure the pre-filled params are update not overwritten
* Get rid of transition in itemiterator
* WIP: Rough version of NodeActions keyboard navigation, replace nodeCreator composable with Pinia store module
* Rewrite to add support for ActionItem to ItemIterator and make CategorizedItems accept items props
* Fix category item counter & cleanup
* Add APIHint to actions search no-result, clean up NodeCreatorNode
* Improve node actions no results message
* Remove logging, fix filtering of recommended placeholder category
* Remove unused NodeActions component and node merging feature falg
* Do not show regular nodes without actions
* Make sure to add manual trigger when adding http node via actions hint
* Fixed api hint footer line height
* Prevent pointer-events od NodeIcon img and remove "this" from template
* Address PR points
* Fix e2e specs
* Make sure canvas ia loaded
* Make sure canvas ia loaded before opening nodeCreator in e2e spec
* Fix flaky workflows tags e2e getter
* Imrpove node creator click outside UX, add manual node to regular nodes added from trigger panel
* Add manual trigger node if dragging regular from trigger panel
2022-12-09 01:56:36 -08:00
name : 'Split In Batches' ,
2019-06-23 03:35:23 -07:00
color : '#007755' ,
} ,
inputs : [ 'main' ] ,
outputs : [ 'main' ] ,
properties : [
2021-09-19 07:13:48 -07:00
{
2022-08-17 08:50:24 -07:00
displayName :
'You may not need this node — n8n nodes automatically run once for each input item. <a href="https://docs.n8n.io/getting-started/key-concepts/looping.html#using-loops-in-n8n" target="_blank">More info</a>' ,
2021-09-19 07:13:48 -07:00
name : 'splitInBatchesNotice' ,
type : 'notice' ,
default : '' ,
} ,
2019-06-23 03:35:23 -07:00
{
displayName : 'Batch Size' ,
name : 'batchSize' ,
type : 'number' ,
typeOptions : {
minValue : 1 ,
} ,
default : 10 ,
2022-05-06 14:01:25 -07:00
description : 'The number of items to return with each call' ,
2019-06-23 03:35:23 -07:00
} ,
2020-04-08 04:24:49 -07:00
{
displayName : 'Options' ,
name : 'options' ,
type : 'collection' ,
placeholder : 'Add Option' ,
default : { } ,
options : [
{
displayName : 'Reset' ,
name : 'reset' ,
type : 'boolean' ,
default : false ,
2022-08-17 08:50:24 -07:00
description :
'Whether the node will be reset and so with the current input-data newly initialized' ,
2020-04-08 04:24:49 -07:00
} ,
] ,
} ,
2019-06-23 03:35:23 -07:00
] ,
} ;
async execute ( this : IExecuteFunctions ) : Promise < INodeExecutionData [ ] [ ] | null > {
2019-08-01 13:55:33 -07:00
// Get the input data and create a new array so that we can remove
// items without a problem
const items = this . getInputData ( ) . slice ( ) ;
2019-06-23 03:35:23 -07:00
const nodeContext = this . getContext ( 'node' ) ;
const batchSize = this . getNodeParameter ( 'batchSize' , 0 ) as number ;
const returnItems : INodeExecutionData [ ] = [ ] ;
2022-12-02 12:54:28 -08:00
const options = this . getNodeParameter ( 'options' , 0 , { } ) ;
2020-04-08 04:24:49 -07:00
if ( nodeContext . items === undefined || options . reset === true ) {
2019-06-23 03:35:23 -07:00
// Is the first time the node runs
2022-12-09 04:39:06 -08:00
const sourceData = this . getInputSourceData ( ) ;
2019-06-23 03:35:23 -07:00
nodeContext . currentRunIndex = 0 ;
nodeContext . maxRunIndex = Math . ceil ( items . length / batchSize ) ;
2022-12-09 04:39:06 -08:00
nodeContext . sourceData = deepCopy ( sourceData ) ;
2019-06-23 03:35:23 -07:00
// Get the items which should be returned
returnItems . push . apply ( returnItems , items . splice ( 0 , batchSize ) ) ;
// Set the other items to be saved in the context to return at later runs
2022-12-09 04:39:06 -08:00
nodeContext . items = [ . . . items ] ;
2020-04-08 04:24:49 -07:00
} else {
2019-06-23 03:35:23 -07:00
// The node has been called before. So return the next batch of items.
nodeContext . currentRunIndex += 1 ;
returnItems . push . apply ( returnItems , nodeContext . items . splice ( 0 , batchSize ) ) ;
2022-12-09 04:39:06 -08:00
const addSourceOverwrite = ( pairedItem : IPairedItemData | number ) : IPairedItemData = > {
if ( typeof pairedItem === 'number' ) {
return {
item : pairedItem ,
sourceOverwrite : nodeContext.sourceData ,
} ;
}
return {
. . . pairedItem ,
sourceOverwrite : nodeContext.sourceData ,
} ;
} ;
function getPairedItemInformation (
item : INodeExecutionData ,
) : IPairedItemData | IPairedItemData [ ] {
if ( item . pairedItem === undefined ) {
return {
item : 0 ,
sourceOverwrite : nodeContext.sourceData ,
} ;
}
if ( Array . isArray ( item . pairedItem ) ) {
return item . pairedItem . map ( addSourceOverwrite ) ;
}
return addSourceOverwrite ( item . pairedItem ) ;
}
returnItems . map ( ( item ) = > {
item . pairedItem = getPairedItemInformation ( item ) ;
} ) ;
2019-06-23 03:35:23 -07:00
}
nodeContext . noItemsLeft = nodeContext . items . length === 0 ;
if ( returnItems . length === 0 ) {
// No data left to return so stop execution of the branch
return null ;
}
2022-12-09 04:39:06 -08:00
return [ returnItems ] ;
2019-06-23 03:35:23 -07:00
}
}