jspurefix 5.1.0 → 5.3.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 (159) hide show
  1. package/BACKPORT_PLAN.md +138 -79
  2. package/dist/buffer/fixml/fixml-view.js.map +1 -1
  3. package/dist/buffer/msg-encoder.js +34 -1
  4. package/dist/buffer/msg-encoder.js.map +1 -1
  5. package/dist/buffer/msg-parser.js +34 -1
  6. package/dist/buffer/msg-parser.js.map +1 -1
  7. package/dist/buffer/msg-view.js.map +1 -1
  8. package/dist/collections/index.js +1 -0
  9. package/dist/config/js-fix-config.d.ts +2 -0
  10. package/dist/config/js-fix-config.js.map +1 -1
  11. package/dist/config/winston-logger.js.map +1 -1
  12. package/dist/dict-parser.js +34 -1
  13. package/dist/dict-parser.js.map +1 -1
  14. package/dist/dictionary/compiler/enum-compiler.js +37 -4
  15. package/dist/dictionary/compiler/enum-compiler.js.map +1 -1
  16. package/dist/dictionary/compiler/msg-compiler.js +36 -3
  17. package/dist/dictionary/compiler/msg-compiler.js.map +1 -1
  18. package/dist/dictionary/compiler/standard-snippet.js +34 -1
  19. package/dist/dictionary/compiler/standard-snippet.js.map +1 -1
  20. package/dist/dictionary/contained/contained-field-set.js +2 -0
  21. package/dist/dictionary/contained/contained-field-set.js.map +1 -1
  22. package/dist/dictionary/definition/simple-field-definition.js +34 -1
  23. package/dist/dictionary/definition/simple-field-definition.js.map +1 -1
  24. package/dist/dictionary/fix-parser.js +34 -1
  25. package/dist/dictionary/fix-parser.js.map +1 -1
  26. package/dist/dictionary/parser/fix-repository/repository-type.js +1 -0
  27. package/dist/dictionary/parser/fix-repository/repository-xml-parser.js +35 -2
  28. package/dist/dictionary/parser/fix-repository/repository-xml-parser.js.map +1 -1
  29. package/dist/dictionary/parser/fixml/fields-parser.js.map +1 -1
  30. package/dist/dictionary/parser/fixml/fix-xsd-parser.js +34 -1
  31. package/dist/dictionary/parser/fixml/fix-xsd-parser.js.map +1 -1
  32. package/dist/dictionary/parser/fixml/include-graph.js +35 -2
  33. package/dist/dictionary/parser/fixml/include-graph.js.map +1 -1
  34. package/dist/dictionary/parser/fixml/node-definitions.js +1 -0
  35. package/dist/dictionary/parser/fixml/xsd-parser.js +34 -1
  36. package/dist/dictionary/parser/fixml/xsd-parser.js.map +1 -1
  37. package/dist/jsfix-cmd.js +39 -3
  38. package/dist/jsfix-cmd.js.map +1 -1
  39. package/dist/runtime/session-launcher.js +34 -1
  40. package/dist/runtime/session-launcher.js.map +1 -1
  41. package/dist/sample/http/oms/app.js +34 -1
  42. package/dist/sample/http/oms/app.js.map +1 -1
  43. package/dist/sample/tcp/recovering-skeleton/app.js +34 -1
  44. package/dist/sample/tcp/recovering-skeleton/app.js.map +1 -1
  45. package/dist/store/file-session-store.d.ts +42 -0
  46. package/dist/store/file-session-store.js +256 -0
  47. package/dist/store/file-session-store.js.map +1 -0
  48. package/dist/store/file-session-stream-provider.d.ts +25 -0
  49. package/dist/store/file-session-stream-provider.js +162 -0
  50. package/dist/store/file-session-stream-provider.js.map +1 -0
  51. package/dist/store/fix-msg-ascii-store-resend.js +1 -1
  52. package/dist/store/fix-msg-ascii-store-resend.js.map +1 -1
  53. package/dist/store/fix-session-store-factory.d.ts +13 -0
  54. package/dist/store/fix-session-store-factory.js +21 -0
  55. package/dist/store/fix-session-store-factory.js.map +1 -0
  56. package/dist/store/fix-session-store.d.ts +19 -0
  57. package/dist/store/fix-session-store.js +3 -0
  58. package/dist/store/fix-session-store.js.map +1 -0
  59. package/dist/store/index.d.ts +9 -0
  60. package/dist/store/index.js +9 -0
  61. package/dist/store/index.js.map +1 -1
  62. package/dist/store/memory-session-store.d.ts +27 -0
  63. package/dist/store/memory-session-store.js +104 -0
  64. package/dist/store/memory-session-store.js.map +1 -0
  65. package/dist/store/memory-session-stream-provider.d.ts +26 -0
  66. package/dist/store/memory-session-stream-provider.js +103 -0
  67. package/dist/store/memory-session-stream-provider.js.map +1 -0
  68. package/dist/store/session-id.d.ts +9 -0
  69. package/dist/store/session-id.js +55 -0
  70. package/dist/store/session-id.js.map +1 -0
  71. package/dist/store/session-stream-provider.d.ts +15 -0
  72. package/dist/store/session-stream-provider.js +3 -0
  73. package/dist/store/session-stream-provider.js.map +1 -0
  74. package/dist/store/store-config.d.ts +4 -0
  75. package/dist/store/store-config.js +3 -0
  76. package/dist/store/store-config.js.map +1 -0
  77. package/dist/transport/ascii/ascii-session.d.ts +12 -1
  78. package/dist/transport/ascii/ascii-session.js +154 -5
  79. package/dist/transport/ascii/ascii-session.js.map +1 -1
  80. package/dist/transport/duplex/http-duplex.js +4 -1
  81. package/dist/transport/duplex/http-duplex.js.map +1 -1
  82. package/dist/transport/duplex/tcp-duplex.js +34 -1
  83. package/dist/transport/duplex/tcp-duplex.js.map +1 -1
  84. package/dist/transport/fix-acceptor.js +34 -1
  85. package/dist/transport/fix-acceptor.js.map +1 -1
  86. package/dist/transport/fix-entity.js +34 -1
  87. package/dist/transport/fix-entity.js.map +1 -1
  88. package/dist/transport/fixml/fixml-msg-transmitter.js +1 -1
  89. package/dist/transport/fixml/fixml-msg-transmitter.js.map +1 -1
  90. package/dist/transport/http/http-acceptor.js +34 -1
  91. package/dist/transport/http/http-acceptor.js.map +1 -1
  92. package/dist/transport/msg-transmitter.js +34 -1
  93. package/dist/transport/msg-transmitter.js.map +1 -1
  94. package/dist/transport/session/a-session-msg-factory.d.ts +1 -1
  95. package/dist/transport/session/a-session-msg-factory.js.map +1 -1
  96. package/dist/transport/session/fix-clock.d.ts +6 -0
  97. package/dist/transport/session/fix-clock.js +10 -0
  98. package/dist/transport/session/fix-clock.js.map +1 -0
  99. package/dist/transport/session/fix-session.d.ts +1 -0
  100. package/dist/transport/session/fix-session.js +37 -1
  101. package/dist/transport/session/fix-session.js.map +1 -1
  102. package/dist/transport/session/index.d.ts +4 -0
  103. package/dist/transport/session/index.js +4 -0
  104. package/dist/transport/session/index.js.map +1 -1
  105. package/dist/transport/session/resend-request-manager.d.ts +69 -0
  106. package/dist/transport/session/resend-request-manager.js +208 -0
  107. package/dist/transport/session/resend-request-manager.js.map +1 -0
  108. package/dist/transport/session/session-description.d.ts +2 -0
  109. package/dist/transport/session/session-description.js.map +1 -1
  110. package/dist/transport/session/session-msg-factory.d.ts +1 -1
  111. package/dist/transport/session/session-msg-factory.js.map +1 -1
  112. package/dist/transport/session/session-sequence-coordinator.d.ts +38 -0
  113. package/dist/transport/session/session-sequence-coordinator.js +180 -0
  114. package/dist/transport/session/session-sequence-coordinator.js.map +1 -0
  115. package/dist/transport/session/session-sequence-store.d.ts +14 -0
  116. package/dist/transport/session/session-sequence-store.js +36 -0
  117. package/dist/transport/session/session-sequence-store.js.map +1 -0
  118. package/dist/transport/tcp/tcp-acceptor.js.map +1 -1
  119. package/dist/transport/tcp/tcp-initiator.js +34 -1
  120. package/dist/transport/tcp/tcp-initiator.js.map +1 -1
  121. package/dist/types/FIX4.4/index.js +1 -0
  122. package/dist/util/buffer-helper.js +34 -1
  123. package/dist/util/buffer-helper.js.map +1 -1
  124. package/dist/util/definition-factory.js +35 -2
  125. package/dist/util/definition-factory.js.map +1 -1
  126. package/jsfix.test_client.txt +67 -66
  127. package/jsfix.test_server.txt +64 -63
  128. package/package.json +11 -10
  129. package/src/buffer/fixml/fixml-view.ts +1 -1
  130. package/src/buffer/msg-view.ts +1 -1
  131. package/src/config/js-fix-config.ts +2 -0
  132. package/src/config/winston-logger.ts +3 -3
  133. package/src/dictionary/contained/contained-field-set.ts +2 -1
  134. package/src/dictionary/parser/fixml/fields-parser.ts +2 -2
  135. package/src/jsfix-cmd.ts +1 -1
  136. package/src/store/file-session-store.ts +294 -0
  137. package/src/store/file-session-stream-provider.ts +123 -0
  138. package/src/store/fix-msg-ascii-store-resend.ts +1 -1
  139. package/src/store/fix-session-store-factory.ts +31 -0
  140. package/src/store/fix-session-store.ts +37 -0
  141. package/src/store/index.ts +9 -0
  142. package/src/store/memory-session-store.ts +102 -0
  143. package/src/store/memory-session-stream-provider.ts +97 -0
  144. package/src/store/session-id.ts +32 -0
  145. package/src/store/session-stream-provider.ts +74 -0
  146. package/src/store/store-config.ts +15 -0
  147. package/src/transport/ascii/ascii-session.ts +218 -6
  148. package/src/transport/fixml/fixml-msg-transmitter.ts +1 -1
  149. package/src/transport/http/http-acceptor.ts +1 -1
  150. package/src/transport/session/a-session-msg-factory.ts +1 -1
  151. package/src/transport/session/fix-clock.ts +9 -0
  152. package/src/transport/session/fix-session.ts +5 -0
  153. package/src/transport/session/index.ts +4 -0
  154. package/src/transport/session/resend-request-manager.ts +268 -0
  155. package/src/transport/session/session-description.ts +2 -0
  156. package/src/transport/session/session-msg-factory.ts +1 -1
  157. package/src/transport/session/session-sequence-coordinator.ts +272 -0
  158. package/src/transport/session/session-sequence-store.ts +33 -0
  159. package/src/transport/tcp/tcp-acceptor.ts +2 -2
@@ -0,0 +1,256 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.FileSessionStore = void 0;
13
+ const fix_msg_store_record_1 = require("./fix-msg-store-record");
14
+ const file_session_stream_provider_1 = require("./file-session-stream-provider");
15
+ class FileSessionStore {
16
+ static createWithFiles(sessionId, directory) {
17
+ return new FileSessionStore(sessionId, new file_session_stream_provider_1.FileSessionStreamProvider(sessionId, directory), true);
18
+ }
19
+ constructor(sessionId, streamProvider, ownsProvider = false) {
20
+ this.sessionId = sessionId;
21
+ this.senderSeqNumValue = 1;
22
+ this.targetSeqNumValue = 1;
23
+ this.creationTimeValue = new Date();
24
+ this.headerIndex = new Map();
25
+ this.streamProvider = streamProvider;
26
+ this.ownsProvider = ownsProvider;
27
+ }
28
+ getStreamProvider() {
29
+ return this.streamProvider;
30
+ }
31
+ get senderSeqNum() {
32
+ return this.senderSeqNumValue;
33
+ }
34
+ set senderSeqNum(value) {
35
+ this.senderSeqNumValue = value;
36
+ }
37
+ get targetSeqNum() {
38
+ return this.targetSeqNumValue;
39
+ }
40
+ set targetSeqNum(value) {
41
+ this.targetSeqNumValue = value;
42
+ }
43
+ setSenderSeqNum(value) {
44
+ return __awaiter(this, void 0, void 0, function* () {
45
+ this.senderSeqNumValue = value;
46
+ yield this.persistSeqNums();
47
+ });
48
+ }
49
+ setTargetSeqNum(value) {
50
+ return __awaiter(this, void 0, void 0, function* () {
51
+ this.targetSeqNumValue = value;
52
+ yield this.persistSeqNums();
53
+ });
54
+ }
55
+ nextSenderSeqNum() {
56
+ return __awaiter(this, void 0, void 0, function* () {
57
+ const next = ++this.senderSeqNumValue;
58
+ yield this.persistSeqNums();
59
+ return next;
60
+ });
61
+ }
62
+ nextTargetSeqNum() {
63
+ return __awaiter(this, void 0, void 0, function* () {
64
+ const next = ++this.targetSeqNumValue;
65
+ yield this.persistSeqNums();
66
+ return next;
67
+ });
68
+ }
69
+ get creationTime() {
70
+ return this.creationTimeValue;
71
+ }
72
+ reset() {
73
+ return __awaiter(this, void 0, void 0, function* () {
74
+ this.senderSeqNumValue = 1;
75
+ this.targetSeqNumValue = 1;
76
+ this.creationTimeValue = new Date();
77
+ this.headerIndex.clear();
78
+ yield this.streamProvider.reset();
79
+ yield this.persistSeqNums();
80
+ yield this.persistSessionTime();
81
+ this.streamProvider.openBody();
82
+ });
83
+ }
84
+ put(record) {
85
+ return __awaiter(this, void 0, void 0, function* () {
86
+ if (record.encoded == null) {
87
+ throw new Error('Record must have encoded content');
88
+ }
89
+ const bytes = Buffer.from(record.encoded, 'utf8');
90
+ const length = bytes.length;
91
+ const offset = yield this.streamProvider.appendBody(bytes);
92
+ this.headerIndex.set(record.seqNum, { offset, length });
93
+ yield this.streamProvider.appendHeaderLine(`${record.seqNum},${offset},${length}`);
94
+ });
95
+ }
96
+ get(seqNum) {
97
+ return __awaiter(this, void 0, void 0, function* () {
98
+ const entry = this.headerIndex.get(seqNum);
99
+ if (!entry)
100
+ return null;
101
+ return yield this.readMessage(seqNum, entry.offset, entry.length);
102
+ });
103
+ }
104
+ getRange(fromSeqNum, toSeqNum) {
105
+ return __awaiter(this, void 0, void 0, function* () {
106
+ const results = [];
107
+ for (let seq = fromSeqNum; seq <= toSeqNum; seq++) {
108
+ const record = yield this.get(seq);
109
+ if (record) {
110
+ results.push(record);
111
+ }
112
+ }
113
+ return results;
114
+ });
115
+ }
116
+ initialize() {
117
+ return __awaiter(this, void 0, void 0, function* () {
118
+ yield this.loadSeqNums();
119
+ yield this.loadSessionTime();
120
+ yield this.loadHeaderIndex();
121
+ this.streamProvider.openBody();
122
+ });
123
+ }
124
+ flush() {
125
+ return __awaiter(this, void 0, void 0, function* () {
126
+ yield this.streamProvider.flush();
127
+ });
128
+ }
129
+ dispose() {
130
+ return __awaiter(this, void 0, void 0, function* () {
131
+ yield this.streamProvider.flush();
132
+ if (this.ownsProvider) {
133
+ yield this.streamProvider.dispose();
134
+ }
135
+ });
136
+ }
137
+ persistSeqNums() {
138
+ return __awaiter(this, void 0, void 0, function* () {
139
+ const sender = this.senderSeqNumValue.toString().padStart(20, ' ');
140
+ const target = this.targetSeqNumValue.toString().padStart(20, ' ');
141
+ yield this.streamProvider.writeSeqNums(`${sender} : ${target}`);
142
+ });
143
+ }
144
+ loadSeqNums() {
145
+ return __awaiter(this, void 0, void 0, function* () {
146
+ const content = yield this.streamProvider.readSeqNums();
147
+ if (content == null) {
148
+ this.senderSeqNumValue = 1;
149
+ this.targetSeqNumValue = 1;
150
+ return;
151
+ }
152
+ const parts = content.split(':');
153
+ if (parts.length === 2) {
154
+ this.senderSeqNumValue = parseInt(parts[0].trim(), 10) || 1;
155
+ this.targetSeqNumValue = parseInt(parts[1].trim(), 10) || 1;
156
+ }
157
+ });
158
+ }
159
+ persistSessionTime() {
160
+ return __awaiter(this, void 0, void 0, function* () {
161
+ yield this.streamProvider.writeSessionTime(FileSessionStore.formatSessionTime(this.creationTimeValue));
162
+ });
163
+ }
164
+ loadSessionTime() {
165
+ return __awaiter(this, void 0, void 0, function* () {
166
+ const content = yield this.streamProvider.readSessionTime();
167
+ if (content == null) {
168
+ this.creationTimeValue = new Date();
169
+ yield this.persistSessionTime();
170
+ return;
171
+ }
172
+ const parsed = FileSessionStore.parseSessionTime(content.trim());
173
+ this.creationTimeValue = parsed !== null && parsed !== void 0 ? parsed : new Date();
174
+ });
175
+ }
176
+ loadHeaderIndex() {
177
+ return __awaiter(this, void 0, void 0, function* () {
178
+ const lines = yield this.streamProvider.readHeaderLines();
179
+ for (const line of lines) {
180
+ if (!line.trim())
181
+ continue;
182
+ const parts = line.split(',');
183
+ if (parts.length === 3) {
184
+ const seqNum = parseInt(parts[0], 10);
185
+ const offset = parseInt(parts[1], 10);
186
+ const length = parseInt(parts[2], 10);
187
+ if (!isNaN(seqNum) && !isNaN(offset) && !isNaN(length)) {
188
+ this.headerIndex.set(seqNum, { offset, length });
189
+ }
190
+ }
191
+ }
192
+ });
193
+ }
194
+ readMessage(seqNum, offset, length) {
195
+ return __awaiter(this, void 0, void 0, function* () {
196
+ const buffer = yield this.streamProvider.readBody(offset, length);
197
+ if (buffer.length !== length)
198
+ return null;
199
+ const encoded = buffer.toString('utf8');
200
+ const msgType = FileSessionStore.extractTag(encoded, '35');
201
+ const sendingTimeStr = FileSessionStore.extractTag(encoded, '52');
202
+ let timestamp = new Date(0);
203
+ if (sendingTimeStr) {
204
+ const parsed = FileSessionStore.parseSessionTime(sendingTimeStr);
205
+ if (parsed)
206
+ timestamp = parsed;
207
+ }
208
+ return new fix_msg_store_record_1.FixMsgStoreRecord(msgType !== null && msgType !== void 0 ? msgType : '', timestamp, seqNum, undefined, encoded);
209
+ });
210
+ }
211
+ static extractTag(message, tag) {
212
+ const tagPrefix = `${tag}=`;
213
+ if (message.startsWith(tagPrefix)) {
214
+ const endIndex = FileSessionStore.findDelimiter(message, tagPrefix.length);
215
+ return message.substring(tagPrefix.length, endIndex);
216
+ }
217
+ for (const delim of ['\x01', '|']) {
218
+ const search = `${delim}${tagPrefix}`;
219
+ const idx = message.indexOf(search);
220
+ if (idx >= 0) {
221
+ const startIndex = idx + search.length;
222
+ const endIndex = FileSessionStore.findDelimiter(message, startIndex);
223
+ return message.substring(startIndex, endIndex);
224
+ }
225
+ }
226
+ return null;
227
+ }
228
+ static findDelimiter(message, fromIndex) {
229
+ for (let i = fromIndex; i < message.length; i++) {
230
+ const ch = message.charAt(i);
231
+ if (ch === '\x01' || ch === '|')
232
+ return i;
233
+ }
234
+ return message.length;
235
+ }
236
+ static formatSessionTime(date) {
237
+ const y = date.getUTCFullYear();
238
+ const M = (date.getUTCMonth() + 1).toString().padStart(2, '0');
239
+ const d = date.getUTCDate().toString().padStart(2, '0');
240
+ const h = date.getUTCHours().toString().padStart(2, '0');
241
+ const m = date.getUTCMinutes().toString().padStart(2, '0');
242
+ const s = date.getUTCSeconds().toString().padStart(2, '0');
243
+ const ms = date.getUTCMilliseconds().toString().padStart(3, '0');
244
+ return `${y}${M}${d}-${h}:${m}:${s}.${ms}000`;
245
+ }
246
+ static parseSessionTime(str) {
247
+ const match = str.match(/^(\d{4})(\d{2})(\d{2})-(\d{2}):(\d{2}):(\d{2})\.(\d{3,6})$/);
248
+ if (!match)
249
+ return null;
250
+ const [, y, M, d, h, m, s, frac] = match;
251
+ const ms = parseInt(frac.substring(0, 3), 10);
252
+ return new Date(Date.UTC(parseInt(y), parseInt(M) - 1, parseInt(d), parseInt(h), parseInt(m), parseInt(s), ms));
253
+ }
254
+ }
255
+ exports.FileSessionStore = FileSessionStore;
256
+ //# sourceMappingURL=file-session-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-session-store.js","sourceRoot":"","sources":["../../src/store/file-session-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { IFixSessionStore } from './fix-session-store'\nimport { SessionId } from './session-id'\nimport { IFixMsgStoreRecord, FixMsgStoreRecord } from './fix-msg-store-record'\nimport { ISessionStreamProvider } from './session-stream-provider'\nimport { FileSessionStreamProvider } from './file-session-stream-provider'\n\n/**\n * QuickFix-compatible file-based session store.\n *\n * File format:\n * - .seqnums: \"SSSSSSSSSSSSSSSSSSSS : TTTTTTTTTTTTTTTTTTTT\" (20-char right-justified sender : target)\n * - .session: \"YYYYMMDD-HH:MM:SS.ffffff\" (session creation time)\n * - .header: \"seqnum,offset,length\" per line (index into body)\n * - .body: concatenated raw FIX messages (no delimiters)\n */\nexport class FileSessionStore implements IFixSessionStore {\n private readonly streamProvider: ISessionStreamProvider\n private readonly ownsProvider: boolean\n\n private senderSeqNumValue: number = 1\n private targetSeqNumValue: number = 1\n private creationTimeValue: Date = new Date()\n\n // In-memory index: seqnum -> { offset, length }\n private readonly headerIndex: Map<number, { offset: number, length: number }> = new Map()\n\n /**\n * Creates a FileSessionStore with the default file-based stream provider.\n */\n static createWithFiles (sessionId: SessionId, directory: string): FileSessionStore {\n return new FileSessionStore(sessionId, new FileSessionStreamProvider(sessionId, directory), true)\n }\n\n /**\n * Creates a FileSessionStore with a custom stream provider.\n * Useful for testing with in-memory streams.\n */\n constructor (\n public readonly sessionId: SessionId,\n streamProvider: ISessionStreamProvider,\n ownsProvider: boolean = false\n ) {\n this.streamProvider = streamProvider\n this.ownsProvider = ownsProvider\n }\n\n /**\n * Gets the stream provider for direct access (useful for testing).\n */\n getStreamProvider (): ISessionStreamProvider {\n return this.streamProvider\n }\n\n // Sequence Numbers\n\n get senderSeqNum (): number {\n return this.senderSeqNumValue\n }\n\n set senderSeqNum (value: number) {\n this.senderSeqNumValue = value\n }\n\n get targetSeqNum (): number {\n return this.targetSeqNumValue\n }\n\n set targetSeqNum (value: number) {\n this.targetSeqNumValue = value\n }\n\n async setSenderSeqNum (value: number): Promise<void> {\n this.senderSeqNumValue = value\n await this.persistSeqNums()\n }\n\n async setTargetSeqNum (value: number): Promise<void> {\n this.targetSeqNumValue = value\n await this.persistSeqNums()\n }\n\n async nextSenderSeqNum (): Promise<number> {\n const next = ++this.senderSeqNumValue\n await this.persistSeqNums()\n return next\n }\n\n async nextTargetSeqNum (): Promise<number> {\n const next = ++this.targetSeqNumValue\n await this.persistSeqNums()\n return next\n }\n\n // Session\n\n get creationTime (): Date {\n return this.creationTimeValue\n }\n\n async reset (): Promise<void> {\n this.senderSeqNumValue = 1\n this.targetSeqNumValue = 1\n this.creationTimeValue = new Date()\n this.headerIndex.clear()\n\n await this.streamProvider.reset()\n await this.persistSeqNums()\n await this.persistSessionTime()\n this.streamProvider.openBody()\n }\n\n // Message Operations\n\n async put (record: IFixMsgStoreRecord): Promise<void> {\n if (record.encoded == null) {\n throw new Error('Record must have encoded content')\n }\n\n const bytes = Buffer.from(record.encoded, 'utf8')\n const length = bytes.length\n const offset = await this.streamProvider.appendBody(bytes)\n this.headerIndex.set(record.seqNum, { offset, length })\n await this.streamProvider.appendHeaderLine(`${record.seqNum},${offset},${length}`)\n }\n\n async get (seqNum: number): Promise<IFixMsgStoreRecord | null> {\n const entry = this.headerIndex.get(seqNum)\n if (!entry) return null\n return await this.readMessage(seqNum, entry.offset, entry.length)\n }\n\n async getRange (fromSeqNum: number, toSeqNum: number): Promise<IFixMsgStoreRecord[]> {\n const results: IFixMsgStoreRecord[] = []\n for (let seq = fromSeqNum; seq <= toSeqNum; seq++) {\n const record = await this.get(seq)\n if (record) {\n results.push(record)\n }\n }\n return results\n }\n\n // Lifecycle\n\n async initialize (): Promise<void> {\n await this.loadSeqNums()\n await this.loadSessionTime()\n await this.loadHeaderIndex()\n this.streamProvider.openBody()\n }\n\n async flush (): Promise<void> {\n await this.streamProvider.flush()\n }\n\n async dispose (): Promise<void> {\n await this.streamProvider.flush()\n if (this.ownsProvider) {\n await this.streamProvider.dispose()\n }\n }\n\n // Private - persistence\n\n private async persistSeqNums (): Promise<void> {\n const sender = this.senderSeqNumValue.toString().padStart(20, ' ')\n const target = this.targetSeqNumValue.toString().padStart(20, ' ')\n await this.streamProvider.writeSeqNums(`${sender} : ${target}`)\n }\n\n private async loadSeqNums (): Promise<void> {\n const content = await this.streamProvider.readSeqNums()\n if (content == null) {\n this.senderSeqNumValue = 1\n this.targetSeqNumValue = 1\n return\n }\n const parts = content.split(':')\n if (parts.length === 2) {\n this.senderSeqNumValue = parseInt(parts[0].trim(), 10) || 1\n this.targetSeqNumValue = parseInt(parts[1].trim(), 10) || 1\n }\n }\n\n private async persistSessionTime (): Promise<void> {\n await this.streamProvider.writeSessionTime(FileSessionStore.formatSessionTime(this.creationTimeValue))\n }\n\n private async loadSessionTime (): Promise<void> {\n const content = await this.streamProvider.readSessionTime()\n if (content == null) {\n this.creationTimeValue = new Date()\n await this.persistSessionTime()\n return\n }\n const parsed = FileSessionStore.parseSessionTime(content.trim())\n this.creationTimeValue = parsed ?? new Date()\n }\n\n private async loadHeaderIndex (): Promise<void> {\n const lines = await this.streamProvider.readHeaderLines()\n for (const line of lines) {\n if (!line.trim()) continue\n const parts = line.split(',')\n if (parts.length === 3) {\n const seqNum = parseInt(parts[0], 10)\n const offset = parseInt(parts[1], 10)\n const length = parseInt(parts[2], 10)\n if (!isNaN(seqNum) && !isNaN(offset) && !isNaN(length)) {\n this.headerIndex.set(seqNum, { offset, length })\n }\n }\n }\n }\n\n // Private - message reading\n\n private async readMessage (seqNum: number, offset: number, length: number): Promise<IFixMsgStoreRecord | null> {\n const buffer = await this.streamProvider.readBody(offset, length)\n if (buffer.length !== length) return null\n\n const encoded = buffer.toString('utf8')\n const msgType = FileSessionStore.extractTag(encoded, '35')\n const sendingTimeStr = FileSessionStore.extractTag(encoded, '52')\n let timestamp = new Date(0)\n if (sendingTimeStr) {\n const parsed = FileSessionStore.parseSessionTime(sendingTimeStr)\n if (parsed) timestamp = parsed\n }\n\n return new FixMsgStoreRecord(msgType ?? '', timestamp, seqNum, undefined, encoded)\n }\n\n /**\n * Extract a FIX tag value from a raw message string.\n * Tags are delimited by SOH (0x01) or pipe (|).\n */\n static extractTag (message: string, tag: string): string | null {\n const tagPrefix = `${tag}=`\n\n // Check if tag is at the start\n if (message.startsWith(tagPrefix)) {\n const endIndex = FileSessionStore.findDelimiter(message, tagPrefix.length)\n return message.substring(tagPrefix.length, endIndex)\n }\n\n // Search for SOH + tag= or | + tag=\n for (const delim of ['\\x01', '|']) {\n const search = `${delim}${tagPrefix}`\n const idx = message.indexOf(search)\n if (idx >= 0) {\n const startIndex = idx + search.length\n const endIndex = FileSessionStore.findDelimiter(message, startIndex)\n return message.substring(startIndex, endIndex)\n }\n }\n\n return null\n }\n\n private static findDelimiter (message: string, fromIndex: number): number {\n for (let i = fromIndex; i < message.length; i++) {\n const ch = message.charAt(i)\n if (ch === '\\x01' || ch === '|') return i\n }\n return message.length\n }\n\n /**\n * Format a date as QuickFix session time: YYYYMMDD-HH:MM:SS.ffffff\n */\n static formatSessionTime (date: Date): string {\n const y = date.getUTCFullYear()\n const M = (date.getUTCMonth() + 1).toString().padStart(2, '0')\n const d = date.getUTCDate().toString().padStart(2, '0')\n const h = date.getUTCHours().toString().padStart(2, '0')\n const m = date.getUTCMinutes().toString().padStart(2, '0')\n const s = date.getUTCSeconds().toString().padStart(2, '0')\n const ms = date.getUTCMilliseconds().toString().padStart(3, '0')\n return `${y}${M}${d}-${h}:${m}:${s}.${ms}000`\n }\n\n /**\n * Parse a QuickFix session time string: YYYYMMDD-HH:MM:SS.fff[fff]\n */\n static parseSessionTime (str: string): Date | null {\n // Format: YYYYMMDD-HH:MM:SS.ffffff\n const match = str.match(/^(\\d{4})(\\d{2})(\\d{2})-(\\d{2}):(\\d{2}):(\\d{2})\\.(\\d{3,6})$/)\n if (!match) return null\n const [, y, M, d, h, m, s, frac] = match\n const ms = parseInt(frac.substring(0, 3), 10)\n return new Date(Date.UTC(parseInt(y), parseInt(M) - 1, parseInt(d), parseInt(h), parseInt(m), parseInt(s), ms))\n }\n}\n"]}
@@ -0,0 +1,25 @@
1
+ import { ISessionStreamProvider } from './session-stream-provider';
2
+ import { SessionId } from './session-id';
3
+ export declare class FileSessionStreamProvider implements ISessionStreamProvider {
4
+ private readonly bodyPath;
5
+ private readonly headerPath;
6
+ private readonly seqNumsPath;
7
+ private readonly sessionPath;
8
+ private bodyFd;
9
+ private bodySize;
10
+ constructor(sessionId: SessionId, directory: string);
11
+ openBody(): void;
12
+ appendBody(data: Buffer): Promise<number>;
13
+ readBody(offset: number, length: number): Promise<Buffer>;
14
+ getBodySize(): number;
15
+ appendHeaderLine(line: string): Promise<void>;
16
+ readHeaderLines(): Promise<string[]>;
17
+ readSeqNums(): Promise<string | null>;
18
+ writeSeqNums(content: string): Promise<void>;
19
+ readSessionTime(): Promise<string | null>;
20
+ writeSessionTime(content: string): Promise<void>;
21
+ reset(): Promise<void>;
22
+ flush(): Promise<void>;
23
+ dispose(): Promise<void>;
24
+ private deleteIfExists;
25
+ }
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.FileSessionStreamProvider = void 0;
46
+ const fs = __importStar(require("fs"));
47
+ class FileSessionStreamProvider {
48
+ constructor(sessionId, directory) {
49
+ this.bodyFd = null;
50
+ this.bodySize = 0;
51
+ fs.mkdirSync(directory, { recursive: true });
52
+ this.bodyPath = sessionId.getFilePath(directory, 'body');
53
+ this.headerPath = sessionId.getFilePath(directory, 'header');
54
+ this.seqNumsPath = sessionId.getFilePath(directory, 'seqnums');
55
+ this.sessionPath = sessionId.getFilePath(directory, 'session');
56
+ }
57
+ openBody() {
58
+ if (this.bodyFd !== null)
59
+ return;
60
+ this.bodyFd = fs.openSync(this.bodyPath, 'a+');
61
+ const stat = fs.fstatSync(this.bodyFd);
62
+ this.bodySize = stat.size;
63
+ }
64
+ appendBody(data) {
65
+ return __awaiter(this, void 0, void 0, function* () {
66
+ if (this.bodyFd === null) {
67
+ this.openBody();
68
+ }
69
+ const offset = this.bodySize;
70
+ fs.writeSync(this.bodyFd, data, 0, data.length, offset);
71
+ this.bodySize += data.length;
72
+ return offset;
73
+ });
74
+ }
75
+ readBody(offset, length) {
76
+ return __awaiter(this, void 0, void 0, function* () {
77
+ if (this.bodyFd === null) {
78
+ this.openBody();
79
+ }
80
+ const buf = Buffer.alloc(length);
81
+ fs.readSync(this.bodyFd, buf, 0, length, offset);
82
+ return buf;
83
+ });
84
+ }
85
+ getBodySize() {
86
+ return this.bodySize;
87
+ }
88
+ appendHeaderLine(line) {
89
+ return __awaiter(this, void 0, void 0, function* () {
90
+ yield fs.promises.appendFile(this.headerPath, line + '\n', 'utf8');
91
+ });
92
+ }
93
+ readHeaderLines() {
94
+ return __awaiter(this, void 0, void 0, function* () {
95
+ if (!fs.existsSync(this.headerPath))
96
+ return [];
97
+ const content = yield fs.promises.readFile(this.headerPath, 'utf8');
98
+ if (!content.trim())
99
+ return [];
100
+ return content.split('\n').filter(l => l.trim().length > 0);
101
+ });
102
+ }
103
+ readSeqNums() {
104
+ return __awaiter(this, void 0, void 0, function* () {
105
+ if (!fs.existsSync(this.seqNumsPath))
106
+ return null;
107
+ return yield fs.promises.readFile(this.seqNumsPath, 'utf8');
108
+ });
109
+ }
110
+ writeSeqNums(content) {
111
+ return __awaiter(this, void 0, void 0, function* () {
112
+ yield fs.promises.writeFile(this.seqNumsPath, content, 'utf8');
113
+ });
114
+ }
115
+ readSessionTime() {
116
+ return __awaiter(this, void 0, void 0, function* () {
117
+ if (!fs.existsSync(this.sessionPath))
118
+ return null;
119
+ return yield fs.promises.readFile(this.sessionPath, 'utf8');
120
+ });
121
+ }
122
+ writeSessionTime(content) {
123
+ return __awaiter(this, void 0, void 0, function* () {
124
+ yield fs.promises.writeFile(this.sessionPath, content, 'utf8');
125
+ });
126
+ }
127
+ reset() {
128
+ return __awaiter(this, void 0, void 0, function* () {
129
+ if (this.bodyFd !== null) {
130
+ fs.closeSync(this.bodyFd);
131
+ this.bodyFd = null;
132
+ }
133
+ this.bodySize = 0;
134
+ this.deleteIfExists(this.bodyPath);
135
+ this.deleteIfExists(this.headerPath);
136
+ this.deleteIfExists(this.seqNumsPath);
137
+ this.deleteIfExists(this.sessionPath);
138
+ });
139
+ }
140
+ flush() {
141
+ return __awaiter(this, void 0, void 0, function* () {
142
+ if (this.bodyFd !== null) {
143
+ fs.fsyncSync(this.bodyFd);
144
+ }
145
+ });
146
+ }
147
+ dispose() {
148
+ return __awaiter(this, void 0, void 0, function* () {
149
+ if (this.bodyFd !== null) {
150
+ fs.closeSync(this.bodyFd);
151
+ this.bodyFd = null;
152
+ }
153
+ });
154
+ }
155
+ deleteIfExists(filePath) {
156
+ if (fs.existsSync(filePath)) {
157
+ fs.unlinkSync(filePath);
158
+ }
159
+ }
160
+ }
161
+ exports.FileSessionStreamProvider = FileSessionStreamProvider;
162
+ //# sourceMappingURL=file-session-stream-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-session-stream-provider.js","sourceRoot":"","sources":["../../src/store/file-session-stream-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs'\nimport { ISessionStreamProvider } from './session-stream-provider'\nimport { SessionId } from './session-id'\n\n/**\n * File-based implementation of ISessionStreamProvider.\n * Creates QuickFix-compatible files in the specified directory.\n *\n * Files created:\n * - {prefix}.body — concatenated raw FIX messages\n * - {prefix}.header — index lines: \"seqnum,offset,length\"\n * - {prefix}.seqnums — sender/target sequence numbers\n * - {prefix}.session — session creation time\n */\nexport class FileSessionStreamProvider implements ISessionStreamProvider {\n private readonly bodyPath: string\n private readonly headerPath: string\n private readonly seqNumsPath: string\n private readonly sessionPath: string\n private bodyFd: number | null = null\n private bodySize: number = 0\n\n constructor (\n sessionId: SessionId,\n directory: string\n ) {\n fs.mkdirSync(directory, { recursive: true })\n this.bodyPath = sessionId.getFilePath(directory, 'body')\n this.headerPath = sessionId.getFilePath(directory, 'header')\n this.seqNumsPath = sessionId.getFilePath(directory, 'seqnums')\n this.sessionPath = sessionId.getFilePath(directory, 'session')\n }\n\n openBody (): void {\n if (this.bodyFd !== null) return\n this.bodyFd = fs.openSync(this.bodyPath, 'a+')\n const stat = fs.fstatSync(this.bodyFd)\n this.bodySize = stat.size\n }\n\n async appendBody (data: Buffer): Promise<number> {\n if (this.bodyFd === null) {\n this.openBody()\n }\n const offset = this.bodySize\n fs.writeSync(this.bodyFd!, data, 0, data.length, offset)\n this.bodySize += data.length\n return offset\n }\n\n async readBody (offset: number, length: number): Promise<Buffer> {\n if (this.bodyFd === null) {\n this.openBody()\n }\n const buf = Buffer.alloc(length)\n fs.readSync(this.bodyFd!, buf, 0, length, offset)\n return buf\n }\n\n getBodySize (): number {\n return this.bodySize\n }\n\n async appendHeaderLine (line: string): Promise<void> {\n await fs.promises.appendFile(this.headerPath, line + '\\n', 'utf8')\n }\n\n async readHeaderLines (): Promise<string[]> {\n if (!fs.existsSync(this.headerPath)) return []\n const content = await fs.promises.readFile(this.headerPath, 'utf8')\n if (!content.trim()) return []\n return content.split('\\n').filter(l => l.trim().length > 0)\n }\n\n async readSeqNums (): Promise<string | null> {\n if (!fs.existsSync(this.seqNumsPath)) return null\n return await fs.promises.readFile(this.seqNumsPath, 'utf8')\n }\n\n async writeSeqNums (content: string): Promise<void> {\n await fs.promises.writeFile(this.seqNumsPath, content, 'utf8')\n }\n\n async readSessionTime (): Promise<string | null> {\n if (!fs.existsSync(this.sessionPath)) return null\n return await fs.promises.readFile(this.sessionPath, 'utf8')\n }\n\n async writeSessionTime (content: string): Promise<void> {\n await fs.promises.writeFile(this.sessionPath, content, 'utf8')\n }\n\n async reset (): Promise<void> {\n if (this.bodyFd !== null) {\n fs.closeSync(this.bodyFd)\n this.bodyFd = null\n }\n this.bodySize = 0\n this.deleteIfExists(this.bodyPath)\n this.deleteIfExists(this.headerPath)\n this.deleteIfExists(this.seqNumsPath)\n this.deleteIfExists(this.sessionPath)\n }\n\n async flush (): Promise<void> {\n if (this.bodyFd !== null) {\n fs.fsyncSync(this.bodyFd)\n }\n }\n\n async dispose (): Promise<void> {\n if (this.bodyFd !== null) {\n fs.closeSync(this.bodyFd)\n this.bodyFd = null\n }\n }\n\n private deleteIfExists (filePath: string): void {\n if (fs.existsSync(filePath)) {\n fs.unlinkSync(filePath)\n }\n }\n}\n"]}
@@ -78,7 +78,7 @@ class FixMsgAsciiStoreResend {
78
78
  sequenceResetGap(startGap, newSeq) {
79
79
  const factory = this.config.factory;
80
80
  const gapFill = factory === null || factory === void 0 ? void 0 : factory.sequenceReset(newSeq, true);
81
- gapFill.StandardHeader = factory === null || factory === void 0 ? void 0 : factory.header(types_1.MsgType.SequenceReset, startGap);
81
+ gapFill.StandardHeader = factory === null || factory === void 0 ? void 0 : factory.header(types_1.MsgType.SequenceReset, startGap, new Date());
82
82
  gapFill.StandardHeader.PossDupFlag = true;
83
83
  return new fix_msg_store_record_1.FixMsgStoreRecord(types_1.MsgType.SequenceReset, new Date(), startGap, gapFill, null);
84
84
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fix-msg-ascii-store-resend.js","sourceRoot":"","sources":["../../src/store/fix-msg-ascii-store-resend.ts"],"names":[],"mappings":"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","sourcesContent":["import { IFixMsgStore } from './fix-msg-store'\nimport { FixMsgStoreRecord, IFixMsgStoreRecord } from './fix-msg-store-record'\nimport { IJsFixConfig } from '../config'\nimport { MsgType } from '../types'\nimport { ElasticBuffer, MsgView } from '../buffer'\nimport { AsciiParser } from '../buffer/ascii'\nimport { ISequenceReset, IStandardHeader } from '../types/FIX4.4/repo'\n\nexport class FixMsgAsciiStoreResend {\n parser: AsciiParser\n constructor (public readonly store: IFixMsgStore, public readonly config: IJsFixConfig) {\n this.parser = new AsciiParser(this.config, null, new ElasticBuffer(160 * 1024))\n }\n\n public async getResendRequest (startSeq: number, endSeq: number): Promise<IFixMsgStoreRecord[]> {\n // need to cover request from start to end where any missing numbers are\n // included as gaps to allow vector of messages to be sent by the session\n // on a request\n\n return await new Promise((resolve, reject) => {\n this.store.getSeqNumRange(startSeq, endSeq).then(res => {\n resolve(this.inflateRange(startSeq, endSeq, res))\n }).catch(e => {\n reject(e)\n })\n })\n }\n\n private inflateRange (startSeq: number, endSeq: number, input: IFixMsgStoreRecord[]): IFixMsgStoreRecord[] {\n const toResend: IFixMsgStoreRecord[] = []\n // If no records for this given sequence number range, returns a single gap fill\n if (input.length === 0) {\n this.gap(startSeq, endSeq + 1, toResend)\n return toResend\n }\n\n let expected = startSeq\n for (let i = 0; i < input.length; ++i) {\n const record = this.prepareRecordForRetransmission(input[i])\n const seqNum = record.seqNum\n const toGap = seqNum - expected\n if (toGap > 0) {\n this.gap(expected, seqNum, toResend)\n }\n expected = seqNum + 1\n if (record.encoded) {\n this.inflate(record)\n }\n toResend.push(record)\n }\n if (endSeq - expected > 0) {\n this.gap(expected, endSeq + 1, toResend)\n }\n return toResend\n }\n\n private gap (beginGap: number, newSeq: number, arr: IFixMsgStoreRecord[]): void {\n if (beginGap > 0) {\n arr.push(this.sequenceResetGap(beginGap, newSeq))\n }\n }\n\n // if records were sent as encoded text then inflate back to object\n // so can be resent or examined\n\n private inflate (record: IFixMsgStoreRecord): void {\n if (record.obj) return\n if (!record.encoded) return\n const parser = this.parser\n parser.on('error', (_: Error) => {\n record.obj = null\n })\n parser.on('msg', (view: MsgView) => {\n record.obj = view.toObject()\n })\n // inline parse\n parser.parseText(record.encoded)\n }\n\n /**\n * A continuous sequence of messages not being retransmitted should be skipped over using a\n * single SequenceReset(35=4) message with GapFillFlag(123) set to “Y” and MsgSeqNum(34) set\n * to the sequence number of the first skipped message and NewSeqNo(36) must always be set\n * to the value of the next sequence number to be expected by the peer immediately following\n * the messages being skipped.\n */\n private sequenceResetGap (startGap: number, newSeq: number): IFixMsgStoreRecord {\n const factory = this.config.factory\n const gapFill: ISequenceReset = factory?.sequenceReset(newSeq, true) as ISequenceReset\n gapFill.StandardHeader = factory?.header(MsgType.SequenceReset, startGap) as IStandardHeader\n gapFill.StandardHeader.PossDupFlag = true\n\n return new FixMsgStoreRecord(\n MsgType.SequenceReset,\n new Date(),\n startGap,\n gapFill,\n null\n )\n }\n\n /**\n * Prepares the FIX message as response to ResendRequest (2).\n *\n * The FIX session processor retransmitting a message with the PossDupFlag(43) set to \"Y\" must modify the following fields:\n *\n * SendingTime(52) set to the current sending time\n * OrigSendingTime(122) set to the SendingTime(52) from the original message\n * Recalculate the BodyLength(9)\n * Recalculate the CheckSum(10)\n *\n * If the message is encrypted, SecureDataLen(90) and SecureData(91) may also require re-encryption and re-encoding\n *\n * @see https://www.fixtrading.org/standards/fix-session-layer-online/#message-recovery\n *\n * @param originalRecord the FIX message to be retransmitted as possible duplicate\n * @returns the FIX message ready to be retransmitted\n */\n private prepareRecordForRetransmission (originalRecord: IFixMsgStoreRecord): IFixMsgStoreRecord {\n const retransmitted = originalRecord.clone() // We don't want to accidently change any fields of the original record\n\n const factory = this.config.factory\n if (!retransmitted.obj) {\n retransmitted.obj = {}\n }\n\n // Rebuilds header with the updated fields\n const header = factory?.header(\n retransmitted.msgType,\n retransmitted.seqNum,\n new Date(), // SendingTime(52)\n {\n PossDupFlag: true,\n OrigSendingTime: retransmitted.timestamp\n }\n )\n retransmitted.obj = {\n ...retransmitted.obj,\n StandardHeader: header\n }\n return retransmitted\n }\n}\n"]}
1
+ {"version":3,"file":"fix-msg-ascii-store-resend.js","sourceRoot":"","sources":["../../src/store/fix-msg-ascii-store-resend.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,iEAA8E;AAE9E,oCAAkC;AAClC,sCAAkD;AAClD,2CAA6C;AAG7C,MAAa,sBAAsB;IAEjC,YAA6B,KAAmB,EAAkB,MAAoB;QAAzD,UAAK,GAAL,KAAK,CAAc;QAAkB,WAAM,GAAN,MAAM,CAAc;QACpF,IAAI,CAAC,MAAM,GAAG,IAAI,mBAAW,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,sBAAa,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAA;IACjF,CAAC;IAEY,gBAAgB,CAAE,QAAgB,EAAE,MAAc;;YAK7D,OAAO,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC3C,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;oBACrD,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,CAAA;gBACnD,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;oBACX,MAAM,CAAC,CAAC,CAAC,CAAA;gBACX,CAAC,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;QACJ,CAAC;KAAA;IAEO,YAAY,CAAE,QAAgB,EAAE,MAAc,EAAE,KAA2B;QACjF,MAAM,QAAQ,GAAyB,EAAE,CAAA;QAEzC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAA;YACxC,OAAO,QAAQ,CAAA;QACjB,CAAC;QAED,IAAI,QAAQ,GAAG,QAAQ,CAAA;QACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,IAAI,CAAC,8BAA8B,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;YAC5D,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAA;YAC5B,MAAM,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAA;YAC/B,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACd,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAA;YACtC,CAAC;YACD,QAAQ,GAAG,MAAM,GAAG,CAAC,CAAA;YACrB,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;YACtB,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACvB,CAAC;QACD,IAAI,MAAM,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAA;QAC1C,CAAC;QACD,OAAO,QAAQ,CAAA;IACjB,CAAC;IAEO,GAAG,CAAE,QAAgB,EAAE,MAAc,EAAE,GAAyB;QACtE,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;YACjB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAA;QACnD,CAAC;IACH,CAAC;IAKO,OAAO,CAAE,MAA0B;QACzC,IAAI,MAAM,CAAC,GAAG;YAAE,OAAM;QACtB,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,OAAM;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QAC1B,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAQ,EAAE,EAAE;YAC9B,MAAM,CAAC,GAAG,GAAG,IAAI,CAAA;QACnB,CAAC,CAAC,CAAA;QACF,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,IAAa,EAAE,EAAE;YACjC,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAA;QAC9B,CAAC,CAAC,CAAA;QAEF,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAClC,CAAC;IASO,gBAAgB,CAAE,QAAgB,EAAE,MAAc;QACxD,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAA;QACnC,MAAM,OAAO,GAAmB,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,aAAa,CAAC,MAAM,EAAE,IAAI,CAAmB,CAAA;QACtF,OAAO,CAAC,cAAc,GAAG,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,MAAM,CAAC,eAAO,CAAC,aAAa,EAAE,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAoB,CAAA;QACxG,OAAO,CAAC,cAAc,CAAC,WAAW,GAAG,IAAI,CAAA;QAEzC,OAAO,IAAI,wCAAiB,CAC1B,eAAO,CAAC,aAAa,EACrB,IAAI,IAAI,EAAE,EACV,QAAQ,EACR,OAAO,EACP,IAAI,CACL,CAAA;IACH,CAAC;IAmBO,8BAA8B,CAAE,cAAkC;QACxE,MAAM,aAAa,GAAG,cAAc,CAAC,KAAK,EAAE,CAAA;QAE5C,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAA;QACnC,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC;YACvB,aAAa,CAAC,GAAG,GAAG,EAAE,CAAA;QACxB,CAAC;QAGD,MAAM,MAAM,GAAG,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,MAAM,CAC5B,aAAa,CAAC,OAAO,EACrB,aAAa,CAAC,MAAM,EACpB,IAAI,IAAI,EAAE,EACV;YACE,WAAW,EAAE,IAAI;YACjB,eAAe,EAAE,aAAa,CAAC,SAAS;SACzC,CACF,CAAA;QACD,aAAa,CAAC,GAAG,mCACZ,aAAa,CAAC,GAAG,KACpB,cAAc,EAAE,MAAM,GACvB,CAAA;QACD,OAAO,aAAa,CAAA;IACtB,CAAC;CACF;AAtID,wDAsIC","sourcesContent":["import { IFixMsgStore } from './fix-msg-store'\nimport { FixMsgStoreRecord, IFixMsgStoreRecord } from './fix-msg-store-record'\nimport { IJsFixConfig } from '../config'\nimport { MsgType } from '../types'\nimport { ElasticBuffer, MsgView } from '../buffer'\nimport { AsciiParser } from '../buffer/ascii'\nimport { ISequenceReset, IStandardHeader } from '../types/FIX4.4/repo'\n\nexport class FixMsgAsciiStoreResend {\n parser: AsciiParser\n constructor (public readonly store: IFixMsgStore, public readonly config: IJsFixConfig) {\n this.parser = new AsciiParser(this.config, null, new ElasticBuffer(160 * 1024))\n }\n\n public async getResendRequest (startSeq: number, endSeq: number): Promise<IFixMsgStoreRecord[]> {\n // need to cover request from start to end where any missing numbers are\n // included as gaps to allow vector of messages to be sent by the session\n // on a request\n\n return await new Promise((resolve, reject) => {\n this.store.getSeqNumRange(startSeq, endSeq).then(res => {\n resolve(this.inflateRange(startSeq, endSeq, res))\n }).catch(e => {\n reject(e)\n })\n })\n }\n\n private inflateRange (startSeq: number, endSeq: number, input: IFixMsgStoreRecord[]): IFixMsgStoreRecord[] {\n const toResend: IFixMsgStoreRecord[] = []\n // If no records for this given sequence number range, returns a single gap fill\n if (input.length === 0) {\n this.gap(startSeq, endSeq + 1, toResend)\n return toResend\n }\n\n let expected = startSeq\n for (let i = 0; i < input.length; ++i) {\n const record = this.prepareRecordForRetransmission(input[i])\n const seqNum = record.seqNum\n const toGap = seqNum - expected\n if (toGap > 0) {\n this.gap(expected, seqNum, toResend)\n }\n expected = seqNum + 1\n if (record.encoded) {\n this.inflate(record)\n }\n toResend.push(record)\n }\n if (endSeq - expected > 0) {\n this.gap(expected, endSeq + 1, toResend)\n }\n return toResend\n }\n\n private gap (beginGap: number, newSeq: number, arr: IFixMsgStoreRecord[]): void {\n if (beginGap > 0) {\n arr.push(this.sequenceResetGap(beginGap, newSeq))\n }\n }\n\n // if records were sent as encoded text then inflate back to object\n // so can be resent or examined\n\n private inflate (record: IFixMsgStoreRecord): void {\n if (record.obj) return\n if (!record.encoded) return\n const parser = this.parser\n parser.on('error', (_: Error) => {\n record.obj = null\n })\n parser.on('msg', (view: MsgView) => {\n record.obj = view.toObject()\n })\n // inline parse\n parser.parseText(record.encoded)\n }\n\n /**\n * A continuous sequence of messages not being retransmitted should be skipped over using a\n * single SequenceReset(35=4) message with GapFillFlag(123) set to “Y” and MsgSeqNum(34) set\n * to the sequence number of the first skipped message and NewSeqNo(36) must always be set\n * to the value of the next sequence number to be expected by the peer immediately following\n * the messages being skipped.\n */\n private sequenceResetGap (startGap: number, newSeq: number): IFixMsgStoreRecord {\n const factory = this.config.factory\n const gapFill: ISequenceReset = factory?.sequenceReset(newSeq, true) as ISequenceReset\n gapFill.StandardHeader = factory?.header(MsgType.SequenceReset, startGap, new Date()) as IStandardHeader\n gapFill.StandardHeader.PossDupFlag = true\n\n return new FixMsgStoreRecord(\n MsgType.SequenceReset,\n new Date(),\n startGap,\n gapFill,\n null\n )\n }\n\n /**\n * Prepares the FIX message as response to ResendRequest (2).\n *\n * The FIX session processor retransmitting a message with the PossDupFlag(43) set to \"Y\" must modify the following fields:\n *\n * SendingTime(52) set to the current sending time\n * OrigSendingTime(122) set to the SendingTime(52) from the original message\n * Recalculate the BodyLength(9)\n * Recalculate the CheckSum(10)\n *\n * If the message is encrypted, SecureDataLen(90) and SecureData(91) may also require re-encryption and re-encoding\n *\n * @see https://www.fixtrading.org/standards/fix-session-layer-online/#message-recovery\n *\n * @param originalRecord the FIX message to be retransmitted as possible duplicate\n * @returns the FIX message ready to be retransmitted\n */\n private prepareRecordForRetransmission (originalRecord: IFixMsgStoreRecord): IFixMsgStoreRecord {\n const retransmitted = originalRecord.clone() // We don't want to accidently change any fields of the original record\n\n const factory = this.config.factory\n if (!retransmitted.obj) {\n retransmitted.obj = {}\n }\n\n // Rebuilds header with the updated fields\n const header = factory?.header(\n retransmitted.msgType,\n retransmitted.seqNum,\n new Date(), // SendingTime(52)\n {\n PossDupFlag: true,\n OrigSendingTime: retransmitted.timestamp\n }\n )\n retransmitted.obj = {\n ...retransmitted.obj,\n StandardHeader: header\n }\n return retransmitted\n }\n}\n"]}
@@ -0,0 +1,13 @@
1
+ import { IFixSessionStore } from './fix-session-store';
2
+ import { SessionId } from './session-id';
3
+ export interface IFixSessionStoreFactory {
4
+ create(sessionId: SessionId): IFixSessionStore;
5
+ }
6
+ export declare class MemorySessionStoreFactory implements IFixSessionStoreFactory {
7
+ create(sessionId: SessionId): IFixSessionStore;
8
+ }
9
+ export declare class FileSessionStoreFactory implements IFixSessionStoreFactory {
10
+ private readonly directory;
11
+ constructor(directory: string);
12
+ create(sessionId: SessionId): IFixSessionStore;
13
+ }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FileSessionStoreFactory = exports.MemorySessionStoreFactory = void 0;
4
+ const memory_session_store_1 = require("./memory-session-store");
5
+ const file_session_store_1 = require("./file-session-store");
6
+ class MemorySessionStoreFactory {
7
+ create(sessionId) {
8
+ return new memory_session_store_1.MemorySessionStore(sessionId);
9
+ }
10
+ }
11
+ exports.MemorySessionStoreFactory = MemorySessionStoreFactory;
12
+ class FileSessionStoreFactory {
13
+ constructor(directory) {
14
+ this.directory = directory;
15
+ }
16
+ create(sessionId) {
17
+ return file_session_store_1.FileSessionStore.createWithFiles(sessionId, this.directory);
18
+ }
19
+ }
20
+ exports.FileSessionStoreFactory = FileSessionStoreFactory;
21
+ //# sourceMappingURL=fix-session-store-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix-session-store-factory.js","sourceRoot":"","sources":["../../src/store/fix-session-store-factory.ts"],"names":[],"mappings":";;;AAEA,iEAA2D;AAC3D,6DAAuD;AAYvD,MAAa,yBAAyB;IACpC,MAAM,CAAE,SAAoB;QAC1B,OAAO,IAAI,yCAAkB,CAAC,SAAS,CAAC,CAAA;IAC1C,CAAC;CACF;AAJD,8DAIC;AAKD,MAAa,uBAAuB;IAClC,YAA8B,SAAiB;QAAjB,cAAS,GAAT,SAAS,CAAQ;IAAG,CAAC;IAEnD,MAAM,CAAE,SAAoB;QAC1B,OAAO,qCAAgB,CAAC,eAAe,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;IACpE,CAAC;CACF;AAND,0DAMC","sourcesContent":["import { IFixSessionStore } from './fix-session-store'\nimport { SessionId } from './session-id'\nimport { MemorySessionStore } from './memory-session-store'\nimport { FileSessionStore } from './file-session-store'\n\n/**\n * Factory for creating session stores.\n */\nexport interface IFixSessionStoreFactory {\n create (sessionId: SessionId): IFixSessionStore\n}\n\n/**\n * Factory for creating in-memory session stores.\n */\nexport class MemorySessionStoreFactory implements IFixSessionStoreFactory {\n create (sessionId: SessionId): IFixSessionStore {\n return new MemorySessionStore(sessionId)\n }\n}\n\n/**\n * Factory for creating file-based session stores.\n */\nexport class FileSessionStoreFactory implements IFixSessionStoreFactory {\n constructor (private readonly directory: string) {}\n\n create (sessionId: SessionId): IFixSessionStore {\n return FileSessionStore.createWithFiles(sessionId, this.directory)\n }\n}\n"]}
@@ -0,0 +1,19 @@
1
+ import { SessionId } from './session-id';
2
+ import { IFixMsgStoreRecord } from './fix-msg-store-record';
3
+ export interface IFixSessionStore {
4
+ readonly sessionId: SessionId;
5
+ put(record: IFixMsgStoreRecord): Promise<void>;
6
+ get(seqNum: number): Promise<IFixMsgStoreRecord | null>;
7
+ getRange(fromSeqNum: number, toSeqNum: number): Promise<IFixMsgStoreRecord[]>;
8
+ senderSeqNum: number;
9
+ targetSeqNum: number;
10
+ setSenderSeqNum(value: number): Promise<void>;
11
+ setTargetSeqNum(value: number): Promise<void>;
12
+ nextSenderSeqNum(): Promise<number>;
13
+ nextTargetSeqNum(): Promise<number>;
14
+ readonly creationTime: Date;
15
+ reset(): Promise<void>;
16
+ initialize(): Promise<void>;
17
+ flush(): Promise<void>;
18
+ dispose(): Promise<void>;
19
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=fix-session-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix-session-store.js","sourceRoot":"","sources":["../../src/store/fix-session-store.ts"],"names":[],"mappings":"","sourcesContent":["import { SessionId } from './session-id'\nimport { IFixMsgStoreRecord } from './fix-msg-store-record'\n\n/**\n * Unified session store interface for FIX message persistence and sequence number management.\n * Coordinates all persistence for a single FIX session:\n * - Message storage (.body + .header files)\n * - Sequence numbers (.seqnums file)\n * - Session metadata (.session file)\n *\n * QuickFix-compatible file format for interoperability.\n */\nexport interface IFixSessionStore {\n readonly sessionId: SessionId\n\n // Message Operations\n put (record: IFixMsgStoreRecord): Promise<void>\n get (seqNum: number): Promise<IFixMsgStoreRecord | null>\n getRange (fromSeqNum: number, toSeqNum: number): Promise<IFixMsgStoreRecord[]>\n\n // Sequence Number Operations\n senderSeqNum: number\n targetSeqNum: number\n setSenderSeqNum (value: number): Promise<void>\n setTargetSeqNum (value: number): Promise<void>\n nextSenderSeqNum (): Promise<number>\n nextTargetSeqNum (): Promise<number>\n\n // Session Operations\n readonly creationTime: Date\n reset (): Promise<void>\n\n // Lifecycle\n initialize (): Promise<void>\n flush (): Promise<void>\n dispose (): Promise<void>\n}\n"]}
@@ -2,3 +2,12 @@ export * from './fix-msg-memory-store';
2
2
  export * from './fix-msg-store';
3
3
  export * from './fix-msg-store-record';
4
4
  export * from './fix-msg-ascii-store-resend';
5
+ export * from './session-id';
6
+ export * from './fix-session-store';
7
+ export * from './memory-session-store';
8
+ export * from './fix-session-store-factory';
9
+ export * from './session-stream-provider';
10
+ export * from './memory-session-stream-provider';
11
+ export * from './file-session-stream-provider';
12
+ export * from './file-session-store';
13
+ export * from './store-config';