Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: 2.1
parameters:
node-version:
type: string
default: "18.13.0"
default: "24.10.0"
orbs:
node: circleci/node@5.0.0
slack: circleci/slack@4.5.3
Expand Down Expand Up @@ -72,7 +72,7 @@ commands:
jobs:
test:
docker: # run the steps with Docker
- image: cimg/node:18.13.0
- image: cimg/node:24.10.0
steps:
- checkout
- node/install:
Expand All @@ -88,7 +88,7 @@ jobs:
command: npm test
build:
docker:
- image: cimg/node:18.13.0
- image: cimg/node:24.10.0
user: root
steps:
- checkout
Expand Down
27 changes: 18 additions & 9 deletions .nsprc
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
{
"GHSA-27h2-hvpr-p74q": {
"GHSA-fjxv-7rqg-78g4": {
"active": true,
"notes": "We don't use verify function from jsonwebtoken, so not affected"
"notes": "This vulnerability is in form-data used transitively via deprecated 'request' library. We do not use form-data directly. Waiting on upstream libraries to upgrade."
},
"GHSA-wc69-rhjr-hc9g": {
"GHSA-869p-cjfg-cm3x": {
"active": true,
"notes": "Bunyan library set only new Date to momentjs as parameter"
"notes": "jws vulnerability in jsonwebtoken (via @elastic.io/maester-client -> elasticio-sailor-nodejs). This is a transitive dependency from sailor. Waiting on upstream libraries to upgrade."
},
"GHSA-hrpp-h998-j3pp": {
"GHSA-6rw7-vpxm-498p": {
"active": true,
"notes": "There is no query-string user input in sailor"
"notes": "qs vulnerability in request (via co-request). This is a transitive dependency. The deprecated 'request' library is used by co-request. Waiting on upstream libraries to upgrade."
},
"GHSA-fjxv-7rqg-78g4": {
"active": true
"GHSA-23c5-xmqv-rm74": {
"active": true,
"notes": "minimatch ReDoS via nested extglobs. minimatch is only used with static patterns in this project (no user-controlled glob patterns), so the risk of exploitation is negligible. Waiting on upstream libraries to upgrade."
},
"GHSA-3ppc-4f35-3m26": {
"active": true,
"notes": "minimatch ReDoS via repeated wildcards with non-matching literal in pattern. minimatch is only used with static patterns in this project (no user-controlled glob patterns), so the risk of exploitation is negligible. Waiting on upstream libraries to upgrade."
},
"GHSA-7r86-cg39-jmmj": {
"active": true,
"notes": "minimatch ReDoS via combinatorial backtracking in matchOne() with multiple non-adjacent GLOBSTAR segments. minimatch is only used with static patterns in this project (no user-controlled glob patterns), so the risk of exploitation is negligible. Waiting on upstream libraries to upgrade."
}
}
}
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 1.0.2 (February 27, 2026)
* Updated the following dependencies:
* Node.js version 22 -> 24
* axios 1.12.2 -> 1.13.5
* elasticio-sailor-nodejs 2.7.6 -> 2.7.8
* Added `strong-soap` v5.0.7 lib support
* Removed unused `elasticio-node` dependency

## 1.0.1 (September 26, 2025)
* Updated the following dependencies:
* Node.js version 18 -> 22
Expand Down
62 changes: 62 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ Built-in Node.js global objects are also supported.
- [`axios`](https://github.com/axios/axios) - A well-known HTTP Client [Documentation](https://www.npmjs.com/package/axios)
- [`request`](https://github.com/request/request) - Http Client (wrapped in `co` - [this library](https://www.npmjs.com/package/co-request) so that it is pre-promisified). We recommend using `axios`. Support for `request` is maintained for backward compatibility only.
- `_` - [Lodash](https://lodash.com/)
- [`strong-soap`](https://github.com/loopbackio/strong-soap) - SOAP client for invoking web services

## Credentials

Expand Down Expand Up @@ -200,3 +201,64 @@ async function run(msg, cfg, snapshot) {
await this.emit('data', { body: data });
}
```

### Calling a SOAP web service with strong-soap

The Code component exposes the [`strong-soap`](https://github.com/loopbackio/strong-soap) client as `soap`. You can call SOAP operations using async/await. Create the client with a small promise wrapper, then invoke methods (they return promises).

**Basic SOAP call (WSDL URL and operation args from incoming message):**

```JavaScript
function createSoapClient(wsdlUrl, options = {}) {
return new Promise((resolve, reject) => {
soap.createClient(wsdlUrl, options, (err, client) => {
if (err) reject(err);
else resolve(client);
});
});
}

async function run(msg, cfg, snapshot) {
const { wsdlUrl, operation, args } = msg.body;
const client = await createSoapClient(wsdlUrl);
const { result } = await client[operation](args || {});
await this.emit('data', { body: result });
}
```

**SOAP with Basic authentication (using component credentials):**

```JavaScript
function createSoapClient(wsdlUrl, options = {}) {
return new Promise((resolve, reject) => {
soap.createClient(wsdlUrl, options, (err, client) => {
if (err) reject(err);
else resolve(client);
});
});
}

async function run(msg, cfg, snapshot) {
const { wsdlUrl, operation, args } = msg.body;
const client = await createSoapClient(wsdlUrl);

if (cfg.credentials && cfg.credentials.username) {
client.setSecurity(new soap.BasicAuthSecurity(cfg.credentials.username, cfg.credentials.password));
}

const { result } = await client[operation](args || {});
await this.emit('data', { body: result });
}
```

**Calling a specific service and port:**

If the WSDL defines multiple services or ports, use the `ServiceName.PortName.MethodName` form (use the same `createSoapClient` helper as in the examples above):

```JavaScript
async function run(msg, cfg, snapshot) {
const client = await createSoapClient(msg.body.wsdlUrl);
const { result } = await client.MyService.MyPort.MyFunction({ name: msg.body.inputName });
await this.emit('data', { body: result });
}
```
8 changes: 7 additions & 1 deletion actions/code.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
const _ = require('lodash');
const axios = require('axios');
const vm = require('vm');
const { messages } = require('elasticio-node');
const co = require('co');
const request = require('co-request');
const { soap } = require('strong-soap');

function wait(timeout) {
return new Promise((ok) => {
Expand All @@ -16,6 +16,11 @@ function wait(timeout) {
});
}

const messages = {
newMessageWithBody: (body) => ({ body, headers: {} }),
newEmptyMessage: () => ({ body: {}, headers: {} }),
};

// eslint-disable-next-line consistent-return,func-names
exports.process = async function (msg, conf, snapshot) {
const vmExports = {};
Expand Down Expand Up @@ -43,6 +48,7 @@ exports.process = async function (msg, conf, snapshot) {
// Other Libraries
_,
axios,
soap,
request,
wait: wait.bind(this),
});
Expand Down
2 changes: 1 addition & 1 deletion component.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"title": "Node.js Code with Credentials",
"version": "1.0.1",
"version": "1.0.2",
"description": "You can write your own code and deploy it as part of integration process. With the use of credentials.",
"docsUrl": "https://docs.elastic.io/components/code-with-credentials/index.html",
"authClientTypes": [
Expand Down
Loading