@yousolution/node-red-contrib-you-sap-service-layer 0.0.6 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ # [0.1.1] - 2022-12-09
6
+
7
+ - Added label output to nextLink block
8
+ - Fix authentication for subflows compatibility
9
+ - Bug fix
10
+
11
+ # [0.1.0] - 2022-07-28
12
+
13
+ - Added sqlQuery node to execute saved sql from SAP Service Layer
14
+ - Added a second output to the nextLink node to check when pagination is finished
15
+ - Bug fix
16
+
5
17
  # [0.0.5] - 2022-05-27
6
18
 
7
19
  - Change cross join
@@ -0,0 +1,180 @@
1
+ <script type="text/javascript">
2
+ RED.nodes.registerType('SQLQuery',{
3
+ category: 'Sap',
4
+ color: '#FFC300',
5
+ defaults: {
6
+ name: {value: ''},
7
+ sqlCode: {value: ''},
8
+ // sqlName: {value: ''},
9
+ // sqlText: {value: ''},
10
+ headers: {value: ''},
11
+ nextLink: {value: ''},
12
+ bodyPost: {value: ''}
13
+ },
14
+ inputs:1,
15
+ outputs:1,
16
+ icon: 'font-awesome/fa-search',
17
+ label: function() {
18
+ return this.name||"SQL Query";
19
+ },
20
+ oneditprepare: function() {
21
+
22
+ $("#node-input-sqlCode").typedInput({
23
+ type:"msg",
24
+ types:["msg"],
25
+ typeField: "#node-input-sqlCode-type",
26
+ value: 'sqlCode'
27
+ });
28
+
29
+ // $("#node-input-sqlName").typedInput({
30
+ // type:"msg",
31
+ // types:["msg"],
32
+ // typeField: "#node-input-sqlName-type",
33
+ // value: 'sqlName'
34
+ // });
35
+
36
+ // $("#node-input-sqlText").typedInput({
37
+ // type:"msg",
38
+ // types:["msg"],
39
+ // typeField: "#node-input-sqlText-type",
40
+ // value: 'sqlText'
41
+ // });
42
+
43
+ $("#node-input-headers").typedInput({
44
+ type:"msg",
45
+ types:["msg"],
46
+ typeField: "#node-input-headers-type",
47
+ value: 'headers'
48
+ });
49
+
50
+ $("#node-input-nextLink").typedInput({
51
+ type:"msg",
52
+ types:["msg"],
53
+ typeField: "#node-input-nextLink-type",
54
+ value: 'nextLink'
55
+ });
56
+
57
+ $("#node-input-bodyPost").typedInput({
58
+ type:"msg",
59
+ types:["msg"],
60
+ typeField: "#node-input-bodyPost-type",
61
+ value: 'bodyPost'
62
+ });
63
+
64
+ // jQuery("#node-input-entity").change(function() {
65
+ // jQuery('#container-udo').hide();
66
+ // jQuery('#container-udt').hide();
67
+ // jQuery('#container-partnerName').hide();
68
+ // jQuery('#container-scriptName').hide();
69
+ // if (jQuery(this).val() === 'UDO'){
70
+ // jQuery('#container-udo').show();
71
+ // }
72
+ // if (jQuery(this).val() === 'UDT'){
73
+ // jQuery('#container-udt').show();
74
+ // }
75
+ // if (jQuery(this).val() === 'script'){
76
+ // jQuery('#container-partnerName').show();
77
+ // jQuery('#container-scriptName').show();
78
+ // }
79
+
80
+ // });
81
+ }
82
+ });
83
+ </script>
84
+
85
+ <script type="text/html" data-template-name="SQLQuery">
86
+ <div class="form-row">
87
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
88
+ <input type="text" id="node-input-name" placeholder="Name">
89
+ </div>
90
+
91
+ <div class="form-row">
92
+ <label for="node-input-type"><i class="fa fa-cog"></i> SqlCode</label>
93
+ <input type="text" id="node-input-sqlCode">
94
+ <input type="hidden" id="node-input-sqlCode-type">
95
+ </div>
96
+
97
+ <!-- <div class="form-row">
98
+ <label for="node-input-type"><i class="fa fa-cog"></i> SqlName</label>
99
+ <input type="text" id="node-input-sqlName">
100
+ <input type="hidden" id="node-input-sqlName-type">
101
+ </div>
102
+
103
+ <div class="form-row">
104
+ <label for="node-input-type"><i class="fa fa-cog"></i> SqlText</label>
105
+ <input type="text" id="node-input-sqlText">
106
+ <input type="hidden" id="node-input-sqlText-type">
107
+ </div> -->
108
+
109
+ <div class="form-row">
110
+ <label for="node-input-type"><i class="fa fa-cog"></i> Headers</label>
111
+ <input type="text" id="node-input-headers">
112
+ <input type="hidden" id="node-input-headers-type">
113
+ </div>
114
+
115
+ <div class="form-row">
116
+ <label for="node-input-type"><i class="fa fa-cog"></i> NextLink</label>
117
+ <input type="text" id="node-input-nextLink">
118
+ <input type="hidden" id="node-input-nextLink-type">
119
+ </div>
120
+
121
+ <div class="form-row">
122
+ <label for="node-input-type"><i class="fa fa-cog"></i> BodyPost</label>
123
+ <input type="text" id="node-input-bodyPost">
124
+ <input type="hidden" id="node-input-bodyPost-type">
125
+ </div>
126
+ </script>
127
+
128
+
129
+ <!-- Documentation -->
130
+ <script type="text/html" data-help-name="SQLQuery">
131
+ <p>Create a new Entity action</p>
132
+
133
+ <h3>Inputs</h3>
134
+ <dl class="message-properties">
135
+ <dt>Name
136
+ <span class="property-type">string</span>
137
+ </dt>
138
+ <dd> the node's name </dd>
139
+ <dt>Entity
140
+ <span class="property-type">string</span>
141
+ </dt>
142
+ <dd> the entity name of SAP resource </dd>
143
+ <dt>EntityId
144
+ <span class="property-type">number | string</span>
145
+ </dt>
146
+ <dd> the id of the entity of SAP resource </dd>
147
+ <dt>bodyPost
148
+ <span class="property-type">object</span>
149
+ </dt>
150
+ <dd> the data of the entity </dd>
151
+ </dl>
152
+
153
+ <h3>Outputs</h3>
154
+ <ol class="node-ports">
155
+ <li>Standard output
156
+ <dl class="message-properties">
157
+ <dt>payload <span class="property-type">string</span></dt>
158
+ <dd>the standard output of the command.</dd>
159
+ </dl>
160
+ </li>
161
+ </ol>
162
+
163
+ <h3>Details</h3>
164
+ <p>this node is used to create the entity of SAP.
165
+ See the examples to understand how to use it.
166
+ </p>
167
+ <!-- <p><code>msg.payload</code> is used as the payload of the published message.
168
+ If it contains an Object it will be converted to a JSON string before being sent.
169
+ If it contains a binary Buffer the message will be published as-is.</p>
170
+ <p>The topic used can be configured in the node or, if left blank, can be set
171
+ by <code>msg.topic</code>.</p>
172
+ <p>Likewise the QoS and retain values can be configured in the node or, if left
173
+ blank, set by <code>msg.qos</code> and <code>msg.retain</code> respectively.</p> -->
174
+
175
+ <h3>References</h3>
176
+ <ul>
177
+ <li><a href="https://sap-samples.github.io/smb-summit-hackathon/b1sl.html" target="_black">Service layer API docs</a> - for more details </li>
178
+ <li><a href="https://github.com/yousolution-cloud/node-red-contrib-you-sap-service-layer">@yousolution-cloud/node-red-contrib-you-sap-service-layer</a> - the nodes github repository</li>
179
+ </ul>
180
+ </script>
@@ -0,0 +1,43 @@
1
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
2
+ const axios = require('axios');
3
+ const Support = require('./support');
4
+
5
+ module.exports = function (RED) {
6
+ function SQLQuery(config) {
7
+ RED.nodes.createNode(this, config);
8
+ const node = this;
9
+ // reset status
10
+ node.status({});
11
+
12
+ node.on('input', async (msg, send, done) => {
13
+ // reset status
14
+ node.status({});
15
+ try {
16
+ const data = msg[config.bodyPost];
17
+ const params = {
18
+ SqlCode: msg[config.sqlCode],
19
+ };
20
+
21
+ if (!params.SqlCode) {
22
+ const missingParams = [];
23
+ params.SqlCode ? null : missingParams.push('SqlCode');
24
+ done(new Error(`Missing mandatory params: ${missingParams.join(',')}.`));
25
+ return;
26
+ }
27
+
28
+ const options = { method: 'POST', hasRawQuery: false, isSQLQuery: true, data: data };
29
+ const login = Support.login;
30
+ const result = await Support.sendRequest({ node, msg, config, axios, login, options });
31
+ msg.payload = result.data;
32
+ msg.nextLink = result.data['odata.nextLink'] || result.data['@odata.nextLink'];
33
+ msg.statusCode = result.status;
34
+ node.status({ fill: 'green', shape: 'dot', text: 'success' });
35
+ node.send(msg);
36
+ } catch (error) {
37
+ node.status({ fill: 'red', shape: 'dot', text: 'Error' });
38
+ done(error);
39
+ }
40
+ });
41
+ }
42
+ RED.nodes.registerType('SQLQuery', SQLQuery, {});
43
+ };
@@ -9,8 +9,10 @@
9
9
  version: {value: ''}
10
10
  },
11
11
  credentials: {
12
- company: {type: "string"},
12
+ company: {type: "string"},
13
+ companyType: {type: 'string'},
13
14
  user: {type:"string"},
15
+ userType: {type: 'string'},
14
16
  password: {type:"password"}
15
17
  },
16
18
  inputs:1,
@@ -18,6 +20,19 @@
18
20
  icon: 'font-awesome/fa-lock',
19
21
  label: function() {
20
22
  return this.name||"Sap authenticate";
23
+ },
24
+ oneditprepare: function() {
25
+ $("#node-input-company").typedInput({
26
+ default:"msg",
27
+ types:["msg", "str"],
28
+ typeField: "#node-input-companyType"
29
+ });
30
+
31
+ $("#node-input-user").typedInput({
32
+ default:"msg",
33
+ types:["msg", "str"],
34
+ typeField: "#node-input-userType"
35
+ });
21
36
  }
22
37
  });
23
38
  </script>
@@ -49,11 +64,13 @@
49
64
  <div class="form-row">
50
65
  <label for="node-input-company"><i class="fa fa-tag"></i> Company</label>
51
66
  <input type="text" id="node-input-company" placeholder="company">
67
+ <input type="hidden" id="node-input-companyType">
52
68
  </div>
53
69
 
54
70
  <div class="form-row">
55
71
  <label for="node-input-user"><i class="fa fa-tag"></i> User</label>
56
72
  <input type="text" id="node-input-user" placeholder="user">
73
+ <input type="hidden" id="node-input-userType">
57
74
  </div>
58
75
 
59
76
  <div class="form-row">
@@ -9,9 +9,9 @@ module.exports = function (RED) {
9
9
  // reset status
10
10
  node.status({});
11
11
 
12
- const flowContext = node.context().flow;
12
+ const globalContext = node.context().global;
13
13
 
14
- flowContext.set(`_YOU_SapServiceLayer_${node.id}`, {
14
+ globalContext.set(`_YOU_SapServiceLayer_${node.id}`, {
15
15
  host: config.host,
16
16
  port: config.port,
17
17
  version: config.version,
@@ -27,6 +27,18 @@ module.exports = function (RED) {
27
27
  }
28
28
 
29
29
  node.on('input', async (msg, send, done) => {
30
+ // If Company setted from msg
31
+ if (node.credentials.companyType == 'msg') {
32
+ const company = msg[node.credentials.company];
33
+ globalContext.set(`_YOU_SapServiceLayer_${node.id}.credentials.CompanyDB`, company);
34
+ }
35
+
36
+ // If User setted from msg
37
+ if (node.credentials.userType == 'msg') {
38
+ const user = msg[node.credentials.user];
39
+ globalContext.set(`_YOU_SapServiceLayer_${node.id}.credentials.UserName`, user);
40
+ }
41
+
30
42
  // reset status
31
43
  node.status({});
32
44
 
@@ -36,7 +48,7 @@ module.exports = function (RED) {
36
48
  return;
37
49
  }
38
50
 
39
- const headers = flowContext.get(`_YOU_SapServiceLayer_${node.id}.headers`);
51
+ const headers = globalContext.get(`_YOU_SapServiceLayer_${node.id}.headers`);
40
52
 
41
53
  msg._YOU_SapServiceLayer = {
42
54
  idAuth: node.id,
@@ -45,7 +57,7 @@ module.exports = function (RED) {
45
57
  if (!headers) {
46
58
  try {
47
59
  const result = await Support.login(node, node.id);
48
- flowContext.set(`_YOU_SapServiceLayer_${node.id}.headers`, result.headers['set-cookie']);
60
+ globalContext.set(`_YOU_SapServiceLayer_${node.id}.headers`, result.headers['set-cookie']);
49
61
  } catch (error) {
50
62
  msg.payload = error;
51
63
  if (error.response && error.response.data) {
@@ -65,7 +77,9 @@ module.exports = function (RED) {
65
77
  RED.nodes.registerType('authenticateSap', AuthenticateSapNode, {
66
78
  credentials: {
67
79
  company: { type: 'text' },
80
+ companyType: { type: 'text' },
68
81
  user: { type: 'text' },
82
+ userType: { type: 'text' },
69
83
  password: { type: 'password' },
70
84
  },
71
85
  });
@@ -0,0 +1,166 @@
1
+ <script type="text/javascript">
2
+ RED.nodes.registerType('createSQLQuery',{
3
+ category: 'Sap',
4
+ color: '#FFC300',
5
+ defaults: {
6
+ name: {value: ''},
7
+ sqlCode: {value: ''},
8
+ sqlName: {value: ''},
9
+ sqlText: {value: ''},
10
+ headers: {value: ''},
11
+ bodyPost: {value: ''}
12
+ },
13
+ inputs:1,
14
+ outputs:1,
15
+ icon: 'font-awesome/fa-plus',
16
+ label: function() {
17
+ return this.name||"Create SQL Query";
18
+ },
19
+ oneditprepare: function() {
20
+
21
+ $("#node-input-sqlCode").typedInput({
22
+ type:"msg",
23
+ types:["msg"],
24
+ typeField: "#node-input-sqlCode-type",
25
+ value: 'sqlCode'
26
+ });
27
+
28
+ $("#node-input-sqlName").typedInput({
29
+ type:"msg",
30
+ types:["msg"],
31
+ typeField: "#node-input-sqlName-type",
32
+ value: 'sqlName'
33
+ });
34
+
35
+ $("#node-input-sqlText").typedInput({
36
+ type:"msg",
37
+ types:["msg"],
38
+ typeField: "#node-input-sqlText-type",
39
+ value: 'sqlText'
40
+ });
41
+
42
+ $("#node-input-headers").typedInput({
43
+ type:"msg",
44
+ types:["msg"],
45
+ typeField: "#node-input-headers-type",
46
+ value: 'headers'
47
+ });
48
+
49
+ $("#node-input-bodyPost").typedInput({
50
+ type:"msg",
51
+ types:["msg"],
52
+ typeField: "#node-input-bodyPost-type",
53
+ value: 'bodyPost'
54
+ });
55
+
56
+ // jQuery("#node-input-entity").change(function() {
57
+ // jQuery('#container-udo').hide();
58
+ // jQuery('#container-udt').hide();
59
+ // jQuery('#container-partnerName').hide();
60
+ // jQuery('#container-scriptName').hide();
61
+ // if (jQuery(this).val() === 'UDO'){
62
+ // jQuery('#container-udo').show();
63
+ // }
64
+ // if (jQuery(this).val() === 'UDT'){
65
+ // jQuery('#container-udt').show();
66
+ // }
67
+ // if (jQuery(this).val() === 'script'){
68
+ // jQuery('#container-partnerName').show();
69
+ // jQuery('#container-scriptName').show();
70
+ // }
71
+
72
+ // });
73
+ }
74
+ });
75
+ </script>
76
+
77
+ <script type="text/html" data-template-name="createSQLQuery">
78
+ <div class="form-row">
79
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
80
+ <input type="text" id="node-input-name" placeholder="Name">
81
+ </div>
82
+
83
+ <div class="form-row">
84
+ <label for="node-input-type"><i class="fa fa-cog"></i> SqlCode</label>
85
+ <input type="text" id="node-input-sqlCode">
86
+ <input type="hidden" id="node-input-sqlCode-type">
87
+ </div>
88
+
89
+ <div class="form-row">
90
+ <label for="node-input-type"><i class="fa fa-cog"></i> SqlName</label>
91
+ <input type="text" id="node-input-sqlName">
92
+ <input type="hidden" id="node-input-sqlName-type">
93
+ </div>
94
+
95
+ <div class="form-row">
96
+ <label for="node-input-type"><i class="fa fa-cog"></i> SqlText</label>
97
+ <input type="text" id="node-input-sqlText">
98
+ <input type="hidden" id="node-input-sqlText-type">
99
+ </div>
100
+
101
+ <div class="form-row">
102
+ <label for="node-input-type"><i class="fa fa-cog"></i> Headers</label>
103
+ <input type="text" id="node-input-headers">
104
+ <input type="hidden" id="node-input-headers-type">
105
+ </div>
106
+
107
+ <div class="form-row">
108
+ <label for="node-input-type"><i class="fa fa-cog"></i> BodyPost</label>
109
+ <input type="text" id="node-input-bodyPost">
110
+ <input type="hidden" id="node-input-bodyPost-type">
111
+ </div>
112
+ </script>
113
+
114
+
115
+ <!-- Documentation -->
116
+ <script type="text/html" data-help-name="createSQLQuery">
117
+ <p>Create a new SQL query from SAP service layer</p>
118
+
119
+ <h3>Inputs</h3>
120
+ <dl class="message-properties">
121
+ <dt>Name
122
+ <span class="property-type">string</span>
123
+ </dt>
124
+ <dd> the node's name </dd>
125
+ <dt>Entity
126
+ <span class="property-type">string</span>
127
+ </dt>
128
+ <dd> the entity name of SAP resource </dd>
129
+ <dt>EntityId
130
+ <span class="property-type">number | string</span>
131
+ </dt>
132
+ <dd> the id of the entity of SAP resource </dd>
133
+ <dt>bodyPost
134
+ <span class="property-type">object</span>
135
+ </dt>
136
+ <dd> the data of the entity </dd>
137
+ </dl>
138
+
139
+ <h3>Outputs</h3>
140
+ <ol class="node-ports">
141
+ <li>Standard output
142
+ <dl class="message-properties">
143
+ <dt>payload <span class="property-type">string</span></dt>
144
+ <dd>the standard output of the command.</dd>
145
+ </dl>
146
+ </li>
147
+ </ol>
148
+
149
+ <h3>Details</h3>
150
+ <p>this node is used to create the entity of SAP.
151
+ See the examples to understand how to use it.
152
+ </p>
153
+ <!-- <p><code>msg.payload</code> is used as the payload of the published message.
154
+ If it contains an Object it will be converted to a JSON string before being sent.
155
+ If it contains a binary Buffer the message will be published as-is.</p>
156
+ <p>The topic used can be configured in the node or, if left blank, can be set
157
+ by <code>msg.topic</code>.</p>
158
+ <p>Likewise the QoS and retain values can be configured in the node or, if left
159
+ blank, set by <code>msg.qos</code> and <code>msg.retain</code> respectively.</p> -->
160
+
161
+ <h3>References</h3>
162
+ <ul>
163
+ <li><a href="https://sap-samples.github.io/smb-summit-hackathon/b1sl.html" target="_black">Service layer API docs</a> - for more details </li>
164
+ <li><a href="https://github.com/yousolution-cloud/node-red-contrib-you-sap-service-layer">@yousolution-cloud/node-red-contrib-you-sap-service-layer</a> - the nodes github repository</li>
165
+ </ul>
166
+ </script>
@@ -0,0 +1,67 @@
1
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
2
+ const axios = require('axios');
3
+ const Support = require('./support');
4
+
5
+ module.exports = function (RED) {
6
+ function CreateSQLQuery(config) {
7
+ RED.nodes.createNode(this, config);
8
+ const node = this;
9
+ // reset status
10
+ node.status({});
11
+
12
+ node.on('input', async (msg, send, done) => {
13
+ // reset status
14
+ node.status({});
15
+ try {
16
+ // const data = msg[config.bodyPost];
17
+ const data = {
18
+ SqlCode: msg[config.sqlCode],
19
+ SqlName: msg[config.sqlName],
20
+ SqlText: msg[config.sqlText],
21
+ };
22
+
23
+ if (!data.SqlCode || !data.SqlName || !data.SqlText) {
24
+ const missingParams = [];
25
+ data.SqlCode ? null : missingParams.push('SqlCode');
26
+ data.SqlName ? null : missingParams.push('SqlName');
27
+ data.SqlText ? null : missingParams.push('SqlText');
28
+ done(new Error(`Missing mandatory params: ${missingParams.join(',')}.`));
29
+ return;
30
+ }
31
+
32
+ // if (!data.SqlCode) {
33
+ // node.status({ fill: 'red', shape: 'dot', text: 'SqlCode must have value' });
34
+ // done(new Error('SqlCode must have value'));
35
+ // return;
36
+ // }
37
+ // if (!data.SqlName) {
38
+ // node.status({ fill: 'red', shape: 'dot', text: 'SqlName must have value' });
39
+ // done(new Error('SqlName must have value'));
40
+ // return;
41
+ // }
42
+ // if (!data.SqlText) {
43
+ // node.status({ fill: 'red', shape: 'dot', text: 'SqlText must have value' });
44
+ // done(new Error('SqlText must have value'));
45
+ // return;
46
+ // }
47
+
48
+ // if (!data) {
49
+ // node.status({ fill: 'red', shape: 'dot', text: 'bodyPost must have value' });
50
+ // done(new Error('bodyPost must have value'));
51
+ // return;
52
+ // }
53
+ const options = { method: 'POST', hasRawQuery: false, isCreateSQLQuery: true, data: data };
54
+ const login = Support.login;
55
+ const result = await Support.sendRequest({ node, msg, config, axios, login, options });
56
+ msg.payload = result;
57
+ msg.statusCode = result.status;
58
+ node.status({ fill: 'green', shape: 'dot', text: 'success' });
59
+ node.send(msg);
60
+ } catch (error) {
61
+ node.status({ fill: 'red', shape: 'dot', text: 'Error' });
62
+ done(error);
63
+ }
64
+ });
65
+ }
66
+ RED.nodes.registerType('createSQLQuery', CreateSQLQuery, {});
67
+ };
@@ -21,7 +21,7 @@ module.exports = function (RED) {
21
21
  const result = await Support.sendRequest({ node, msg, config, axios, login, options });
22
22
  msg.payload = result.data;
23
23
  msg.statusCode = result.status;
24
- msg.nextLink = result.data['odata.nextLink'];
24
+ msg.nextLink = result.data['odata.nextLink'] || result.data['@odata.nextLink'];
25
25
  node.status({ fill: 'green', shape: 'dot', text: 'success' });
26
26
  node.send(msg);
27
27
  } catch (error) {
package/nodes/listSap.js CHANGED
@@ -20,7 +20,7 @@ module.exports = function (RED) {
20
20
  const login = Support.login;
21
21
  const result = await Support.sendRequest({ node, msg, config, axios, login, options });
22
22
  msg.payload = result.data;
23
- msg.nextLink = result.data['odata.nextLink'];
23
+ msg.nextLink = result.data['odata.nextLink'] || result.data['@odata.nextLink'];
24
24
  msg.statusCode = result.status;
25
25
  node.status({ fill: 'green', shape: 'dot', text: 'success' });
26
26
  node.send(msg);