@homaiohq/napi-quickfix 0.0.0-stage → 0.2.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.
Files changed (104) hide show
  1. package/CMakeLists.txt +135 -0
  2. package/LICENSE +21 -0
  3. package/README.md +638 -2
  4. package/THIRD_PARTY_LICENSES +48 -0
  5. package/cpp/acceptor_wrap.cpp +468 -0
  6. package/cpp/acceptor_wrap.h +116 -0
  7. package/cpp/addon.cpp +87 -0
  8. package/cpp/application_bridge.cpp +466 -0
  9. package/cpp/application_bridge.h +204 -0
  10. package/cpp/data_dictionary_wrap.cpp +165 -0
  11. package/cpp/data_dictionary_wrap.h +59 -0
  12. package/cpp/engine_common.cpp +5 -0
  13. package/cpp/engine_common.h +127 -0
  14. package/cpp/engine_workers.h +167 -0
  15. package/cpp/errors.h +142 -0
  16. package/cpp/field_map_ops.h +492 -0
  17. package/cpp/group_wrap.cpp +221 -0
  18. package/cpp/group_wrap.h +76 -0
  19. package/cpp/initiator_wrap.cpp +492 -0
  20. package/cpp/initiator_wrap.h +104 -0
  21. package/cpp/message_wrap.cpp +288 -0
  22. package/cpp/message_wrap.h +95 -0
  23. package/cpp/session_id_wrap.cpp +91 -0
  24. package/cpp/session_id_wrap.h +46 -0
  25. package/cpp/session_op_gate.h +201 -0
  26. package/cpp/session_settings_wrap.cpp +98 -0
  27. package/cpp/session_settings_wrap.h +40 -0
  28. package/cpp/session_static.cpp +220 -0
  29. package/cpp/session_wrap.cpp +438 -0
  30. package/cpp/session_wrap.h +144 -0
  31. package/dist/cjs/acceptor.d.ts +29 -0
  32. package/dist/cjs/acceptor.js +38 -0
  33. package/dist/cjs/application.d.ts +115 -0
  34. package/dist/cjs/application.js +62 -0
  35. package/dist/cjs/data-dictionary.d.ts +67 -0
  36. package/dist/cjs/data-dictionary.js +105 -0
  37. package/dist/cjs/engine.d.ts +152 -0
  38. package/dist/cjs/engine.js +183 -0
  39. package/dist/cjs/enums.d.ts +56 -0
  40. package/dist/cjs/enums.js +44 -0
  41. package/dist/cjs/field-value.d.ts +12 -0
  42. package/dist/cjs/field-value.js +40 -0
  43. package/dist/cjs/generated/fields.d.ts +6122 -0
  44. package/dist/cjs/generated/fields.js +6127 -0
  45. package/dist/cjs/generated/values.d.ts +8548 -0
  46. package/dist/cjs/generated/values.js +8580 -0
  47. package/dist/cjs/group.d.ts +126 -0
  48. package/dist/cjs/group.js +185 -0
  49. package/dist/cjs/index.d.ts +68 -0
  50. package/dist/cjs/index.js +73 -0
  51. package/dist/cjs/initiator.d.ts +29 -0
  52. package/dist/cjs/initiator.js +38 -0
  53. package/dist/cjs/load-native.cjs +5 -0
  54. package/dist/cjs/message.d.ts +238 -0
  55. package/dist/cjs/message.js +299 -0
  56. package/dist/cjs/native.d.ts +325 -0
  57. package/dist/cjs/native.js +22 -0
  58. package/dist/cjs/package.json +1 -0
  59. package/dist/cjs/session-id.d.ts +51 -0
  60. package/dist/cjs/session-id.js +87 -0
  61. package/dist/cjs/session-settings.d.ts +46 -0
  62. package/dist/cjs/session-settings.js +75 -0
  63. package/dist/cjs/session.d.ts +213 -0
  64. package/dist/cjs/session.js +337 -0
  65. package/dist/esm/acceptor.d.ts +29 -0
  66. package/dist/esm/acceptor.js +34 -0
  67. package/dist/esm/application.d.ts +115 -0
  68. package/dist/esm/application.js +57 -0
  69. package/dist/esm/data-dictionary.d.ts +67 -0
  70. package/dist/esm/data-dictionary.js +101 -0
  71. package/dist/esm/engine.d.ts +152 -0
  72. package/dist/esm/engine.js +179 -0
  73. package/dist/esm/enums.d.ts +56 -0
  74. package/dist/esm/enums.js +35 -0
  75. package/dist/esm/field-value.d.ts +12 -0
  76. package/dist/esm/field-value.js +37 -0
  77. package/dist/esm/generated/fields.d.ts +6122 -0
  78. package/dist/esm/generated/fields.js +6124 -0
  79. package/dist/esm/generated/values.d.ts +8548 -0
  80. package/dist/esm/generated/values.js +8564 -0
  81. package/dist/esm/group.d.ts +126 -0
  82. package/dist/esm/group.js +181 -0
  83. package/dist/esm/index.d.ts +68 -0
  84. package/dist/esm/index.js +43 -0
  85. package/dist/esm/initiator.d.ts +29 -0
  86. package/dist/esm/initiator.js +34 -0
  87. package/dist/esm/load-native.cjs +5 -0
  88. package/dist/esm/message.d.ts +238 -0
  89. package/dist/esm/message.js +293 -0
  90. package/dist/esm/native.d.ts +325 -0
  91. package/dist/esm/native.js +16 -0
  92. package/dist/esm/session-id.d.ts +51 -0
  93. package/dist/esm/session-id.js +82 -0
  94. package/dist/esm/session-settings.d.ts +46 -0
  95. package/dist/esm/session-settings.js +71 -0
  96. package/dist/esm/session.d.ts +213 -0
  97. package/dist/esm/session.js +329 -0
  98. package/package.json +95 -4
  99. package/prebuilds/darwin-arm64/node.napi.node +0 -0
  100. package/prebuilds/darwin-x64/node.napi.node +0 -0
  101. package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
  102. package/prebuilds/linux-x64/node.napi.musl.node +0 -0
  103. package/prebuilds/win32-x64/node.napi.node +0 -0
  104. package/src/load-native.cjs +5 -0
@@ -0,0 +1,288 @@
1
+ #include "message_wrap.h"
2
+
3
+ #include <algorithm>
4
+ #include <string>
5
+ #include <utility>
6
+
7
+ #include "data_dictionary_wrap.h"
8
+ #include "errors.h"
9
+ #include "field_map_ops.h"
10
+ #include "quickfix/FieldNumbers.h"
11
+
12
+ namespace napi_quickfix {
13
+
14
+ Napi::FunctionReference MessageWrap::constructor_;
15
+
16
+ Napi::Object MessageWrap::Init(Napi::Env env, Napi::Object exports) {
17
+ Napi::Function func = DefineClass(
18
+ env, "Message",
19
+ {
20
+ InstanceMethod("getField", &MessageWrap::GetField),
21
+ InstanceMethod("setField", &MessageWrap::SetField),
22
+ InstanceMethod("isSetField", &MessageWrap::IsSetField),
23
+ InstanceMethod("removeField", &MessageWrap::RemoveField),
24
+ InstanceMethod("getFieldIfSet", &MessageWrap::GetFieldIfSet),
25
+ InstanceMethod("getHeaderField", &MessageWrap::GetHeaderField),
26
+ InstanceMethod("setHeaderField", &MessageWrap::SetHeaderField),
27
+ InstanceMethod("getTrailerField", &MessageWrap::GetTrailerField),
28
+ InstanceMethod("setTrailerField", &MessageWrap::SetTrailerField),
29
+ InstanceMethod("isEmpty", &MessageWrap::IsEmpty),
30
+ InstanceMethod("totalFields", &MessageWrap::TotalFields),
31
+ InstanceMethod("clear", &MessageWrap::Clear),
32
+ InstanceMethod("fields", &MessageWrap::Fields),
33
+ InstanceMethod("headerFields", &MessageWrap::HeaderFields),
34
+ InstanceMethod("trailerFields", &MessageWrap::TrailerFields),
35
+ InstanceMethod("addGroup", &MessageWrap::AddGroup),
36
+ InstanceMethod("getGroup", &MessageWrap::GetGroup),
37
+ InstanceMethod("replaceGroup", &MessageWrap::ReplaceGroup),
38
+ InstanceMethod("removeGroup", &MessageWrap::RemoveGroup),
39
+ InstanceMethod("hasGroup", &MessageWrap::HasGroup),
40
+ InstanceMethod("groupCount", &MessageWrap::GroupCount),
41
+ InstanceMethod("toString", &MessageWrap::ToString),
42
+ InstanceMethod("toPretty", &MessageWrap::ToPretty),
43
+ InstanceMethod("getMsgType", &MessageWrap::GetMsgType),
44
+ });
45
+
46
+ constructor_ = Napi::Persistent(func);
47
+ constructor_.SuppressDestruct();
48
+
49
+ exports.Set("MessageWrap", func);
50
+ return exports;
51
+ }
52
+
53
+ // Both construct an empty MessageWrap then fill its (empty) FIX::Message. A
54
+ // move keeps the nested entries typed by itself: FieldMap's move assignment
55
+ // takes the entry pointers over.
56
+ Napi::Object MessageWrap::NewInstance(Napi::Env env, const FIX::Message& msg) {
57
+ Napi::Object obj = constructor_.New({});
58
+ MessageWrap* wrap = Napi::ObjectWrap<MessageWrap>::Unwrap(obj);
59
+ fieldmap::CloneMessage(wrap->message_, msg);
60
+ return obj;
61
+ }
62
+
63
+ Napi::Object MessageWrap::NewInstance(
64
+ Napi::Env env, FIX::Message&& msg,
65
+ std::shared_ptr<const FIX::DataDictionary> sessionDictionary) {
66
+ Napi::Object obj = constructor_.New({});
67
+ MessageWrap* wrap = Napi::ObjectWrap<MessageWrap>::Unwrap(obj);
68
+ wrap->message_ = std::move(msg);
69
+ wrap->sessionDictionary_ = std::move(sessionDictionary);
70
+ return obj;
71
+ }
72
+
73
+ MessageWrap* MessageWrap::UnwrapArg(Napi::Env env, Napi::Value value,
74
+ const char* argName) {
75
+ if (!value.IsObject() ||
76
+ !value.As<Napi::Object>().InstanceOf(constructor_.Value())) {
77
+ throw Napi::TypeError::New(
78
+ env, std::string(argName) + " must be a Message instance");
79
+ }
80
+ return Napi::ObjectWrap<MessageWrap>::Unwrap(value.As<Napi::Object>());
81
+ }
82
+
83
+ MessageWrap::MessageWrap(const Napi::CallbackInfo& info)
84
+ : Napi::ObjectWrap<MessageWrap>(info) {
85
+ Napi::Env env = info.Env();
86
+ if (info.Length() == 0) {
87
+ // Empty message.
88
+ return;
89
+ }
90
+ if (!info[0].IsString()) {
91
+ throw Napi::TypeError::New(
92
+ env,
93
+ "new Message(raw: string, validate?: boolean, "
94
+ "sessionDictionary?: DataDictionary, "
95
+ "applicationDictionary?: DataDictionary)");
96
+ }
97
+ const std::string raw = info[0].As<Napi::String>().Utf8Value();
98
+ bool validate = false;
99
+ if (info.Length() >= 2 && !fieldmap::IsNullish(info[1])) {
100
+ validate = info[1].ToBoolean().Value();
101
+ }
102
+ const FIX::DataDictionary* sessionDD = nullptr;
103
+ const FIX::DataDictionary* appDD = nullptr;
104
+ if (info.Length() >= 3 && !fieldmap::IsNullish(info[2])) {
105
+ sessionDictionary_ =
106
+ DataDictionaryWrap::UnwrapArg(env, info[2], "sessionDictionary")
107
+ ->Shared();
108
+ sessionDD = sessionDictionary_.get();
109
+ }
110
+ if (info.Length() >= 4 && !fieldmap::IsNullish(info[3])) {
111
+ appDD = &DataDictionaryWrap::UnwrapArg(env, info[3], "applicationDictionary")
112
+ ->Dictionary();
113
+ }
114
+ NQ_TRY(env) {
115
+ if (sessionDD != nullptr || appDD != nullptr) {
116
+ // The dictionaries are read only during this call; the wrapper objects
117
+ // are kept alive by the caller's arguments for its duration.
118
+ message_.setString(raw, validate, sessionDD, appDD);
119
+ } else {
120
+ message_.setString(raw, validate);
121
+ }
122
+ } NQ_CATCH(env)
123
+ }
124
+
125
+ namespace {
126
+
127
+ bool Holds(const FIX::FieldMap& map, int tag) {
128
+ return map.isSetField(tag) || map.hasGroup(tag);
129
+ }
130
+
131
+ } // namespace
132
+
133
+ // Auto-route standard header/trailer fields (MsgType, SenderCompID, CheckSum,
134
+ // NoHops, ...) and the ones the session dictionary declares to the right
135
+ // section, as the parser does, so callers don't have to know which section a
136
+ // tag belongs to, and a dictionary header field that is removed and set again
137
+ // goes back to the header. Without a dictionary (a message built in JS or
138
+ // parsed without one), any other tag is a body field unless the header or
139
+ // trailer already holds it, so reads find such a field and setField /
140
+ // removeField edit it in place rather than adding a body duplicate. A tag
141
+ // held nowhere stays a body field.
142
+ FIX::FieldMap& MessageWrap::SectionFor(int tag) {
143
+ const FIX::DataDictionary* dd = sessionDictionary_.get();
144
+ if (FIX::Message::isHeaderField(tag, dd)) {
145
+ return message_.getHeader();
146
+ }
147
+ if (FIX::Message::isTrailerField(tag, dd)) {
148
+ return message_.getTrailer();
149
+ }
150
+ if (Holds(message_, tag)) {
151
+ return message_;
152
+ }
153
+ if (Holds(message_.getHeader(), tag)) {
154
+ return message_.getHeader();
155
+ }
156
+ if (Holds(message_.getTrailer(), tag)) {
157
+ return message_.getTrailer();
158
+ }
159
+ return message_;
160
+ }
161
+
162
+ #define NQ_ROUTED [this](int tag) -> FIX::FieldMap& { return SectionFor(tag); }
163
+ #define NQ_HEADER [this](int) -> FIX::FieldMap& { return message_.getHeader(); }
164
+ #define NQ_TRAILER [this](int) -> FIX::FieldMap& { return message_.getTrailer(); }
165
+
166
+ Napi::Value MessageWrap::GetField(const Napi::CallbackInfo& info) {
167
+ return fieldmap::GetField(info, NQ_ROUTED);
168
+ }
169
+
170
+ Napi::Value MessageWrap::SetField(const Napi::CallbackInfo& info) {
171
+ return fieldmap::SetField(info, NQ_ROUTED);
172
+ }
173
+
174
+ Napi::Value MessageWrap::IsSetField(const Napi::CallbackInfo& info) {
175
+ return fieldmap::IsSetField(info, NQ_ROUTED);
176
+ }
177
+
178
+ Napi::Value MessageWrap::RemoveField(const Napi::CallbackInfo& info) {
179
+ return fieldmap::RemoveField(info, NQ_ROUTED);
180
+ }
181
+
182
+ Napi::Value MessageWrap::GetFieldIfSet(const Napi::CallbackInfo& info) {
183
+ return fieldmap::GetFieldIfSet(info, NQ_ROUTED);
184
+ }
185
+
186
+ Napi::Value MessageWrap::GetHeaderField(const Napi::CallbackInfo& info) {
187
+ return fieldmap::GetField(info, NQ_HEADER);
188
+ }
189
+
190
+ Napi::Value MessageWrap::SetHeaderField(const Napi::CallbackInfo& info) {
191
+ return fieldmap::SetField(info, NQ_HEADER);
192
+ }
193
+
194
+ Napi::Value MessageWrap::GetTrailerField(const Napi::CallbackInfo& info) {
195
+ return fieldmap::GetField(info, NQ_TRAILER);
196
+ }
197
+
198
+ Napi::Value MessageWrap::SetTrailerField(const Napi::CallbackInfo& info) {
199
+ return fieldmap::SetField(info, NQ_TRAILER);
200
+ }
201
+
202
+ // Header, body and trailer (FIX::Message::isEmpty, not FieldMap's body-only
203
+ // one), like clear().
204
+ Napi::Value MessageWrap::IsEmpty(const Napi::CallbackInfo& info) {
205
+ Napi::Env env = info.Env();
206
+ NQ_TRY(env) {
207
+ return Napi::Boolean::New(env, message_.isEmpty());
208
+ } NQ_CATCH(env)
209
+ }
210
+
211
+ Napi::Value MessageWrap::TotalFields(const Napi::CallbackInfo& info) {
212
+ return fieldmap::TotalFields(info.Env(), message_);
213
+ }
214
+
215
+ // Empties header, body and trailer.
216
+ Napi::Value MessageWrap::Clear(const Napi::CallbackInfo& info) {
217
+ Napi::Env env = info.Env();
218
+ NQ_TRY(env) {
219
+ message_.clear();
220
+ } NQ_CATCH(env)
221
+ return env.Undefined();
222
+ }
223
+
224
+ Napi::Value MessageWrap::Fields(const Napi::CallbackInfo& info) {
225
+ return fieldmap::Fields(info.Env(), message_);
226
+ }
227
+
228
+ Napi::Value MessageWrap::HeaderFields(const Napi::CallbackInfo& info) {
229
+ return fieldmap::Fields(info.Env(), message_.getHeader());
230
+ }
231
+
232
+ Napi::Value MessageWrap::TrailerFields(const Napi::CallbackInfo& info) {
233
+ return fieldmap::Fields(info.Env(), message_.getTrailer());
234
+ }
235
+
236
+ Napi::Value MessageWrap::AddGroup(const Napi::CallbackInfo& info) {
237
+ return fieldmap::AddGroup(info, NQ_ROUTED);
238
+ }
239
+
240
+ Napi::Value MessageWrap::GetGroup(const Napi::CallbackInfo& info) {
241
+ return fieldmap::GetGroup(info, NQ_ROUTED);
242
+ }
243
+
244
+ Napi::Value MessageWrap::ReplaceGroup(const Napi::CallbackInfo& info) {
245
+ return fieldmap::ReplaceGroup(info, NQ_ROUTED);
246
+ }
247
+
248
+ Napi::Value MessageWrap::RemoveGroup(const Napi::CallbackInfo& info) {
249
+ return fieldmap::RemoveGroup(info, NQ_ROUTED);
250
+ }
251
+
252
+ Napi::Value MessageWrap::HasGroup(const Napi::CallbackInfo& info) {
253
+ return fieldmap::HasGroup(info, NQ_ROUTED);
254
+ }
255
+
256
+ Napi::Value MessageWrap::GroupCount(const Napi::CallbackInfo& info) {
257
+ return fieldmap::GroupCount(info, NQ_ROUTED);
258
+ }
259
+
260
+ #undef NQ_ROUTED
261
+ #undef NQ_HEADER
262
+ #undef NQ_TRAILER
263
+
264
+ Napi::Value MessageWrap::ToString(const Napi::CallbackInfo& info) {
265
+ Napi::Env env = info.Env();
266
+ NQ_TRY(env) {
267
+ return Napi::String::New(env, message_.toString());
268
+ } NQ_CATCH(env)
269
+ }
270
+
271
+ Napi::Value MessageWrap::ToPretty(const Napi::CallbackInfo& info) {
272
+ Napi::Env env = info.Env();
273
+ NQ_TRY(env) {
274
+ std::string s = message_.toString();
275
+ std::replace(s.begin(), s.end(), '\x01', '|');
276
+ return Napi::String::New(env, s);
277
+ } NQ_CATCH(env)
278
+ }
279
+
280
+ Napi::Value MessageWrap::GetMsgType(const Napi::CallbackInfo& info) {
281
+ Napi::Env env = info.Env();
282
+ NQ_TRY(env) {
283
+ const std::string& msgType = message_.getHeader().getField(FIX::FIELD::MsgType);
284
+ return Napi::String::New(env, msgType);
285
+ } NQ_CATCH(env)
286
+ }
287
+
288
+ } // namespace napi_quickfix
@@ -0,0 +1,95 @@
1
+ #ifndef NAPI_QUICKFIX_MESSAGE_WRAP_H
2
+ #define NAPI_QUICKFIX_MESSAGE_WRAP_H
3
+
4
+ #include <napi.h>
5
+
6
+ #include <memory>
7
+
8
+ #include "quickfix/DataDictionary.h"
9
+ #include "quickfix/Message.h"
10
+
11
+ namespace napi_quickfix {
12
+
13
+ // Napi::ObjectWrap over FIX::Message.
14
+ //
15
+ // new MessageWrap()
16
+ // new MessageWrap(raw: string, validate?: boolean = false,
17
+ // sessionDictionary?: DataDictionary,
18
+ // applicationDictionary?: DataDictionary)
19
+ //
20
+ // With a dictionary the raw string is parsed structurally (repeating groups
21
+ // become nested FieldMaps); without one it is parsed flat, as before.
22
+ //
23
+ // Field methods (getField / setField / isSetField / removeField /
24
+ // getFieldIfSet) and group methods (addGroup / getGroup / replaceGroup /
25
+ // removeGroup / hasGroup / groupCount) auto-route standard header/trailer
26
+ // tags to the right section, as well as the header/trailer fields declared by
27
+ // the session dictionary the message was parsed or delivered with. Any other
28
+ // tag goes to the section that already holds it (body first). isEmpty and
29
+ // clear() cover all three sections; totalFields / fields read the body.
30
+ class MessageWrap : public Napi::ObjectWrap<MessageWrap> {
31
+ public:
32
+ static Napi::Object Init(Napi::Env env, Napi::Object exports);
33
+
34
+ // Build a JS MessageWrap holding a copy of `msg` (typed down to the last
35
+ // nested group entry, see fieldmap::CloneMessage), or taking `msg` over.
36
+ // The ApplicationBridge trampoline moves its own copy in, with the session
37
+ // dictionary that routes its fields (null: none).
38
+ static Napi::Object NewInstance(Napi::Env env, const FIX::Message& msg);
39
+ static Napi::Object NewInstance(
40
+ Napi::Env env, FIX::Message&& msg,
41
+ std::shared_ptr<const FIX::DataDictionary> sessionDictionary = nullptr);
42
+
43
+ explicit MessageWrap(const Napi::CallbackInfo& info);
44
+
45
+ // Internal accessor for other wrappers (validate, sendToTarget, bridge).
46
+ FIX::Message& Message() { return message_; }
47
+ const FIX::Message& Message() const { return message_; }
48
+
49
+ // Unwrap a JS value that must be a MessageWrap; throws Napi::TypeError if not.
50
+ static MessageWrap* UnwrapArg(Napi::Env env, Napi::Value value,
51
+ const char* argName);
52
+
53
+ private:
54
+ static Napi::FunctionReference constructor_;
55
+
56
+ // The section (header / body / trailer) that owns `tag`.
57
+ FIX::FieldMap& SectionFor(int tag);
58
+
59
+ Napi::Value GetField(const Napi::CallbackInfo& info);
60
+ Napi::Value SetField(const Napi::CallbackInfo& info);
61
+ Napi::Value IsSetField(const Napi::CallbackInfo& info);
62
+ Napi::Value RemoveField(const Napi::CallbackInfo& info);
63
+ Napi::Value GetFieldIfSet(const Napi::CallbackInfo& info);
64
+ Napi::Value GetHeaderField(const Napi::CallbackInfo& info);
65
+ Napi::Value SetHeaderField(const Napi::CallbackInfo& info);
66
+ Napi::Value GetTrailerField(const Napi::CallbackInfo& info);
67
+ Napi::Value SetTrailerField(const Napi::CallbackInfo& info);
68
+ Napi::Value IsEmpty(const Napi::CallbackInfo& info);
69
+ Napi::Value TotalFields(const Napi::CallbackInfo& info);
70
+ Napi::Value Clear(const Napi::CallbackInfo& info);
71
+ Napi::Value Fields(const Napi::CallbackInfo& info);
72
+ Napi::Value HeaderFields(const Napi::CallbackInfo& info);
73
+ Napi::Value TrailerFields(const Napi::CallbackInfo& info);
74
+
75
+ Napi::Value AddGroup(const Napi::CallbackInfo& info);
76
+ Napi::Value GetGroup(const Napi::CallbackInfo& info);
77
+ Napi::Value ReplaceGroup(const Napi::CallbackInfo& info);
78
+ Napi::Value RemoveGroup(const Napi::CallbackInfo& info);
79
+ Napi::Value HasGroup(const Napi::CallbackInfo& info);
80
+ Napi::Value GroupCount(const Napi::CallbackInfo& info);
81
+
82
+ Napi::Value ToString(const Napi::CallbackInfo& info);
83
+ Napi::Value ToPretty(const Napi::CallbackInfo& info);
84
+ Napi::Value GetMsgType(const Napi::CallbackInfo& info);
85
+
86
+ FIX::Message message_;
87
+ // The session dictionary whose header/trailer fields SectionFor routes
88
+ // (null: none). Shared, since the message may outlive the session or the
89
+ // JS DataDictionary it came from.
90
+ std::shared_ptr<const FIX::DataDictionary> sessionDictionary_;
91
+ };
92
+
93
+ } // namespace napi_quickfix
94
+
95
+ #endif // NAPI_QUICKFIX_MESSAGE_WRAP_H
@@ -0,0 +1,91 @@
1
+ #include "session_id_wrap.h"
2
+
3
+ #include <string>
4
+
5
+ #include "errors.h"
6
+
7
+ namespace napi_quickfix {
8
+
9
+ Napi::FunctionReference SessionIDWrap::constructor_;
10
+
11
+ Napi::Object SessionIDWrap::Init(Napi::Env env, Napi::Object exports) {
12
+ Napi::Function func = DefineClass(
13
+ env, "SessionID",
14
+ {
15
+ InstanceMethod("getBeginString", &SessionIDWrap::GetBeginString),
16
+ InstanceMethod("getSenderCompID", &SessionIDWrap::GetSenderCompID),
17
+ InstanceMethod("getTargetCompID", &SessionIDWrap::GetTargetCompID),
18
+ InstanceMethod("getSessionQualifier",
19
+ &SessionIDWrap::GetSessionQualifier),
20
+ InstanceMethod("toString", &SessionIDWrap::ToString),
21
+ });
22
+
23
+ constructor_ = Napi::Persistent(func);
24
+ constructor_.SuppressDestruct();
25
+
26
+ exports.Set("SessionIDWrap", func);
27
+ return exports;
28
+ }
29
+
30
+ Napi::Object SessionIDWrap::NewInstance(Napi::Env env,
31
+ const FIX::SessionID& id) {
32
+ Napi::Object obj = constructor_.New(
33
+ {Napi::String::New(env, id.getBeginString().getValue()),
34
+ Napi::String::New(env, id.getSenderCompID().getValue()),
35
+ Napi::String::New(env, id.getTargetCompID().getValue()),
36
+ Napi::String::New(env, id.getSessionQualifier())});
37
+ return obj;
38
+ }
39
+
40
+ SessionIDWrap* SessionIDWrap::UnwrapArg(Napi::Env env, Napi::Value value,
41
+ const char* argName) {
42
+ if (!value.IsObject() ||
43
+ !value.As<Napi::Object>().InstanceOf(constructor_.Value())) {
44
+ throw Napi::TypeError::New(
45
+ env, std::string(argName) + " must be a SessionID instance");
46
+ }
47
+ return Napi::ObjectWrap<SessionIDWrap>::Unwrap(value.As<Napi::Object>());
48
+ }
49
+
50
+ SessionIDWrap::SessionIDWrap(const Napi::CallbackInfo& info)
51
+ : Napi::ObjectWrap<SessionIDWrap>(info) {
52
+ Napi::Env env = info.Env();
53
+ if (info.Length() < 3 || !info[0].IsString() || !info[1].IsString() ||
54
+ !info[2].IsString()) {
55
+ throw Napi::TypeError::New(
56
+ env,
57
+ "new SessionID(beginString, senderCompID, targetCompID, qualifier?)");
58
+ }
59
+ std::string begin = info[0].As<Napi::String>().Utf8Value();
60
+ std::string sender = info[1].As<Napi::String>().Utf8Value();
61
+ std::string target = info[2].As<Napi::String>().Utf8Value();
62
+ std::string qualifier;
63
+ if (info.Length() >= 4 && info[3].IsString()) {
64
+ qualifier = info[3].As<Napi::String>().Utf8Value();
65
+ }
66
+ session_id_ = FIX::SessionID(begin, sender, target, qualifier);
67
+ }
68
+
69
+ Napi::Value SessionIDWrap::GetBeginString(const Napi::CallbackInfo& info) {
70
+ return Napi::String::New(info.Env(), session_id_.getBeginString().getValue());
71
+ }
72
+
73
+ Napi::Value SessionIDWrap::GetSenderCompID(const Napi::CallbackInfo& info) {
74
+ return Napi::String::New(info.Env(),
75
+ session_id_.getSenderCompID().getValue());
76
+ }
77
+
78
+ Napi::Value SessionIDWrap::GetTargetCompID(const Napi::CallbackInfo& info) {
79
+ return Napi::String::New(info.Env(),
80
+ session_id_.getTargetCompID().getValue());
81
+ }
82
+
83
+ Napi::Value SessionIDWrap::GetSessionQualifier(const Napi::CallbackInfo& info) {
84
+ return Napi::String::New(info.Env(), session_id_.getSessionQualifier());
85
+ }
86
+
87
+ Napi::Value SessionIDWrap::ToString(const Napi::CallbackInfo& info) {
88
+ return Napi::String::New(info.Env(), session_id_.toString());
89
+ }
90
+
91
+ } // namespace napi_quickfix
@@ -0,0 +1,46 @@
1
+ #ifndef NAPI_QUICKFIX_SESSION_ID_WRAP_H
2
+ #define NAPI_QUICKFIX_SESSION_ID_WRAP_H
3
+
4
+ #include <napi.h>
5
+
6
+ #include "quickfix/SessionID.h"
7
+
8
+ namespace napi_quickfix {
9
+
10
+ // Napi::ObjectWrap over FIX::SessionID.
11
+ //
12
+ // new SessionID(beginString, senderCompID, targetCompID, qualifier?)
13
+ //
14
+ // Getters: getBeginString / getSenderCompID / getTargetCompID /
15
+ // getSessionQualifier; plus toString.
16
+ class SessionIDWrap : public Napi::ObjectWrap<SessionIDWrap> {
17
+ public:
18
+ static Napi::Object Init(Napi::Env env, Napi::Object exports);
19
+
20
+ // Build a JS SessionID wrapping a copy of the given FIX::SessionID.
21
+ static Napi::Object NewInstance(Napi::Env env, const FIX::SessionID& id);
22
+
23
+ explicit SessionIDWrap(const Napi::CallbackInfo& info);
24
+
25
+ FIX::SessionID& SessionID() { return session_id_; }
26
+ const FIX::SessionID& SessionID() const { return session_id_; }
27
+
28
+ // Unwrap a JS value that must be a SessionID; throws Napi::TypeError if not.
29
+ static SessionIDWrap* UnwrapArg(Napi::Env env, Napi::Value value,
30
+ const char* argName);
31
+
32
+ private:
33
+ static Napi::FunctionReference constructor_;
34
+
35
+ Napi::Value GetBeginString(const Napi::CallbackInfo& info);
36
+ Napi::Value GetSenderCompID(const Napi::CallbackInfo& info);
37
+ Napi::Value GetTargetCompID(const Napi::CallbackInfo& info);
38
+ Napi::Value GetSessionQualifier(const Napi::CallbackInfo& info);
39
+ Napi::Value ToString(const Napi::CallbackInfo& info);
40
+
41
+ FIX::SessionID session_id_;
42
+ };
43
+
44
+ } // namespace napi_quickfix
45
+
46
+ #endif // NAPI_QUICKFIX_SESSION_ID_WRAP_H