@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,221 @@
1
+ #include "group_wrap.h"
2
+
3
+ #include <string>
4
+ #include <unordered_set>
5
+ #include <vector>
6
+
7
+ #include "errors.h"
8
+ #include "field_map_ops.h"
9
+
10
+ namespace napi_quickfix {
11
+
12
+ Napi::FunctionReference GroupWrap::constructor_;
13
+
14
+ Napi::Object GroupWrap::Init(Napi::Env env, Napi::Object exports) {
15
+ Napi::Function func = DefineClass(
16
+ env, "Group",
17
+ {
18
+ InstanceMethod("field", &GroupWrap::Field),
19
+ InstanceMethod("delim", &GroupWrap::Delim),
20
+ InstanceMethod("getField", &GroupWrap::GetField),
21
+ InstanceMethod("setField", &GroupWrap::SetField),
22
+ InstanceMethod("isSetField", &GroupWrap::IsSetField),
23
+ InstanceMethod("removeField", &GroupWrap::RemoveField),
24
+ InstanceMethod("getFieldIfSet", &GroupWrap::GetFieldIfSet),
25
+ InstanceMethod("totalFields", &GroupWrap::TotalFields),
26
+ InstanceMethod("isEmpty", &GroupWrap::IsEmpty),
27
+ InstanceMethod("clear", &GroupWrap::Clear),
28
+ InstanceMethod("fields", &GroupWrap::Fields),
29
+ InstanceMethod("toString", &GroupWrap::ToString),
30
+ InstanceMethod("addGroup", &GroupWrap::AddGroup),
31
+ InstanceMethod("getGroup", &GroupWrap::GetGroup),
32
+ InstanceMethod("replaceGroup", &GroupWrap::ReplaceGroup),
33
+ InstanceMethod("removeGroup", &GroupWrap::RemoveGroup),
34
+ InstanceMethod("hasGroup", &GroupWrap::HasGroup),
35
+ InstanceMethod("groupCount", &GroupWrap::GroupCount),
36
+ });
37
+
38
+ constructor_ = Napi::Persistent(func);
39
+ constructor_.SuppressDestruct();
40
+
41
+ exports.Set("GroupWrap", func);
42
+ return exports;
43
+ }
44
+
45
+ // The entry travels to the constructor as an External, which JS code cannot
46
+ // forge, so the constructor can tell this internal path from a user call. The
47
+ // pointer is only read, and only during constructor_.New (Napi::External
48
+ // takes a non-const pointer, hence the cast).
49
+ Napi::Object GroupWrap::NewInstance(Napi::Env env, int tag, int delim,
50
+ const FIX::FieldMap& entry) {
51
+ return constructor_.New(
52
+ {Napi::External<FIX::FieldMap>::New(env,
53
+ const_cast<FIX::FieldMap*>(&entry)),
54
+ Napi::Number::New(env, tag), Napi::Number::New(env, delim)});
55
+ }
56
+
57
+ GroupWrap* GroupWrap::UnwrapArg(Napi::Env env, Napi::Value value,
58
+ const char* argName) {
59
+ if (!value.IsObject() ||
60
+ !value.As<Napi::Object>().InstanceOf(constructor_.Value())) {
61
+ throw Napi::TypeError::New(
62
+ env, std::string(argName) + " must be a Group instance");
63
+ }
64
+ return Napi::ObjectWrap<GroupWrap>::Unwrap(value.As<Napi::Object>());
65
+ }
66
+
67
+ const FIX::FieldMap* GroupWrap::EntryArg(const Napi::CallbackInfo& info) {
68
+ if (info.Length() == 3 && info[0].IsExternal()) {
69
+ return info[0].As<Napi::External<FIX::FieldMap>>().Data();
70
+ }
71
+ return nullptr;
72
+ }
73
+
74
+ // FIX::Group has no default constructor, so the member is built from the
75
+ // arguments in the initializer list. Returned as a prvalue: FIX::Group has no
76
+ // move constructor, so a named return would copy (and slice nested entries).
77
+ FIX::Group GroupWrap::MakeGroup(const Napi::CallbackInfo& info) {
78
+ Napi::Env env = info.Env();
79
+ if (EntryArg(info) != nullptr) {
80
+ // The constructor body clones the entry, field order included, over it.
81
+ return FIX::Group(info[1].As<Napi::Number>().Int32Value(),
82
+ info[2].As<Napi::Number>().Int32Value(),
83
+ fieldmap::PlaceholderOrder());
84
+ }
85
+ if (info.Length() < 2 || !info[0].IsNumber() || !info[1].IsNumber()) {
86
+ throw Napi::TypeError::New(
87
+ env, "new Group(field: number, delim: number, order?: number[])");
88
+ }
89
+ const int field = fieldmap::CoerceSetTag(env, info[0]);
90
+ const int delim =
91
+ fieldmap::CheckOrderTag(env, fieldmap::CoerceSetTag(env, info[1]));
92
+
93
+ if (info.Length() < 3 || fieldmap::IsNullish(info[2])) {
94
+ return FIX::Group(field, delim);
95
+ }
96
+ if (!info[2].IsArray()) {
97
+ throw Napi::TypeError::New(env, "order must be an array of field tags");
98
+ }
99
+ // QuickFIX reads the order array up to a 0 terminator, so 0 is not a valid
100
+ // entry; the delimiter must come first for the sort to be meaningful. A tag
101
+ // listed twice takes its last position (message_order::setOrder overwrites
102
+ // its rank), which could move the delimiter off the front: rejected.
103
+ Napi::Array arr = info[2].As<Napi::Array>();
104
+ std::vector<int> order;
105
+ std::unordered_set<int> seen;
106
+ order.reserve(arr.Length() + 1);
107
+ for (uint32_t i = 0; i < arr.Length(); i++) {
108
+ int tag;
109
+ if (!fieldmap::ToInteger(arr.Get(i), tag) || tag <= 0) {
110
+ throw Napi::TypeError::New(
111
+ env, "order must contain only positive integer field tags");
112
+ }
113
+ if (!seen.insert(tag).second) {
114
+ throw Napi::TypeError::New(
115
+ env, "order must not list field tag " + std::to_string(tag) +
116
+ " twice");
117
+ }
118
+ order.push_back(fieldmap::CheckOrderTag(env, tag));
119
+ }
120
+ if (order.empty()) {
121
+ return FIX::Group(field, delim);
122
+ }
123
+ if (order.front() != delim) {
124
+ throw Napi::TypeError::New(env, "order must start with the delimiter tag");
125
+ }
126
+ order.push_back(0);
127
+ return FIX::Group(field, delim, order.data());
128
+ }
129
+
130
+ GroupWrap::GroupWrap(const Napi::CallbackInfo& info)
131
+ : Napi::ObjectWrap<GroupWrap>(info), group_(MakeGroup(info)) {
132
+ if (const FIX::FieldMap* entry = EntryArg(info)) {
133
+ fieldmap::Clone(group_, *entry); // fields, order and typed nested entries
134
+ }
135
+ }
136
+
137
+ Napi::Value GroupWrap::Field(const Napi::CallbackInfo& info) {
138
+ return Napi::Number::New(info.Env(), group_.field());
139
+ }
140
+
141
+ Napi::Value GroupWrap::Delim(const Napi::CallbackInfo& info) {
142
+ return Napi::Number::New(info.Env(), group_.delim());
143
+ }
144
+
145
+ // A Group is a single FieldMap: every tag selects itself.
146
+ #define NQ_SELF [this](int) -> FIX::FieldMap& { return group_; }
147
+
148
+ Napi::Value GroupWrap::GetField(const Napi::CallbackInfo& info) {
149
+ return fieldmap::GetField(info, NQ_SELF);
150
+ }
151
+
152
+ Napi::Value GroupWrap::SetField(const Napi::CallbackInfo& info) {
153
+ return fieldmap::SetField(info, NQ_SELF);
154
+ }
155
+
156
+ Napi::Value GroupWrap::IsSetField(const Napi::CallbackInfo& info) {
157
+ return fieldmap::IsSetField(info, NQ_SELF);
158
+ }
159
+
160
+ Napi::Value GroupWrap::RemoveField(const Napi::CallbackInfo& info) {
161
+ return fieldmap::RemoveField(info, NQ_SELF);
162
+ }
163
+
164
+ Napi::Value GroupWrap::GetFieldIfSet(const Napi::CallbackInfo& info) {
165
+ return fieldmap::GetFieldIfSet(info, NQ_SELF);
166
+ }
167
+
168
+ Napi::Value GroupWrap::TotalFields(const Napi::CallbackInfo& info) {
169
+ return fieldmap::TotalFields(info.Env(), group_);
170
+ }
171
+
172
+ Napi::Value GroupWrap::IsEmpty(const Napi::CallbackInfo& info) {
173
+ return fieldmap::IsEmpty(info.Env(), group_);
174
+ }
175
+
176
+ Napi::Value GroupWrap::Clear(const Napi::CallbackInfo& info) {
177
+ return fieldmap::Clear(info.Env(), group_);
178
+ }
179
+
180
+ Napi::Value GroupWrap::Fields(const Napi::CallbackInfo& info) {
181
+ return fieldmap::Fields(info.Env(), group_);
182
+ }
183
+
184
+ // The entry's fields (and nested groups) as a SOH-delimited string, in the
185
+ // order they would be emitted on the wire.
186
+ Napi::Value GroupWrap::ToString(const Napi::CallbackInfo& info) {
187
+ Napi::Env env = info.Env();
188
+ NQ_TRY(env) {
189
+ std::string s;
190
+ group_.calculateString(s);
191
+ return Napi::String::New(env, s);
192
+ } NQ_CATCH(env)
193
+ }
194
+
195
+ Napi::Value GroupWrap::AddGroup(const Napi::CallbackInfo& info) {
196
+ return fieldmap::AddGroup(info, NQ_SELF);
197
+ }
198
+
199
+ Napi::Value GroupWrap::GetGroup(const Napi::CallbackInfo& info) {
200
+ return fieldmap::GetGroup(info, NQ_SELF);
201
+ }
202
+
203
+ Napi::Value GroupWrap::ReplaceGroup(const Napi::CallbackInfo& info) {
204
+ return fieldmap::ReplaceGroup(info, NQ_SELF);
205
+ }
206
+
207
+ Napi::Value GroupWrap::RemoveGroup(const Napi::CallbackInfo& info) {
208
+ return fieldmap::RemoveGroup(info, NQ_SELF);
209
+ }
210
+
211
+ Napi::Value GroupWrap::HasGroup(const Napi::CallbackInfo& info) {
212
+ return fieldmap::HasGroup(info, NQ_SELF);
213
+ }
214
+
215
+ Napi::Value GroupWrap::GroupCount(const Napi::CallbackInfo& info) {
216
+ return fieldmap::GroupCount(info, NQ_SELF);
217
+ }
218
+
219
+ #undef NQ_SELF
220
+
221
+ } // namespace napi_quickfix
@@ -0,0 +1,76 @@
1
+ #ifndef NAPI_QUICKFIX_GROUP_WRAP_H
2
+ #define NAPI_QUICKFIX_GROUP_WRAP_H
3
+
4
+ #include <napi.h>
5
+
6
+ #include "quickfix/Group.h"
7
+
8
+ namespace napi_quickfix {
9
+
10
+ // Napi::ObjectWrap over FIX::Group — one entry of a repeating group.
11
+ //
12
+ // new GroupWrap(field: number, delim: number, order?: number[])
13
+ //
14
+ // `field` is the group's count tag (e.g. 453 NoPartyIDs), `delim` the first tag
15
+ // of every entry (e.g. 448 PartyID), and `order` the optional full field order
16
+ // of an entry (delimiter first). Without `order`, fields sort delimiter-first
17
+ // then by tag number.
18
+ //
19
+ // Field methods: getField / setField / isSetField / removeField /
20
+ // getFieldIfSet / totalFields / isEmpty / clear / fields / toString.
21
+ // Nested groups: addGroup / getGroup / replaceGroup / removeGroup / hasGroup /
22
+ // groupCount. Group indices are 1-based, as in QuickFIX.
23
+ class GroupWrap : public Napi::ObjectWrap<GroupWrap> {
24
+ public:
25
+ static Napi::Object Init(Napi::Env env, Napi::Object exports);
26
+
27
+ // Build a JS GroupWrap holding a copy of `entry`, an entry of the `tag`
28
+ // repeating group delimited by `delim`. The copy keeps every nested entry
29
+ // typed (fieldmap::Clone), and bypasses the argument validation of the JS
30
+ // constructor: the entry already exists, there is nothing to validate.
31
+ static Napi::Object NewInstance(Napi::Env env, int tag, int delim,
32
+ const FIX::FieldMap& entry);
33
+
34
+ explicit GroupWrap(const Napi::CallbackInfo& info);
35
+
36
+ FIX::Group& Group() { return group_; }
37
+ const FIX::Group& Group() const { return group_; }
38
+
39
+ // Unwrap a JS value that must be a GroupWrap; throws Napi::TypeError if not.
40
+ static GroupWrap* UnwrapArg(Napi::Env env, Napi::Value value,
41
+ const char* argName);
42
+
43
+ private:
44
+ static Napi::FunctionReference constructor_;
45
+
46
+ // The entry NewInstance passes to the constructor, or null for a JS call.
47
+ static const FIX::FieldMap* EntryArg(const Napi::CallbackInfo& info);
48
+ static FIX::Group MakeGroup(const Napi::CallbackInfo& info);
49
+
50
+ Napi::Value Field(const Napi::CallbackInfo& info);
51
+ Napi::Value Delim(const Napi::CallbackInfo& info);
52
+
53
+ Napi::Value GetField(const Napi::CallbackInfo& info);
54
+ Napi::Value SetField(const Napi::CallbackInfo& info);
55
+ Napi::Value IsSetField(const Napi::CallbackInfo& info);
56
+ Napi::Value RemoveField(const Napi::CallbackInfo& info);
57
+ Napi::Value GetFieldIfSet(const Napi::CallbackInfo& info);
58
+ Napi::Value TotalFields(const Napi::CallbackInfo& info);
59
+ Napi::Value IsEmpty(const Napi::CallbackInfo& info);
60
+ Napi::Value Clear(const Napi::CallbackInfo& info);
61
+ Napi::Value Fields(const Napi::CallbackInfo& info);
62
+ Napi::Value ToString(const Napi::CallbackInfo& info);
63
+
64
+ Napi::Value AddGroup(const Napi::CallbackInfo& info);
65
+ Napi::Value GetGroup(const Napi::CallbackInfo& info);
66
+ Napi::Value ReplaceGroup(const Napi::CallbackInfo& info);
67
+ Napi::Value RemoveGroup(const Napi::CallbackInfo& info);
68
+ Napi::Value HasGroup(const Napi::CallbackInfo& info);
69
+ Napi::Value GroupCount(const Napi::CallbackInfo& info);
70
+
71
+ FIX::Group group_;
72
+ };
73
+
74
+ } // namespace napi_quickfix
75
+
76
+ #endif // NAPI_QUICKFIX_GROUP_WRAP_H