ArchitecturePins

Execution Pin

Execution pins control workflow flow in trigger and callable nodes. They determine when and which nodes execute next, enabling conditional logic, loops, and branching patterns.

Key Characteristics

  • Flow Control: Determine execution order and branching
  • Trigger & Callable Only: Not available in pure nodes
  • Scoped Outputs: Can have their own data outputs
  • Conditional Logic: Enable if/else and switch-like patterns

Basic Usage

import * as i from '@xentom/integration-framework';

// Simple execution pin
i.pins.exec();

// With display name
i.pins.exec({
  displayName: 'Success',
  description: 'Executed when operation succeeds',
});

// With scoped outputs
i.pins.exec({
  displayName: 'For Each Item',
  outputs: {
    item: i.pins.data(),
    index: i.pins.data(),
  },
});

Simple Examples

Conditional Branching

validateUser: i.nodes.callable({
  inputs: {
    email: i.pins.data({ control: i.controls.text() }),
  },

  outputs: {
    valid: i.pins.exec({
      outputs: { user: i.pins.data() },
    }),
    invalid: i.pins.exec({
      outputs: { error: i.pins.data() },
    }),
  },

  run({ inputs, next }) {
    if (inputs.email.includes('@')) {
      next('valid', { user: { email: inputs.email } });
    } else {
      next('invalid', { error: 'Invalid email' });
    }
  },
});

Loop Processing

processItems: i.nodes.callable({
  inputs: {
    items: i.pins.data({ control: i.controls.expression() }),
  },

  outputs: {
    forEach: i.pins.exec({
      outputs: {
        item: i.pins.data(),
        index: i.pins.data(),
      },
    }),
    completed: i.pins.exec({
      outputs: { count: i.pins.data() },
    }),
  },

  run({ inputs, next }) {
    inputs.items.forEach((item, index) => {
      next('forEach', { item, index });
    });

    next('completed', { count: inputs.items.length });
  },
});

Trigger with Conditions

export const onWebhook = i.nodes.trigger({
  outputs: {
    userEvent: i.pins.exec({
      outputs: { user: i.pins.data() },
    }),
    orderEvent: i.pins.exec({
      outputs: { order: i.pins.data() },
    }),
  },

  subscribe({ next, webhook }) {
    return webhook.subscribe(async (req) => {
      const data = await req.json();

      if (data.type === 'user') {
        next('userEvent', { user: data });
      } else if (data.type === 'order') {
        next('orderEvent', { order: data });
      }

      return new Response('OK');
    });
  },
});

Best Practices

Clear Names

// Good
outputs: {
  validationPassed: i.pins.exec(),
  validationFailed: i.pins.exec()
}

// Avoid
outputs: {
  success: i.pins.exec(),
  failure: i.pins.exec()
}

Meaningful Outputs

// Good - Include relevant context
outputs: {
  userCreated: i.pins.exec({
    outputs: {
      user: i.pins.data(),
      id: i.pins.data(),
      timestamp: i.pins.data(),
    },
  });
}

Handle All Cases

// Good - Cover expected outcomes
outputs: {
  success: i.pins.exec(),
  notFound: i.pins.exec(),
  unauthorized: i.pins.exec(),
  serverError: i.pins.exec()
}

Execution pins enable sophisticated workflow patterns while maintaining visual clarity in the workflow editor.

On this page