Git Product home page Git Product logo

connector-sdk-nodejs's Introduction

Camunda 8 Connector SDK for Node.js

Compatible with: Camunda Platform 8

Note: This is EXPERIMENTAL. The official Camunda (Java) SDK is still in active development, and this community SDK follows it.

This a community project - a pure Node.js implementation of the official Camunda 8 Connector SDK. It is designed to follow the official Java SDK API ergonomics as closely as possible.

Supports secret replacement and non-nullable (required) input process variables.

For a tutorial in using this SDK to write a connector for Camunda 8, see this article.

Outbound Connector

To create an outbound connector:

Scaffold a new project and add the Node.js Connector SDK:

mkdir my-outbound-connector
cd my-outbound-connector
npm init --yes
tsc --init
npm i camunda-connector-sdk

Edit the tsconfig.json and enable the following two options:

"experimentalDecorators": true,                
"emitDecoratorMetadata": true,       

Here is an example Outbound connector:

import {
    BPMNError,
    Secret,
    OutboundConnector,
    OutboundConnectorFunction,
    OutboundConnectorContext,
    NotNull
} from 'camunda-connector-sdk'

class myDTO {
    @NotNull @Secret auth!: string
    @NotNull lat!: string
    @NotNull long!: string
    mightbe?: number
}

@OutboundConnector({
    name: "Test Connector",
    type: "io.camunda:connector-1",
    inputVariables: ["auth", "lat", "long", "mightbe"]
})
export class MyConnector implements OutboundConnectorFunction {
    async execute(context: OutboundConnectorContext) {
        const vars = context.getVariablesAsType(myDTO)
        context.validate(vars)
        context.replaceSecrets(vars)

        try {
            const outcome = await this.businessLogic(vars)
            
            // How to signal success, failure, or error

            if (outcome.status === 'OK') {
                // any return value is added to the process variables
                return { result: outcome.result }
            }

            if (outcome.status === 'BUSINESS_ERROR') {
                // Throw a BPMNError to raise a BPMN Error in the engine
                throw new BPMNError(outcome.message)
            }
        } catch (e: any) {
            // Throw to fail the job
            throw new Error('Technical error: ' + e.message)
        }
    }

    async businessLogic(vars: myDTO): string {
        // some business logic here
        // throw here to bubble up technical failure to the execute method
        return worked ? {
            status: 'OK',
            result
         } : {
            status: 'BUSINESS_ERROR'
            message
         }
    }
}

To expose your connector for Connector Runtimes, in the index.ts of your module, export your connector class as Connector, like this:

import { MyConnector } from "./lib/MyConnector"
const Connector = MyConnector
export Connector

This provides a normalised interface for Connector Runtimes to be able to load your connector by convention.

For the Job Worker Connector Runtime see connector-runtime-worker.

connector-sdk-nodejs's People

Contributors

dependabot[bot] avatar jwulf avatar renovate[bot] avatar xomiamoore avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

connector-sdk-nodejs's Issues

Secret value is not being replaced at runtime

Hi there,

In the connector code, I am receiving four parameters and constructing URL string.

The parameters are - host, port, user and secret.

Expected result:
redis://uname:secret-value-here@hostname-fqdn:11485

Of these, one parameter is masked as secret.
secrets.REDIS_SECRET

Observed:
redis://uname:undefined@hostname-fqdn:11485

I also tried sending below value instead.
{{secrets.REDIS_SECRET}}
Observed:
redis://uname:{{secrets.REDIS_SECRET}}@hostname-fqdn:11485

My connector code is here on github.
https://github.com/rchari-ml/redis-connector-nodejs/tree/development

Camunda SaaS

Playground Cluster 
bru-2
Camunda 8.3.5

BPMN Process Name
AA Bank Process

Thanks!

Screenshot 2024-01-24 at 5 13 09 PM

Unable to reach package camunda-connector-worker-runtime

Hi there,

I am seeing an error while following the steps pertaining to running my custom connector with NodeJS.

Option#1 - Wrapping your connector in code.

https://registry.npmjs.org/camunda-connector-worker-runtime

npm i camunda-connector-worker-runtime

verbose stack Error: 404 Not Found - GET https://registry.npmjs.org/camunda-connector-worker-runtime - Not found

I am able to proceed with Option#2 though. I just thought of bringing it to your attention.

Thanks!

No Output Mappings

Describe the bug:

In my process, I would like to store the response of the weather API connector in another variable than weather
(e.g. anotherVariable)

Capture d’écran 2022-11-10 à 12 01 20

Here is my diagram :

<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:zeebe="http://camunda.org/schema/zeebe/1.0" xmlns:modeler="http://camunda.org/schema/modeler/1.0" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Web Modeler" exporterVersion="b3ab9cf" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.1.0" camunda:diagramRelationId="422e777f-7529-4a91-87c9-13ab6bd9d565">
  <bpmn:process id="weather-forecast-diagram" name="Weather Forecast Diagram" isExecutable="true">
    <bpmn:startEvent id="start-weather-forecast">
      <bpmn:outgoing>Flow_0lnx0hx</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:endEvent id="end-weather-forecast">
      <bpmn:incoming>Flow_0lhbapb</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="Flow_0lnx0hx" sourceRef="start-weather-forecast" targetRef="connector-weather-forecast" />
    <bpmn:serviceTask id="connector-weather-forecast" name="Connector Weather Forecast" zeebe:modelerTemplate="e2cff4e2-d7ea-47f1-8196-fb8792126a24" zeebe:modelerTemplateVersion="1668071568158" zeebe:modelerTemplateIcon="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iNDgiIHdpZHRoPSI0OCI+PHBhdGggZD0iTTE4IDMxaDEyLjVxMi4zIDAgMy45LTEuNjI1VDM2IDI1LjVxMC0yLjI1LTEuNTI1LTMuODI1UTMyLjk1IDIwLjEgMzAuNyAyMHEtLjY1LTIuMjUtMi41LTMuNjI1VDI0IDE1cS0yLjA1IDAtMy43NSAxLjA3NS0xLjcgMS4wNzUtMi41NSAyLjk3NS0yLjQuMS00LjA1IDEuODI1UTEyIDIyLjYgMTIgMjVxMCAyLjUgMS43NSA0LjI1VDE4IDMxWm0wLTNxLTEuMjUgMC0yLjEyNS0uODc1VDE1IDI1cTAtMS4yNS44NS0yLjEuODUtLjg1IDIuMDUtLjloMS44bC43LTEuN3EuNS0xLjA1IDEuNDc1LTEuNjc1UTIyLjg1IDE4IDI0IDE4cTEuMzUgMCAyLjQuNzc1IDEuMDUuNzc1IDEuNDUgMi4wNzVsLjYgMi4xNWgyLjFxMS4wNSAwIDEuNzUuNzI1VDMzIDI1LjVxMCAxLS43MjUgMS43NVQzMC41IDI4Wm02IDE2cS00LjEgMC03Ljc1LTEuNTc1LTMuNjUtMS41NzUtNi4zNzUtNC4zLTIuNzI1LTIuNzI1LTQuMy02LjM3NVE0IDI4LjEgNCAyNHEwLTQuMTUgMS41NzUtNy44IDEuNTc1LTMuNjUgNC4zLTYuMzUgMi43MjUtMi43IDYuMzc1LTQuMjc1UTE5LjkgNCAyNCA0cTQuMTUgMCA3LjggMS41NzUgMy42NSAxLjU3NSA2LjM1IDQuMjc1IDIuNyAyLjcgNC4yNzUgNi4zNVE0NCAxOS44NSA0NCAyNHEwIDQuMS0xLjU3NSA3Ljc1LTEuNTc1IDMuNjUtNC4yNzUgNi4zNzV0LTYuMzUgNC4zUTI4LjE1IDQ0IDI0IDQ0Wm0wLTNxNy4xIDAgMTIuMDUtNC45NzVRNDEgMzEuMDUgNDEgMjRxMC03LjEtNC45NS0xMi4wNVEzMS4xIDcgMjQgN3EtNy4wNSAwLTEyLjAyNSA0Ljk1UTcgMTYuOSA3IDI0cTAgNy4wNSA0Ljk3NSAxMi4wMjVRMTYuOTUgNDEgMjQgNDFabTAtMTdaIi8+PC9zdmc+">
      <bpmn:extensionElements>
        <zeebe:ioMapping>
          <zeebe:input source="metric" target="units" />
          <zeebe:input source="52.520008" target="latitude" />
          <zeebe:input source="13.404954" target="longitude" />
          <zeebe:input source="=&#34;secrets.OPENWEATHER_API_KEY&#34;" target="apiKey" />
        </zeebe:ioMapping>
        <zeebe:taskHeaders>
          <zeebe:header key="resultVariable" value="anotherVariable" />
        </zeebe:taskHeaders>
        <zeebe:taskDefinition type="io.camunda:weather-api:1" />
      </bpmn:extensionElements>
      <bpmn:incoming>Flow_0lnx0hx</bpmn:incoming>
      <bpmn:outgoing>Flow_0yrpfrf</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:sequenceFlow id="Flow_0yrpfrf" sourceRef="connector-weather-forecast" targetRef="Gateway_19fckwk" />
    <bpmn:exclusiveGateway id="Gateway_19fckwk" default="Flow_0lhbapb">
      <bpmn:incoming>Flow_0yrpfrf</bpmn:incoming>
      <bpmn:outgoing>Flow_0lhbapb</bpmn:outgoing>
      <bpmn:outgoing>Flow_1equp5j</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:sequenceFlow id="Flow_0lhbapb" sourceRef="Gateway_19fckwk" targetRef="end-weather-forecast" />
    <bpmn:endEvent id="Event_1fla8ne">
      <bpmn:incoming>Flow_1equp5j</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="Flow_1equp5j" sourceRef="Gateway_19fckwk" targetRef="Event_1fla8ne">
      <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">=anotherVariable = null</bpmn:conditionExpression>
    </bpmn:sequenceFlow>
  </bpmn:process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="weather-forecast-diagram">
      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="start-weather-forecast">
        <dc:Bounds x="152" y="102" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Event_012kuu6_di" bpmnElement="end-weather-forecast">
        <dc:Bounds x="582" y="102" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_00oxucj_di" bpmnElement="connector-weather-forecast">
        <dc:Bounds x="270" y="80" width="100" height="80" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Event_1fla8ne_di" bpmnElement="Event_1fla8ne">
        <dc:Bounds x="582" y="202" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Gateway_19fckwk_di" bpmnElement="Gateway_19fckwk" isMarkerVisible="true">
        <dc:Bounds x="455" y="95" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="Flow_0lnx0hx_di" bpmnElement="Flow_0lnx0hx">
        <di:waypoint x="188" y="120" />
        <di:waypoint x="270" y="120" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_0yrpfrf_di" bpmnElement="Flow_0yrpfrf">
        <di:waypoint x="370" y="120" />
        <di:waypoint x="455" y="120" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_0lhbapb_di" bpmnElement="Flow_0lhbapb">
        <di:waypoint x="505" y="120" />
        <di:waypoint x="582" y="120" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_1equp5j_di" bpmnElement="Flow_1equp5j">
        <di:waypoint x="480" y="145" />
        <di:waypoint x="480" y="220" />
        <di:waypoint x="582" y="220" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>

Actual behavior:

The instance is well processed, but the result is not my variable anotherVariable.
It seems that Output mappings are not working.

Capture d’écran 2022-11-10 à 11 55 30

Capture d’écran 2022-11-10 à 11 55 45

Tested on both Camunda SaaS and local Camunda Platform with docker-compose

How to reproduce:

  1. Connect the Weather Forecast Connector to your Camunda SaaS
    https://medium.com/@sitapati/how-to-build-a-camunda-8-connector-using-the-node-js-sdk-5eb3d798f9ff

  2. Deploy a diagram which use this connector with a different result variable (default one is weather)
    See diagram and picture above

  3. Start a process

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.