@mcp-abap-adt/sap-rfc-lite 0.1.0

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/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@mcp-abap-adt/sap-rfc-lite",
3
+ "version": "0.1.0",
4
+ "description": "Lightweight Node.js bindings for SAP NW RFC SDK",
5
+ "license": "Apache-2.0",
6
+ "main": "./lib/index.js",
7
+ "types": "./lib/index.d.ts",
8
+ "files": [
9
+ "binding.gyp",
10
+ "src",
11
+ "lib"
12
+ ],
13
+ "scripts": {
14
+ "install": "node-gyp-build",
15
+ "build:ts": "tsc",
16
+ "build:cpp": "node-gyp rebuild",
17
+ "build": "npm run build:ts && npm run build:cpp",
18
+ "lint": "npx biome check --write src",
19
+ "lint:check": "npx biome check src",
20
+ "format": "npx biome format --write src",
21
+ "test": "jest --testTimeout 60000",
22
+ "prepare": "husky"
23
+ },
24
+ "config": {
25
+ "napi_version": 8
26
+ },
27
+ "dependencies": {
28
+ "node-addon-api": "^6.1.0",
29
+ "node-gyp-build": "^4.6.0"
30
+ },
31
+ "devDependencies": {
32
+ "@biomejs/biome": "^2.3.10",
33
+ "@types/jest": "^29.0.0",
34
+ "@types/node": "^20.0.0",
35
+ "husky": "^9.1.7",
36
+ "jest": "^29.0.0",
37
+ "ts-jest": "^29.0.0",
38
+ "ts-node": "^10.9.2",
39
+ "typescript": "^5.0.0"
40
+ },
41
+ "engines": {
42
+ "node": ">=18"
43
+ },
44
+ "gypfile": true
45
+ }
File without changes
@@ -0,0 +1,464 @@
1
+ // SPDX-FileCopyrightText: 2014 SAP SE Srdjan Boskovic <srdjan.boskovic@sap.com>
2
+ // SPDX-FileCopyrightText: 2026 sap-rfc-lite contributors
3
+ //
4
+ // SPDX-License-Identifier: Apache-2.0
5
+
6
+ #include "Client.h"
7
+ #include <mutex>
8
+ #include <thread>
9
+ #include <tuple>
10
+
11
+ namespace node_rfc {
12
+
13
+ uint_t Client::_id = 1;
14
+
15
+ ErrorPair connectionCheckErrorInit() {
16
+ RFC_ERROR_INFO errorInfo;
17
+ errorInfo.code = RFC_OK;
18
+ return ErrorPair(errorInfo, "");
19
+ }
20
+
21
+ Napi::Value Client::getOperationError(bool conn_closed,
22
+ const char* operation,
23
+ ErrorPair connectionCheckError,
24
+ RFC_ERROR_INFO* errorInfo,
25
+ Napi::Env env) {
26
+ Napi::EscapableHandleScope scope(env);
27
+ Napi::Value error = Env().Undefined();
28
+ if (conn_closed) {
29
+ error = connectionClosedError(operation);
30
+ } else if (connectionCheckError.first.code != RFC_OK) {
31
+ error = rfcSdkError(&connectionCheckError.first);
32
+ } else if (connectionCheckError.second.length() > 0) {
33
+ error = nodeRfcError(connectionCheckError.second);
34
+ } else if (errorInfo->code != RFC_OK) {
35
+ error = rfcSdkError(errorInfo);
36
+ }
37
+ return scope.Escape(error);
38
+ }
39
+
40
+ Napi::Object Client::Init(Napi::Env env, Napi::Object exports) {
41
+ Napi::HandleScope scope(env);
42
+
43
+ Napi::Function func = DefineClass(
44
+ env,
45
+ "Client",
46
+ {
47
+ InstanceAccessor("_id", &Client::IdGetter, nullptr),
48
+ InstanceAccessor("_alive", &Client::AliveGetter, nullptr),
49
+ InstanceMethod("open", &Client::Open),
50
+ InstanceMethod("close", &Client::Close),
51
+ InstanceMethod("invoke", &Client::Invoke),
52
+ });
53
+
54
+ Napi::FunctionReference* constructor = new Napi::FunctionReference();
55
+ *constructor = Napi::Persistent(func);
56
+ constructor->SuppressDestruct();
57
+ env.SetInstanceData(constructor);
58
+
59
+ // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
60
+ exports.Set("Client", func);
61
+ return exports;
62
+ }
63
+
64
+ Napi::Value Client::IdGetter(const Napi::CallbackInfo& info) {
65
+ return Napi::Number::New(info.Env(), id);
66
+ }
67
+
68
+ Napi::Value Client::AliveGetter(const Napi::CallbackInfo& info) {
69
+ return Napi::Boolean::New(info.Env(), connectionHandle != nullptr);
70
+ }
71
+
72
+ Client::Client(const Napi::CallbackInfo& info)
73
+ : Napi::ObjectWrap<Client>(info) {
74
+ init();
75
+
76
+ if (!info[0].IsUndefined() && (info[0].IsFunction() || !info[0].IsObject())) {
77
+ Napi::TypeError::New(Env(), "Client connection parameters missing")
78
+ .ThrowAsJavaScriptException();
79
+ return;
80
+ }
81
+
82
+ if (info.Length() > 0) {
83
+ clientParamsRef = Napi::Persistent(info[0].As<Napi::Object>());
84
+ getConnectionParams(clientParamsRef.Value(), &client_params);
85
+ }
86
+
87
+ if (!info[1].IsUndefined()) {
88
+ clientOptionsRef = Napi::Persistent(info[1].As<Napi::Object>());
89
+ checkClientOptions(clientOptionsRef.Value(), &client_options);
90
+ }
91
+
92
+ if (info.Length() > 2) {
93
+ char errmsg[ERRMSG_LENGTH];
94
+ snprintf(errmsg,
95
+ ERRMSG_LENGTH - 1,
96
+ "Client constructor requires max. two arguments, received %zu",
97
+ info.Length());
98
+ Napi::TypeError::New(node_rfc::__env, errmsg).ThrowAsJavaScriptException();
99
+ }
100
+ };
101
+
102
+ Client::~Client(void) {
103
+ if (connectionHandle != nullptr) {
104
+ RFC_ERROR_INFO errorInfo;
105
+ RfcCloseConnection(connectionHandle, &errorInfo);
106
+ }
107
+ if (!clientParamsRef.IsEmpty()) {
108
+ clientParamsRef.Reset();
109
+ }
110
+ if (!clientOptionsRef.IsEmpty()) {
111
+ clientOptionsRef.Reset();
112
+ }
113
+ }
114
+
115
+ Napi::Value Client::connectionClosedError(const char* suffix) {
116
+ return nodeRfcError("RFM client request over closed connection: " +
117
+ std::string(suffix));
118
+ }
119
+
120
+ class OpenAsync : public Napi::AsyncWorker {
121
+ public:
122
+ OpenAsync(Napi::Function& callback, Client* client)
123
+ : Napi::AsyncWorker(callback), client(client) {}
124
+ ~OpenAsync() {}
125
+
126
+ // cppcheck-suppress unusedFunction
127
+ void Execute() {
128
+ client->LockMutex();
129
+ client->connectionHandle =
130
+ RfcOpenConnection(client->client_params.connectionParams,
131
+ client->client_params.paramSize,
132
+ &errorInfo);
133
+ if (errorInfo.code != RFC_OK) {
134
+ client->connectionHandle = nullptr;
135
+ }
136
+ client->UnlockMutex();
137
+ }
138
+
139
+ // cppcheck-suppress unusedFunction
140
+ void OnOK() {
141
+ if (errorInfo.code != RFC_OK) {
142
+ Callback().Call({rfcSdkError(&errorInfo)});
143
+ } else {
144
+ Callback().Call({});
145
+ }
146
+ Callback().Reset();
147
+ }
148
+
149
+ private:
150
+ Client* client;
151
+ RFC_ERROR_INFO errorInfo;
152
+ };
153
+
154
+ class CloseAsync : public Napi::AsyncWorker {
155
+ public:
156
+ CloseAsync(Napi::Function& callback, Client* client)
157
+ : Napi::AsyncWorker(callback), client(client) {}
158
+ ~CloseAsync() {}
159
+
160
+ void Execute() {
161
+ client->LockMutex();
162
+ conn_closed = (client->connectionHandle == nullptr);
163
+ if (!conn_closed) {
164
+ RfcCloseConnection(client->connectionHandle, &errorInfo);
165
+ client->connectionHandle = nullptr;
166
+ }
167
+ client->UnlockMutex();
168
+ }
169
+
170
+ void OnOK() {
171
+ Napi::HandleScope scope(Env());
172
+
173
+ if (conn_closed) {
174
+ Callback().Call({client->connectionClosedError("close()")});
175
+ } else if (errorInfo.code != RFC_OK) {
176
+ Callback().Call({rfcSdkError(&errorInfo)});
177
+ } else {
178
+ Callback().Call({});
179
+ }
180
+ Callback().Reset();
181
+ }
182
+
183
+ private:
184
+ Client* client;
185
+ RFC_ERROR_INFO errorInfo;
186
+ bool conn_closed = false;
187
+ };
188
+
189
+ class InvokeAsync : public Napi::AsyncWorker {
190
+ public:
191
+ InvokeAsync(Napi::Function& callback,
192
+ Client* client,
193
+ RFC_FUNCTION_HANDLE functionHandle,
194
+ RFC_FUNCTION_DESC_HANDLE functionDescHandle)
195
+ : Napi::AsyncWorker(callback),
196
+ client(client),
197
+ functionHandle(functionHandle),
198
+ functionDescHandle(functionDescHandle) {}
199
+ ~InvokeAsync() {}
200
+
201
+ void Execute() {
202
+ client->LockMutex();
203
+ conn_closed = (client->connectionHandle == nullptr);
204
+ if (!conn_closed) {
205
+ RfcInvoke(client->connectionHandle, functionHandle, &errorInfo);
206
+ if (errorInfo.code != RFC_OK) {
207
+ connectionCheckError = client->connectionCheck(&errorInfo);
208
+ }
209
+ }
210
+ }
211
+
212
+ void OnOK() {
213
+ Napi::HandleScope scope(Env());
214
+
215
+ std::string closed_errmsg =
216
+ "invoke() " + wrapString(client->errorPath.functionName)
217
+ .As<Napi::String>()
218
+ .Utf8Value();
219
+ ValuePair result =
220
+ ValuePair(client->getOperationError(conn_closed,
221
+ closed_errmsg.c_str(),
222
+ connectionCheckError,
223
+ &errorInfo,
224
+ Env()),
225
+ Env().Undefined());
226
+
227
+ if (result.first.IsUndefined()) {
228
+ result = getRfmParameters(functionDescHandle,
229
+ functionHandle,
230
+ &client->errorPath,
231
+ &client->client_options);
232
+ }
233
+
234
+ RfcDestroyFunction(functionHandle, nullptr);
235
+ client->UnlockMutex();
236
+
237
+ Callback().Call({result.first, result.second});
238
+ Callback().Reset();
239
+ }
240
+
241
+ private:
242
+ Client* client;
243
+ RFC_FUNCTION_HANDLE functionHandle;
244
+ RFC_FUNCTION_DESC_HANDLE functionDescHandle;
245
+ RFC_ERROR_INFO errorInfo;
246
+ bool conn_closed = false;
247
+ ErrorPair connectionCheckError = connectionCheckErrorInit();
248
+ };
249
+
250
+ class PrepareAsync : public Napi::AsyncWorker {
251
+ public:
252
+ PrepareAsync(Napi::Function& callback,
253
+ Client* client,
254
+ Napi::String rfmName,
255
+ Napi::Array& notRequestedParameters,
256
+ Napi::Object& rfmParams)
257
+ : Napi::AsyncWorker(callback),
258
+ client(client),
259
+ notRequested(Napi::Persistent(notRequestedParameters)),
260
+ rfmParams(Napi::Persistent(rfmParams)) {
261
+ funcName = setString(rfmName);
262
+ client->errorPath.setFunctionName(funcName);
263
+ }
264
+ ~PrepareAsync() { delete[] funcName; }
265
+
266
+ void Execute() {
267
+ client->LockMutex();
268
+ conn_closed = (client->connectionHandle == nullptr);
269
+ if (!conn_closed) {
270
+ functionDescHandle =
271
+ RfcGetFunctionDesc(client->connectionHandle, funcName, &errorInfo);
272
+ }
273
+ }
274
+
275
+ void OnOK() {
276
+ client->UnlockMutex();
277
+ RFC_FUNCTION_HANDLE functionHandle = nullptr;
278
+ Napi::Value argv[2] = {Env().Undefined(), Env().Undefined()};
279
+
280
+ if (conn_closed) {
281
+ std::string errmsg =
282
+ "invoke() " + wrapString(client->errorPath.functionName)
283
+ .As<Napi::String>()
284
+ .Utf8Value();
285
+ argv[0] = client->connectionClosedError(errmsg.c_str());
286
+ } else if (functionDescHandle == nullptr || errorInfo.code != RFC_OK) {
287
+ argv[0] = rfcSdkError(&errorInfo);
288
+ } else {
289
+ // function descriptor handle created, proceed with function handle
290
+ functionHandle = RfcCreateFunction(functionDescHandle, &errorInfo);
291
+
292
+ if (errorInfo.code != RFC_OK) {
293
+ argv[0] = rfcSdkError(&errorInfo);
294
+ } else {
295
+ for (uint_t i = 0; i < notRequested.Value().Length(); i++) {
296
+ Napi::String name = notRequested.Value().Get(i).ToString();
297
+ SAP_UC* paramName = setString(name);
298
+ RFC_RC rc =
299
+ RfcSetParameterActive(functionHandle, paramName, 0, &errorInfo);
300
+ delete[] paramName;
301
+ if (rc != RFC_OK) {
302
+ argv[0] = rfcSdkError(&errorInfo);
303
+ break;
304
+ }
305
+ }
306
+ }
307
+ }
308
+
309
+ notRequested.Reset();
310
+
311
+ if (argv[0].IsUndefined()) {
312
+ Napi::Object params = rfmParams.Value();
313
+ Napi::Array paramNames = params.GetPropertyNames();
314
+ uint_t paramSize = paramNames.Length();
315
+
316
+ for (uint_t i = 0; i < paramSize; i++) {
317
+ Napi::String name = paramNames.Get(i).ToString();
318
+ Napi::Value value = params.Get(name);
319
+ argv[0] = setRfmParameter(functionDescHandle,
320
+ functionHandle,
321
+ name,
322
+ value,
323
+ &client->errorPath,
324
+ &client->client_options);
325
+
326
+ if (!argv[0].IsUndefined()) {
327
+ break;
328
+ }
329
+ }
330
+ }
331
+
332
+ rfmParams.Reset();
333
+
334
+ if (argv[0].IsUndefined()) {
335
+ Napi::Function callbackFunction = Callback().Value().As<Napi::Function>();
336
+ (new InvokeAsync(
337
+ callbackFunction, client, functionHandle, functionDescHandle))
338
+ ->Queue();
339
+ } else {
340
+ Callback().Call({argv[0], argv[1]});
341
+ Callback().Reset();
342
+ }
343
+ }
344
+
345
+ private:
346
+ Client* client;
347
+ SAP_UC* funcName;
348
+
349
+ Napi::Reference<Napi::Array> notRequested;
350
+ Napi::Reference<Napi::Object> rfmParams;
351
+
352
+ RFC_FUNCTION_DESC_HANDLE functionDescHandle;
353
+ RFC_ERROR_INFO errorInfo;
354
+ bool conn_closed = false;
355
+ };
356
+
357
+ ErrorPair Client::connectionCheck(RFC_ERROR_INFO* errorInfo) {
358
+ RFC_ERROR_INFO errorInfoOpen;
359
+
360
+ errorInfoOpen.code = RFC_OK;
361
+
362
+ if (
363
+ errorInfo->code == RFC_COMMUNICATION_FAILURE ||
364
+ errorInfo->code == RFC_ABAP_RUNTIME_FAILURE ||
365
+ errorInfo->code == RFC_ABAP_MESSAGE ||
366
+ errorInfo->code == RFC_EXTERNAL_FAILURE ||
367
+ errorInfo->group == ABAP_RUNTIME_FAILURE ||
368
+ errorInfo->group == LOGON_FAILURE ||
369
+ errorInfo->group == COMMUNICATION_FAILURE ||
370
+ errorInfo->group == EXTERNAL_RUNTIME_FAILURE)
371
+ {
372
+ RFC_CONNECTION_HANDLE new_handle;
373
+ this->connectionHandle = nullptr;
374
+ new_handle = RfcOpenConnection(client_params.connectionParams,
375
+ client_params.paramSize,
376
+ &errorInfoOpen);
377
+ if (errorInfoOpen.code == RFC_OK) {
378
+ this->connectionHandle = new_handle;
379
+ }
380
+ }
381
+
382
+ return ErrorPair(errorInfoOpen, "");
383
+ }
384
+
385
+ Napi::Value Client::Open(const Napi::CallbackInfo& info) {
386
+ if (!info[0].IsFunction()) {
387
+ Napi::TypeError::New(info.Env(),
388
+ "Client open() requires a callback function")
389
+ .ThrowAsJavaScriptException();
390
+ return info.Env().Undefined();
391
+ }
392
+
393
+ Napi::Function callback = info[0].As<Napi::Function>();
394
+
395
+ (new OpenAsync(callback, this))->Queue();
396
+
397
+ return info.Env().Undefined();
398
+ }
399
+
400
+ Napi::Value Client::Close(const Napi::CallbackInfo& info) {
401
+ if (!info[0].IsFunction()) {
402
+ Napi::TypeError::New(info.Env(),
403
+ "Client close() requires a callback function")
404
+ .ThrowAsJavaScriptException();
405
+ return info.Env().Undefined();
406
+ }
407
+
408
+ Napi::Function callback = info[0].As<Napi::Function>();
409
+
410
+ (new CloseAsync(callback, this))->Queue();
411
+
412
+ return info.Env().Undefined();
413
+ }
414
+
415
+ Napi::Value Client::Invoke(const Napi::CallbackInfo& info) {
416
+ Napi::Array notRequested = Napi::Array::New(info.Env());
417
+ Napi::Value bcd;
418
+
419
+ if (!info[2].IsFunction()) {
420
+ Napi::TypeError::New(info.Env(),
421
+ "Client invoke() requires a callback function")
422
+ .ThrowAsJavaScriptException();
423
+ return info.Env().Undefined();
424
+ }
425
+
426
+ Napi::Function callback = info[2].As<Napi::Function>();
427
+
428
+ if (info[3].IsObject()) {
429
+ Napi::Object options = info[3].ToObject();
430
+ Napi::Array props = options.GetPropertyNames();
431
+ for (uint_t i = 0; i < props.Length(); i++) {
432
+ Napi::String key = props.Get(i).ToString();
433
+ if (key.Utf8Value().compare(std::string(CALL_OPTION_KEY_NOTREQUESTED)) ==
434
+ (int)0) {
435
+ notRequested = options.Get(key).As<Napi::Array>();
436
+ } else if (key.Utf8Value().compare(
437
+ std::string(CALL_OPTION_KEY_TIMEOUT)) == (int)0) {
438
+ // timeout = options.Get(key).As<Napi::Array>();
439
+ } else {
440
+ char err[ERRMSG_LENGTH];
441
+ std::string optionName = key.Utf8Value();
442
+ snprintf(err, ERRMSG_LENGTH - 1, "Unknown option: %s", &optionName[0]);
443
+ Napi::TypeError::New(node_rfc::__env, err).ThrowAsJavaScriptException();
444
+ }
445
+ }
446
+ }
447
+
448
+ Napi::String rfmName = info[0].As<Napi::String>();
449
+ Napi::Object rfmParams = info[1].As<Napi::Object>();
450
+
451
+ (new PrepareAsync(callback, this, rfmName, notRequested, rfmParams))->Queue();
452
+
453
+ return info.Env().Undefined();
454
+ }
455
+
456
+ void Client::LockMutex() {
457
+ invocationMutex.lock();
458
+ }
459
+
460
+ void Client::UnlockMutex() {
461
+ invocationMutex.unlock();
462
+ }
463
+
464
+ } // namespace node_rfc
@@ -0,0 +1,66 @@
1
+ // SPDX-FileCopyrightText: 2014 SAP SE Srdjan Boskovic <srdjan.boskovic@sap.com>
2
+ // SPDX-FileCopyrightText: 2026 sap-rfc-lite contributors
3
+ //
4
+ // SPDX-License-Identifier: Apache-2.0
5
+
6
+ #ifndef NodeRfc_Client_H
7
+ #define NodeRfc_Client_H
8
+
9
+ #include "nwrfcsdk.h"
10
+
11
+ namespace node_rfc {
12
+
13
+ extern Napi::Env __env;
14
+
15
+ class Client : public Napi::ObjectWrap<Client> {
16
+ public:
17
+ friend class OpenAsync;
18
+ friend class CloseAsync;
19
+ friend class PrepareAsync;
20
+ friend class InvokeAsync;
21
+ static Napi::Object Init(Napi::Env env, Napi::Object exports);
22
+ // cppcheck-suppress noExplicitConstructor
23
+ Client(const Napi::CallbackInfo& info);
24
+ ~Client(void);
25
+
26
+ private:
27
+ Napi::Value IdGetter(const Napi::CallbackInfo& info);
28
+ Napi::Value AliveGetter(const Napi::CallbackInfo& info);
29
+ Napi::ObjectReference clientParamsRef;
30
+ Napi::ObjectReference clientOptionsRef;
31
+
32
+ Napi::Value connectionClosedError(const char* suffix);
33
+ ErrorPair connectionCheck(RFC_ERROR_INFO* errorInfo);
34
+ Napi::Value getOperationError(bool conn_closed,
35
+ const char* operation,
36
+ ErrorPair connectionCheckError,
37
+ RFC_ERROR_INFO* errorInfo,
38
+ Napi::Env env);
39
+
40
+ Napi::Value Open(const Napi::CallbackInfo& info);
41
+ Napi::Value Close(const Napi::CallbackInfo& info);
42
+ Napi::Value Invoke(const Napi::CallbackInfo& info);
43
+
44
+ RfmErrorPath errorPath;
45
+
46
+ void init() {
47
+ id = Client::_id++;
48
+ connectionHandle = nullptr;
49
+ };
50
+
51
+ static uint_t _id;
52
+ std::mutex invocationMutex;
53
+
54
+ uint_t id;
55
+ RFC_CONNECTION_HANDLE connectionHandle;
56
+
57
+ ConnectionParamsStruct client_params = ConnectionParamsStruct(0, nullptr);
58
+ ClientOptionsStruct client_options;
59
+
60
+ void LockMutex();
61
+ void UnlockMutex();
62
+ };
63
+
64
+ } // namespace node_rfc
65
+
66
+ #endif
@@ -0,0 +1,43 @@
1
+ // SPDX-FileCopyrightText: 2014 SAP SE Srdjan Boskovic <srdjan.boskovic@sap.com>
2
+ // SPDX-FileCopyrightText: 2026 sap-rfc-lite contributors
3
+ //
4
+ // SPDX-License-Identifier: Apache-2.0
5
+
6
+ #include "Client.h"
7
+
8
+ namespace node_rfc {
9
+
10
+ Napi::Env __env = nullptr;
11
+
12
+ Napi::Value BindingVersions(Napi::Env env) {
13
+ uint_t major, minor, patchLevel;
14
+ Napi::EscapableHandleScope scope(env);
15
+
16
+ RfcGetVersion(&major, &minor, &patchLevel);
17
+
18
+ Napi::Object nwrfcsdk = Napi::Object::New(env);
19
+ nwrfcsdk.Set("major", major);
20
+ nwrfcsdk.Set("minor", minor);
21
+ nwrfcsdk.Set("patchLevel", patchLevel);
22
+
23
+ Napi::Object version = Napi::Object::New(env);
24
+ version.Set("version", "0.1.0");
25
+ version.Set("nwrfcsdk", nwrfcsdk);
26
+
27
+ return scope.Escape(version);
28
+ }
29
+
30
+ Napi::Object RegisterModule(Napi::Env env, Napi::Object exports) {
31
+ if (node_rfc::__env == nullptr) {
32
+ node_rfc::__env = env;
33
+ }
34
+
35
+ exports.Set("bindingVersions", BindingVersions(env));
36
+ Client::Init(env, exports);
37
+
38
+ return exports;
39
+ }
40
+
41
+ NODE_API_MODULE(NODE_GYP_MODULE_NAME, RegisterModule)
42
+
43
+ } // namespace node_rfc
@@ -0,0 +1,53 @@
1
+ // SPDX-FileCopyrightText: 2014 SAP SE Srdjan Boskovic <srdjan.boskovic@sap.com>
2
+ // SPDX-FileCopyrightText: 2026 sap-rfc-lite contributors
3
+ //
4
+ // SPDX-License-Identifier: Apache-2.0
5
+
6
+ #ifndef NodeRfc_Common_H
7
+ #define NodeRfc_Common_H
8
+
9
+ #include <napi.h>
10
+ #include <sapnwrfc.h>
11
+
12
+ // Error messages
13
+ #define ERRMSG_LENGTH 255
14
+ #define ERROR_PATH_NAME_LEN 48
15
+
16
+ // Unsigned and pointer types
17
+ #define uint_t uint32_t
18
+ #define pointer_t uintptr_t
19
+
20
+ // client binding version
21
+ #define NODERFC_VERSION "0.1.0"
22
+
23
+ // surpress unused parameter warnings
24
+ #define UNUSED(x) (void)(x)
25
+
26
+ //
27
+ // Client options constants
28
+ //
29
+ #define CLIENT_OPTION_BCD "bcd"
30
+ #define CLIENT_OPTION_DATE "date"
31
+ #define CLIENT_OPTION_TIME "time"
32
+ #define CLIENT_OPTION_FILTER "filter"
33
+ #define CLIENT_OPTION_STATELESS "stateless"
34
+ #define CLIENT_OPTION_TIMEOUT "timeout"
35
+
36
+ #define CALL_OPTION_KEY_NOTREQUESTED "notRequested"
37
+ #define CALL_OPTION_KEY_TIMEOUT CLIENT_OPTION_TIMEOUT
38
+
39
+ #define CLIENT_OPTION_BCD_STRING 0
40
+ #define CLIENT_OPTION_BCD_NUMBER 1
41
+ #define CLIENT_OPTION_BCD_FUNCTION 2
42
+
43
+ #define ENV_UNDEFINED node_rfc::__env.Undefined()
44
+
45
+ // Minimal logging — no-op by default, stderr in debug builds
46
+ #ifdef SAP_RFC_LITE_DEBUG
47
+ #include <cstdio>
48
+ #define RFC_LOG(fmt, ...) fprintf(stderr, "[sap-rfc-lite] " fmt "\n", ##__VA_ARGS__)
49
+ #else
50
+ #define RFC_LOG(fmt, ...) ((void)0)
51
+ #endif
52
+
53
+ #endif