@homaiohq/napi-quickfix 0.0.0-stage → 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/CMakeLists.txt +131 -0
- package/LICENSE +21 -0
- package/README.md +421 -2
- package/THIRD_PARTY_LICENSES +48 -0
- package/cpp/acceptor_wrap.cpp +234 -0
- package/cpp/acceptor_wrap.h +57 -0
- package/cpp/addon.cpp +83 -0
- package/cpp/application_bridge.cpp +382 -0
- package/cpp/application_bridge.h +151 -0
- package/cpp/data_dictionary_wrap.cpp +79 -0
- package/cpp/data_dictionary_wrap.h +37 -0
- package/cpp/engine_common.cpp +5 -0
- package/cpp/engine_common.h +19 -0
- package/cpp/engine_workers.h +86 -0
- package/cpp/enums.cpp +66 -0
- package/cpp/errors.h +142 -0
- package/cpp/initiator_wrap.cpp +255 -0
- package/cpp/initiator_wrap.h +69 -0
- package/cpp/message_wrap.cpp +195 -0
- package/cpp/message_wrap.h +53 -0
- package/cpp/session_id_wrap.cpp +91 -0
- package/cpp/session_id_wrap.h +46 -0
- package/cpp/session_settings_wrap.cpp +98 -0
- package/cpp/session_settings_wrap.h +40 -0
- package/cpp/session_static.cpp +93 -0
- package/dist/cjs/acceptor.d.ts +30 -0
- package/dist/cjs/acceptor.d.ts.map +1 -0
- package/dist/cjs/acceptor.js +39 -0
- package/dist/cjs/acceptor.js.map +1 -0
- package/dist/cjs/application.d.ts +116 -0
- package/dist/cjs/application.d.ts.map +1 -0
- package/dist/cjs/application.js +63 -0
- package/dist/cjs/application.js.map +1 -0
- package/dist/cjs/data-dictionary.d.ts +49 -0
- package/dist/cjs/data-dictionary.d.ts.map +1 -0
- package/dist/cjs/data-dictionary.js +77 -0
- package/dist/cjs/data-dictionary.js.map +1 -0
- package/dist/cjs/engine.d.ts +114 -0
- package/dist/cjs/engine.d.ts.map +1 -0
- package/dist/cjs/engine.js +138 -0
- package/dist/cjs/engine.js.map +1 -0
- package/dist/cjs/enums.d.ts +22 -0
- package/dist/cjs/enums.d.ts.map +1 -0
- package/dist/cjs/enums.js +49 -0
- package/dist/cjs/enums.js.map +1 -0
- package/dist/cjs/generated/fields.d.ts +6123 -0
- package/dist/cjs/generated/fields.d.ts.map +1 -0
- package/dist/cjs/generated/fields.js +6128 -0
- package/dist/cjs/generated/fields.js.map +1 -0
- package/dist/cjs/index.d.ts +47 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +73 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/initiator.d.ts +30 -0
- package/dist/cjs/initiator.d.ts.map +1 -0
- package/dist/cjs/initiator.js +39 -0
- package/dist/cjs/initiator.js.map +1 -0
- package/dist/cjs/load-native.cjs +5 -0
- package/dist/cjs/message.d.ts +114 -0
- package/dist/cjs/message.d.ts.map +1 -0
- package/dist/cjs/message.js +162 -0
- package/dist/cjs/message.js.map +1 -0
- package/dist/cjs/native.d.ts +163 -0
- package/dist/cjs/native.d.ts.map +1 -0
- package/dist/cjs/native.js +23 -0
- package/dist/cjs/native.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/session-id.d.ts +40 -0
- package/dist/cjs/session-id.d.ts.map +1 -0
- package/dist/cjs/session-id.js +67 -0
- package/dist/cjs/session-id.js.map +1 -0
- package/dist/cjs/session-settings.d.ts +47 -0
- package/dist/cjs/session-settings.d.ts.map +1 -0
- package/dist/cjs/session-settings.js +76 -0
- package/dist/cjs/session-settings.js.map +1 -0
- package/dist/esm/acceptor.d.ts +30 -0
- package/dist/esm/acceptor.d.ts.map +1 -0
- package/dist/esm/acceptor.js +35 -0
- package/dist/esm/acceptor.js.map +1 -0
- package/dist/esm/application.d.ts +116 -0
- package/dist/esm/application.d.ts.map +1 -0
- package/dist/esm/application.js +58 -0
- package/dist/esm/application.js.map +1 -0
- package/dist/esm/data-dictionary.d.ts +49 -0
- package/dist/esm/data-dictionary.d.ts.map +1 -0
- package/dist/esm/data-dictionary.js +73 -0
- package/dist/esm/data-dictionary.js.map +1 -0
- package/dist/esm/engine.d.ts +114 -0
- package/dist/esm/engine.d.ts.map +1 -0
- package/dist/esm/engine.js +134 -0
- package/dist/esm/engine.js.map +1 -0
- package/dist/esm/enums.d.ts +22 -0
- package/dist/esm/enums.d.ts.map +1 -0
- package/dist/esm/enums.js +45 -0
- package/dist/esm/enums.js.map +1 -0
- package/dist/esm/generated/fields.d.ts +6123 -0
- package/dist/esm/generated/fields.d.ts.map +1 -0
- package/dist/esm/generated/fields.js +6125 -0
- package/dist/esm/generated/fields.js.map +1 -0
- package/dist/esm/index.d.ts +47 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +52 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/initiator.d.ts +30 -0
- package/dist/esm/initiator.d.ts.map +1 -0
- package/dist/esm/initiator.js +35 -0
- package/dist/esm/initiator.js.map +1 -0
- package/dist/esm/load-native.cjs +5 -0
- package/dist/esm/message.d.ts +114 -0
- package/dist/esm/message.d.ts.map +1 -0
- package/dist/esm/message.js +156 -0
- package/dist/esm/message.js.map +1 -0
- package/dist/esm/native.d.ts +163 -0
- package/dist/esm/native.d.ts.map +1 -0
- package/dist/esm/native.js +17 -0
- package/dist/esm/native.js.map +1 -0
- package/dist/esm/session-id.d.ts +40 -0
- package/dist/esm/session-id.d.ts.map +1 -0
- package/dist/esm/session-id.js +63 -0
- package/dist/esm/session-id.js.map +1 -0
- package/dist/esm/session-settings.d.ts +47 -0
- package/dist/esm/session-settings.d.ts.map +1 -0
- package/dist/esm/session-settings.js +72 -0
- package/dist/esm/session-settings.js.map +1 -0
- package/package.json +83 -4
- package/prebuilds/darwin-arm64/node.napi.node +0 -0
- package/prebuilds/darwin-x64/node.napi.node +0 -0
- package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
- package/prebuilds/linux-x64/node.napi.musl.node +0 -0
- package/prebuilds/win32-x64/node.napi.node +0 -0
- package/src/load-native.cjs +5 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
#include "acceptor_wrap.h"
|
|
2
|
+
|
|
3
|
+
#include <string>
|
|
4
|
+
|
|
5
|
+
#include "quickfix/FileLog.h"
|
|
6
|
+
#include "quickfix/FileStore.h"
|
|
7
|
+
|
|
8
|
+
#include "engine_common.h"
|
|
9
|
+
#include "engine_workers.h"
|
|
10
|
+
#include "errors.h"
|
|
11
|
+
#include "session_settings_wrap.h"
|
|
12
|
+
|
|
13
|
+
namespace napi_quickfix {
|
|
14
|
+
|
|
15
|
+
Napi::FunctionReference AcceptorWrap::constructor_;
|
|
16
|
+
|
|
17
|
+
namespace {
|
|
18
|
+
|
|
19
|
+
std::string OptString(Napi::Object opts, const char* key,
|
|
20
|
+
const std::string& dflt) {
|
|
21
|
+
if (opts.Has(key)) {
|
|
22
|
+
Napi::Value v = opts.Get(key);
|
|
23
|
+
if (v.IsString()) return v.As<Napi::String>().Utf8Value();
|
|
24
|
+
}
|
|
25
|
+
return dflt;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
} // namespace
|
|
29
|
+
|
|
30
|
+
Napi::Object AcceptorWrap::Init(Napi::Env env, Napi::Object exports) {
|
|
31
|
+
Napi::Function func = DefineClass(
|
|
32
|
+
env, "Acceptor",
|
|
33
|
+
{
|
|
34
|
+
InstanceMethod("start", &AcceptorWrap::Start),
|
|
35
|
+
InstanceMethod("stop", &AcceptorWrap::Stop),
|
|
36
|
+
InstanceMethod("isLoggedOn", &AcceptorWrap::IsLoggedOn),
|
|
37
|
+
InstanceMethod("ref", &AcceptorWrap::Ref),
|
|
38
|
+
InstanceMethod("unref", &AcceptorWrap::Unref),
|
|
39
|
+
});
|
|
40
|
+
constructor_ = Napi::Persistent(func);
|
|
41
|
+
constructor_.SuppressDestruct();
|
|
42
|
+
exports.Set("AcceptorWrap", func);
|
|
43
|
+
return exports;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
AcceptorWrap::AcceptorWrap(const Napi::CallbackInfo& info)
|
|
47
|
+
: Napi::ObjectWrap<AcceptorWrap>(info) {
|
|
48
|
+
Napi::Env env = info.Env();
|
|
49
|
+
if (info.Length() < 1 || !info[0].IsObject()) {
|
|
50
|
+
throw Napi::TypeError::New(
|
|
51
|
+
env, "new Acceptor({ settings, handlers?, store?, log? })");
|
|
52
|
+
}
|
|
53
|
+
Napi::Object opts = info[0].As<Napi::Object>();
|
|
54
|
+
|
|
55
|
+
SessionSettingsWrap* settingsWrap =
|
|
56
|
+
SessionSettingsWrap::UnwrapArg(env, opts.Get("settings"), "settings");
|
|
57
|
+
|
|
58
|
+
Napi::Object handlers;
|
|
59
|
+
if (opts.Has("handlers") && opts.Get("handlers").IsObject()) {
|
|
60
|
+
handlers = opts.Get("handlers").As<Napi::Object>();
|
|
61
|
+
} else {
|
|
62
|
+
handlers = Napi::Object::New(env);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
std::string store = OptString(opts, "store", "file");
|
|
66
|
+
std::string log = OptString(opts, "log", "screen");
|
|
67
|
+
|
|
68
|
+
const FIX::SessionSettings& settings = settingsWrap->Settings();
|
|
69
|
+
|
|
70
|
+
bridge_ = std::make_unique<ApplicationBridge>(env, handlers);
|
|
71
|
+
|
|
72
|
+
NQ_TRY(env) {
|
|
73
|
+
if (store == "memory") {
|
|
74
|
+
storeFactory_ = std::make_unique<FIX::MemoryStoreFactory>();
|
|
75
|
+
} else {
|
|
76
|
+
storeFactory_ = std::make_unique<FIX::FileStoreFactory>(settings);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (log == "none") {
|
|
80
|
+
logFactory_ = std::make_unique<NullLogFactory>();
|
|
81
|
+
} else if (log == "file") {
|
|
82
|
+
logFactory_ = std::make_unique<FIX::FileLogFactory>(settings);
|
|
83
|
+
} else {
|
|
84
|
+
logFactory_ = std::make_unique<FIX::ScreenLogFactory>(settings);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
acceptor_ = std::make_unique<FIX::SocketAcceptor>(
|
|
88
|
+
*bridge_, *storeFactory_, settings, *logFactory_);
|
|
89
|
+
} NQ_CATCH(env)
|
|
90
|
+
|
|
91
|
+
// Deterministic teardown on env shutdown, before the TSFN is finalized. See
|
|
92
|
+
// InitiatorWrap for the rationale.
|
|
93
|
+
env_ = env;
|
|
94
|
+
cleanupHook_ = env.AddCleanupHook(&AcceptorWrap::CleanupEntry, this);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
void AcceptorWrap::CleanupEntry(AcceptorWrap* self) {
|
|
98
|
+
self->cleanupHookFired_ = true;
|
|
99
|
+
self->Teardown(true);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
AcceptorWrap::~AcceptorWrap() {
|
|
103
|
+
if (!cleanupHookFired_ && !cleanupHook_.IsEmpty() && env_ != nullptr) {
|
|
104
|
+
cleanupHook_.Remove(env_);
|
|
105
|
+
}
|
|
106
|
+
Teardown(true);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
void AcceptorWrap::Teardown(bool force) {
|
|
110
|
+
// Runs on the MAIN thread. Ordering (see InitiatorWrap::Teardown for detail):
|
|
111
|
+
// 1. Deactivate the bridge so callbacks during stop() pass through without
|
|
112
|
+
// touching the TSFN or waiting on the frozen JS loop (breaks deadlock).
|
|
113
|
+
// 2. stop(force): joins the QuickFIX network threads.
|
|
114
|
+
// 3. Abort the TSFN: safe now that no producer thread remains.
|
|
115
|
+
if (stopped_) return;
|
|
116
|
+
stopped_ = true;
|
|
117
|
+
if (bridge_) {
|
|
118
|
+
bridge_->Deactivate();
|
|
119
|
+
}
|
|
120
|
+
if (acceptor_ && started_) {
|
|
121
|
+
try {
|
|
122
|
+
acceptor_->stop(force);
|
|
123
|
+
} catch (...) {
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (bridge_) {
|
|
127
|
+
bridge_->Abort();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
Napi::Value AcceptorWrap::Start(const Napi::CallbackInfo& info) {
|
|
132
|
+
Napi::Env env = info.Env();
|
|
133
|
+
auto deferred = Napi::Promise::Deferred::New(env);
|
|
134
|
+
if (stopped_) {
|
|
135
|
+
deferred.Reject(Napi::Error::New(env, "Acceptor has been stopped").Value());
|
|
136
|
+
return deferred.Promise();
|
|
137
|
+
}
|
|
138
|
+
if (started_) {
|
|
139
|
+
deferred.Resolve(env.Undefined());
|
|
140
|
+
return deferred.Promise();
|
|
141
|
+
}
|
|
142
|
+
if (busy_) {
|
|
143
|
+
deferred.Reject(
|
|
144
|
+
Napi::Error::New(env, "Acceptor start/stop already in progress")
|
|
145
|
+
.Value());
|
|
146
|
+
return deferred.Promise();
|
|
147
|
+
}
|
|
148
|
+
busy_ = true;
|
|
149
|
+
started_ = true; // optimistic; reset in onSettled on failure
|
|
150
|
+
|
|
151
|
+
FIX::SocketAcceptor* acceptor = acceptor_.get();
|
|
152
|
+
auto* self = this;
|
|
153
|
+
auto* worker = new EngineOpWorker(
|
|
154
|
+
env, info.This().As<Napi::Object>(),
|
|
155
|
+
[acceptor]() { acceptor->start(); },
|
|
156
|
+
[self](bool ok) {
|
|
157
|
+
self->busy_ = false;
|
|
158
|
+
if (!ok) self->started_ = false;
|
|
159
|
+
});
|
|
160
|
+
Napi::Promise promise = worker->Promise();
|
|
161
|
+
worker->Queue();
|
|
162
|
+
return promise;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
Napi::Value AcceptorWrap::Stop(const Napi::CallbackInfo& info) {
|
|
166
|
+
Napi::Env env = info.Env();
|
|
167
|
+
bool force = false;
|
|
168
|
+
if (info.Length() >= 1 && !info[0].IsUndefined()) {
|
|
169
|
+
force = info[0].ToBoolean().Value();
|
|
170
|
+
}
|
|
171
|
+
auto deferred = Napi::Promise::Deferred::New(env);
|
|
172
|
+
if (stopped_) {
|
|
173
|
+
deferred.Resolve(env.Undefined());
|
|
174
|
+
return deferred.Promise();
|
|
175
|
+
}
|
|
176
|
+
if (busy_) {
|
|
177
|
+
deferred.Reject(
|
|
178
|
+
Napi::Error::New(env, "Acceptor start/stop already in progress")
|
|
179
|
+
.Value());
|
|
180
|
+
return deferred.Promise();
|
|
181
|
+
}
|
|
182
|
+
if (!acceptor_ || !started_) {
|
|
183
|
+
stopped_ = true;
|
|
184
|
+
if (bridge_) bridge_->Release();
|
|
185
|
+
deferred.Resolve(env.Undefined());
|
|
186
|
+
return deferred.Promise();
|
|
187
|
+
}
|
|
188
|
+
busy_ = true;
|
|
189
|
+
stopped_ = true;
|
|
190
|
+
|
|
191
|
+
FIX::SocketAcceptor* acceptor = acceptor_.get();
|
|
192
|
+
ApplicationBridge* bridge = bridge_.get();
|
|
193
|
+
auto* self = this;
|
|
194
|
+
auto* worker = new EngineOpWorker(
|
|
195
|
+
env, info.This().As<Napi::Object>(),
|
|
196
|
+
[acceptor, force]() { acceptor->stop(force); },
|
|
197
|
+
[self, bridge, force](bool /*ok*/) {
|
|
198
|
+
self->busy_ = false;
|
|
199
|
+
if (bridge) {
|
|
200
|
+
if (force) {
|
|
201
|
+
bridge->Abort();
|
|
202
|
+
} else {
|
|
203
|
+
bridge->Release();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
Napi::Promise promise = worker->Promise();
|
|
208
|
+
worker->Queue();
|
|
209
|
+
return promise;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
Napi::Value AcceptorWrap::IsLoggedOn(const Napi::CallbackInfo& info) {
|
|
213
|
+
Napi::Env env = info.Env();
|
|
214
|
+
if (!acceptor_ || !started_ || stopped_) {
|
|
215
|
+
return Napi::Boolean::New(env, false);
|
|
216
|
+
}
|
|
217
|
+
NQ_TRY(env) {
|
|
218
|
+
return Napi::Boolean::New(env, acceptor_->isLoggedOn());
|
|
219
|
+
} NQ_CATCH(env)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
Napi::Value AcceptorWrap::Ref(const Napi::CallbackInfo& info) {
|
|
223
|
+
Napi::Env env = info.Env();
|
|
224
|
+
if (bridge_) bridge_->Ref(env);
|
|
225
|
+
return info.This();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
Napi::Value AcceptorWrap::Unref(const Napi::CallbackInfo& info) {
|
|
229
|
+
Napi::Env env = info.Env();
|
|
230
|
+
if (bridge_) bridge_->Unref(env);
|
|
231
|
+
return info.This();
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
} // namespace napi_quickfix
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#ifndef NAPI_QUICKFIX_ACCEPTOR_WRAP_H
|
|
2
|
+
#define NAPI_QUICKFIX_ACCEPTOR_WRAP_H
|
|
3
|
+
|
|
4
|
+
#include <napi.h>
|
|
5
|
+
|
|
6
|
+
#include <memory>
|
|
7
|
+
|
|
8
|
+
#include "quickfix/Log.h"
|
|
9
|
+
#include "quickfix/MessageStore.h"
|
|
10
|
+
#include "quickfix/SocketAcceptor.h"
|
|
11
|
+
|
|
12
|
+
#include "application_bridge.h"
|
|
13
|
+
|
|
14
|
+
namespace napi_quickfix {
|
|
15
|
+
|
|
16
|
+
// Napi::ObjectWrap over FIX::SocketAcceptor. Mirrors InitiatorWrap.
|
|
17
|
+
//
|
|
18
|
+
// new Acceptor({ settings, handlers?, store?, log? })
|
|
19
|
+
class AcceptorWrap : public Napi::ObjectWrap<AcceptorWrap> {
|
|
20
|
+
public:
|
|
21
|
+
static Napi::Object Init(Napi::Env env, Napi::Object exports);
|
|
22
|
+
explicit AcceptorWrap(const Napi::CallbackInfo& info);
|
|
23
|
+
~AcceptorWrap() override;
|
|
24
|
+
|
|
25
|
+
private:
|
|
26
|
+
static Napi::FunctionReference constructor_;
|
|
27
|
+
|
|
28
|
+
Napi::Value Start(const Napi::CallbackInfo& info);
|
|
29
|
+
Napi::Value Stop(const Napi::CallbackInfo& info);
|
|
30
|
+
Napi::Value IsLoggedOn(const Napi::CallbackInfo& info);
|
|
31
|
+
Napi::Value Ref(const Napi::CallbackInfo& info);
|
|
32
|
+
Napi::Value Unref(const Napi::CallbackInfo& info);
|
|
33
|
+
|
|
34
|
+
void Teardown(bool force);
|
|
35
|
+
|
|
36
|
+
// Destruct order: acceptor first (declared last), then log, store, bridge.
|
|
37
|
+
std::unique_ptr<ApplicationBridge> bridge_;
|
|
38
|
+
std::unique_ptr<FIX::MessageStoreFactory> storeFactory_;
|
|
39
|
+
std::unique_ptr<FIX::LogFactory> logFactory_;
|
|
40
|
+
std::unique_ptr<FIX::SocketAcceptor> acceptor_;
|
|
41
|
+
|
|
42
|
+
bool started_ = false;
|
|
43
|
+
bool stopped_ = false;
|
|
44
|
+
bool busy_ = false; // guards against overlapping start/stop AsyncWorkers
|
|
45
|
+
|
|
46
|
+
static void CleanupEntry(AcceptorWrap* self);
|
|
47
|
+
|
|
48
|
+
napi_env env_ = nullptr;
|
|
49
|
+
// Runs Teardown on the MAIN thread during environment shutdown, BEFORE N-API
|
|
50
|
+
// finalizes the TSFN. See InitiatorWrap for the full rationale.
|
|
51
|
+
Napi::Env::CleanupHook<void (*)(AcceptorWrap*), AcceptorWrap> cleanupHook_;
|
|
52
|
+
bool cleanupHookFired_ = false;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
} // namespace napi_quickfix
|
|
56
|
+
|
|
57
|
+
#endif // NAPI_QUICKFIX_ACCEPTOR_WRAP_H
|
package/cpp/addon.cpp
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// Module init for @homaiohq/napi-quickfix: registers all wrappers, enums, and
|
|
2
|
+
// module-level functions.
|
|
3
|
+
|
|
4
|
+
#include <napi.h>
|
|
5
|
+
|
|
6
|
+
#include <exception>
|
|
7
|
+
#include <string>
|
|
8
|
+
|
|
9
|
+
#include "quickfix/Exceptions.h"
|
|
10
|
+
#include "quickfix/Field.h"
|
|
11
|
+
#include "quickfix/FieldNumbers.h"
|
|
12
|
+
#include "quickfix/Message.h"
|
|
13
|
+
|
|
14
|
+
#include "acceptor_wrap.h"
|
|
15
|
+
#include "data_dictionary_wrap.h"
|
|
16
|
+
#include "initiator_wrap.h"
|
|
17
|
+
#include "message_wrap.h"
|
|
18
|
+
#include "session_id_wrap.h"
|
|
19
|
+
#include "session_settings_wrap.h"
|
|
20
|
+
|
|
21
|
+
namespace napi_quickfix {
|
|
22
|
+
|
|
23
|
+
// Defined in session_static.cpp / enums.cpp.
|
|
24
|
+
void RegisterSessionStatic(Napi::Env env, Napi::Object exports);
|
|
25
|
+
void RegisterEnums(Napi::Env env, Napi::Object exports);
|
|
26
|
+
|
|
27
|
+
namespace {
|
|
28
|
+
|
|
29
|
+
// Keep in sync with package.json "version".
|
|
30
|
+
constexpr const char* kAddonVersion = "0.1.0";
|
|
31
|
+
|
|
32
|
+
Napi::Value Version(const Napi::CallbackInfo& info) {
|
|
33
|
+
return Napi::String::New(info.Env(), kAddonVersion);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Phase-1 regression smoke: prove quickfix parsing still links & works.
|
|
37
|
+
Napi::Value QuickfixParseMsgType(const Napi::CallbackInfo& info) {
|
|
38
|
+
Napi::Env env = info.Env();
|
|
39
|
+
if (info.Length() < 1 || !info[0].IsString()) {
|
|
40
|
+
throw Napi::TypeError::New(
|
|
41
|
+
env, "quickfixParseMsgType(raw: string): expected a string argument");
|
|
42
|
+
}
|
|
43
|
+
const std::string raw = info[0].As<Napi::String>().Utf8Value();
|
|
44
|
+
try {
|
|
45
|
+
FIX::Message message(raw, /*validate=*/false);
|
|
46
|
+
const std::string& msgType = message.getHeader().getField(FIX::FIELD::MsgType);
|
|
47
|
+
return Napi::String::New(env, msgType);
|
|
48
|
+
} catch (const FIX::Exception& e) {
|
|
49
|
+
Napi::Error err = Napi::Error::New(env, e.what());
|
|
50
|
+
err.Set("fixError", Napi::String::New(env, "InvalidMessage"));
|
|
51
|
+
throw err;
|
|
52
|
+
} catch (const std::exception& e) {
|
|
53
|
+
throw Napi::Error::New(env, e.what());
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
|
58
|
+
exports.Set("version", Napi::Function::New(env, Version, "version"));
|
|
59
|
+
exports.Set("quickfixParseMsgType",
|
|
60
|
+
Napi::Function::New(env, QuickfixParseMsgType, "quickfixParseMsgType"));
|
|
61
|
+
|
|
62
|
+
MessageWrap::Init(env, exports);
|
|
63
|
+
SessionIDWrap::Init(env, exports);
|
|
64
|
+
SessionSettingsWrap::Init(env, exports);
|
|
65
|
+
DataDictionaryWrap::Init(env, exports);
|
|
66
|
+
InitiatorWrap::Init(env, exports);
|
|
67
|
+
AcceptorWrap::Init(env, exports);
|
|
68
|
+
|
|
69
|
+
RegisterSessionStatic(env, exports);
|
|
70
|
+
RegisterEnums(env, exports);
|
|
71
|
+
|
|
72
|
+
return exports;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
} // namespace
|
|
76
|
+
|
|
77
|
+
} // namespace napi_quickfix
|
|
78
|
+
|
|
79
|
+
static Napi::Object InitModule(Napi::Env env, Napi::Object exports) {
|
|
80
|
+
return napi_quickfix::Init(env, exports);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
NODE_API_MODULE(napi_quickfix, InitModule)
|