jspurefix 5.2.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.
- package/BACKPORT_PLAN.md +15 -29
- package/dist/config/js-fix-config.d.ts +2 -0
- package/dist/config/js-fix-config.js.map +1 -1
- package/dist/store/file-session-store.d.ts +42 -0
- package/dist/store/file-session-store.js +256 -0
- package/dist/store/file-session-store.js.map +1 -0
- package/dist/store/file-session-stream-provider.d.ts +25 -0
- package/dist/store/file-session-stream-provider.js +162 -0
- package/dist/store/file-session-stream-provider.js.map +1 -0
- package/dist/store/fix-session-store-factory.d.ts +13 -0
- package/dist/store/fix-session-store-factory.js +21 -0
- package/dist/store/fix-session-store-factory.js.map +1 -0
- package/dist/store/fix-session-store.d.ts +19 -0
- package/dist/store/fix-session-store.js +3 -0
- package/dist/store/fix-session-store.js.map +1 -0
- package/dist/store/index.d.ts +9 -0
- package/dist/store/index.js +9 -0
- package/dist/store/index.js.map +1 -1
- package/dist/store/memory-session-store.d.ts +27 -0
- package/dist/store/memory-session-store.js +104 -0
- package/dist/store/memory-session-store.js.map +1 -0
- package/dist/store/memory-session-stream-provider.d.ts +26 -0
- package/dist/store/memory-session-stream-provider.js +103 -0
- package/dist/store/memory-session-stream-provider.js.map +1 -0
- package/dist/store/session-id.d.ts +9 -0
- package/dist/store/session-id.js +55 -0
- package/dist/store/session-id.js.map +1 -0
- package/dist/store/session-stream-provider.d.ts +15 -0
- package/dist/store/session-stream-provider.js +3 -0
- package/dist/store/session-stream-provider.js.map +1 -0
- package/dist/store/store-config.d.ts +4 -0
- package/dist/store/store-config.js +3 -0
- package/dist/store/store-config.js.map +1 -0
- package/dist/transport/ascii/ascii-session.d.ts +6 -1
- package/dist/transport/ascii/ascii-session.js +37 -5
- package/dist/transport/ascii/ascii-session.js.map +1 -1
- package/dist/transport/session/session-description.d.ts +2 -0
- package/dist/transport/session/session-description.js.map +1 -1
- package/jsfix.test_client.txt +67 -67
- package/jsfix.test_server.txt +64 -64
- package/package.json +1 -1
- package/src/config/js-fix-config.ts +2 -0
- package/src/store/file-session-store.ts +294 -0
- package/src/store/file-session-stream-provider.ts +123 -0
- package/src/store/fix-session-store-factory.ts +31 -0
- package/src/store/fix-session-store.ts +37 -0
- package/src/store/index.ts +9 -0
- package/src/store/memory-session-store.ts +102 -0
- package/src/store/memory-session-stream-provider.ts +97 -0
- package/src/store/session-id.ts +32 -0
- package/src/store/session-stream-provider.ts +74 -0
- package/src/store/store-config.ts +15 -0
- package/src/transport/ascii/ascii-session.ts +57 -6
- package/src/transport/session/session-description.ts +2 -0
|
@@ -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 @@
|
|
|
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"]}
|
package/dist/store/index.d.ts
CHANGED
|
@@ -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';
|
package/dist/store/index.js
CHANGED
|
@@ -18,4 +18,13 @@ __exportStar(require("./fix-msg-memory-store"), exports);
|
|
|
18
18
|
__exportStar(require("./fix-msg-store"), exports);
|
|
19
19
|
__exportStar(require("./fix-msg-store-record"), exports);
|
|
20
20
|
__exportStar(require("./fix-msg-ascii-store-resend"), exports);
|
|
21
|
+
__exportStar(require("./session-id"), exports);
|
|
22
|
+
__exportStar(require("./fix-session-store"), exports);
|
|
23
|
+
__exportStar(require("./memory-session-store"), exports);
|
|
24
|
+
__exportStar(require("./fix-session-store-factory"), exports);
|
|
25
|
+
__exportStar(require("./session-stream-provider"), exports);
|
|
26
|
+
__exportStar(require("./memory-session-stream-provider"), exports);
|
|
27
|
+
__exportStar(require("./file-session-stream-provider"), exports);
|
|
28
|
+
__exportStar(require("./file-session-store"), exports);
|
|
29
|
+
__exportStar(require("./store-config"), exports);
|
|
21
30
|
//# sourceMappingURL=index.js.map
|
package/dist/store/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAsC;AACtC,kDAA+B;AAC/B,yDAAsC;AACtC,+DAA4C","sourcesContent":["export * from './fix-msg-memory-store'\nexport * from './fix-msg-store'\nexport * from './fix-msg-store-record'\nexport * from './fix-msg-ascii-store-resend'\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAsC;AACtC,kDAA+B;AAC/B,yDAAsC;AACtC,+DAA4C;AAC5C,+CAA4B;AAC5B,sDAAmC;AACnC,yDAAsC;AACtC,8DAA2C;AAC3C,4DAAyC;AACzC,mEAAgD;AAChD,iEAA8C;AAC9C,uDAAoC;AACpC,iDAA8B","sourcesContent":["export * from './fix-msg-memory-store'\nexport * from './fix-msg-store'\nexport * from './fix-msg-store-record'\nexport * from './fix-msg-ascii-store-resend'\nexport * from './session-id'\nexport * from './fix-session-store'\nexport * from './memory-session-store'\nexport * from './fix-session-store-factory'\nexport * from './session-stream-provider'\nexport * from './memory-session-stream-provider'\nexport * from './file-session-stream-provider'\nexport * from './file-session-store'\nexport * from './store-config'\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { IFixSessionStore } from './fix-session-store';
|
|
2
|
+
import { SessionId } from './session-id';
|
|
3
|
+
import { IFixMsgStoreRecord } from './fix-msg-store-record';
|
|
4
|
+
export declare class MemorySessionStore implements IFixSessionStore {
|
|
5
|
+
readonly sessionId: SessionId;
|
|
6
|
+
private readonly messages;
|
|
7
|
+
private senderSeqNumValue;
|
|
8
|
+
private targetSeqNumValue;
|
|
9
|
+
private creationTimeValue;
|
|
10
|
+
constructor(sessionId: SessionId);
|
|
11
|
+
get senderSeqNum(): number;
|
|
12
|
+
set senderSeqNum(value: number);
|
|
13
|
+
get targetSeqNum(): number;
|
|
14
|
+
set targetSeqNum(value: number);
|
|
15
|
+
setSenderSeqNum(value: number): Promise<void>;
|
|
16
|
+
setTargetSeqNum(value: number): Promise<void>;
|
|
17
|
+
nextSenderSeqNum(): Promise<number>;
|
|
18
|
+
nextTargetSeqNum(): Promise<number>;
|
|
19
|
+
get creationTime(): Date;
|
|
20
|
+
reset(): Promise<void>;
|
|
21
|
+
put(record: IFixMsgStoreRecord): Promise<void>;
|
|
22
|
+
get(seqNum: number): Promise<IFixMsgStoreRecord | null>;
|
|
23
|
+
getRange(fromSeqNum: number, toSeqNum: number): Promise<IFixMsgStoreRecord[]>;
|
|
24
|
+
initialize(): Promise<void>;
|
|
25
|
+
flush(): Promise<void>;
|
|
26
|
+
dispose(): Promise<void>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
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.MemorySessionStore = void 0;
|
|
13
|
+
class MemorySessionStore {
|
|
14
|
+
constructor(sessionId) {
|
|
15
|
+
this.sessionId = sessionId;
|
|
16
|
+
this.messages = new Map();
|
|
17
|
+
this.senderSeqNumValue = 1;
|
|
18
|
+
this.targetSeqNumValue = 1;
|
|
19
|
+
this.creationTimeValue = new Date();
|
|
20
|
+
}
|
|
21
|
+
get senderSeqNum() {
|
|
22
|
+
return this.senderSeqNumValue;
|
|
23
|
+
}
|
|
24
|
+
set senderSeqNum(value) {
|
|
25
|
+
this.senderSeqNumValue = value;
|
|
26
|
+
}
|
|
27
|
+
get targetSeqNum() {
|
|
28
|
+
return this.targetSeqNumValue;
|
|
29
|
+
}
|
|
30
|
+
set targetSeqNum(value) {
|
|
31
|
+
this.targetSeqNumValue = value;
|
|
32
|
+
}
|
|
33
|
+
setSenderSeqNum(value) {
|
|
34
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
+
this.senderSeqNumValue = value;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
setTargetSeqNum(value) {
|
|
39
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
40
|
+
this.targetSeqNumValue = value;
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
nextSenderSeqNum() {
|
|
44
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
+
return ++this.senderSeqNumValue;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
nextTargetSeqNum() {
|
|
49
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
return ++this.targetSeqNumValue;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
get creationTime() {
|
|
54
|
+
return this.creationTimeValue;
|
|
55
|
+
}
|
|
56
|
+
reset() {
|
|
57
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
58
|
+
this.senderSeqNumValue = 1;
|
|
59
|
+
this.targetSeqNumValue = 1;
|
|
60
|
+
this.creationTimeValue = new Date();
|
|
61
|
+
this.messages.clear();
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
put(record) {
|
|
65
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
66
|
+
this.messages.set(record.seqNum, record.clone());
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
get(seqNum) {
|
|
70
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
71
|
+
const record = this.messages.get(seqNum);
|
|
72
|
+
return record ? record.clone() : null;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
getRange(fromSeqNum, toSeqNum) {
|
|
76
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
77
|
+
const results = [];
|
|
78
|
+
const keys = Array.from(this.messages.keys())
|
|
79
|
+
.filter(k => k >= fromSeqNum && k <= toSeqNum)
|
|
80
|
+
.sort((a, b) => a - b);
|
|
81
|
+
for (const seq of keys) {
|
|
82
|
+
const record = this.messages.get(seq);
|
|
83
|
+
if (record) {
|
|
84
|
+
results.push(record.clone());
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return results;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
initialize() {
|
|
91
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
flush() {
|
|
95
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
dispose() {
|
|
99
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
exports.MemorySessionStore = MemorySessionStore;
|
|
104
|
+
//# sourceMappingURL=memory-session-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-session-store.js","sourceRoot":"","sources":["../../src/store/memory-session-store.ts"],"names":[],"mappings":";;;;;;;;;;;;AAQA,MAAa,kBAAkB;IAM7B,YAA6B,SAAoB;QAApB,cAAS,GAAT,SAAS,CAAW;QALhC,aAAQ,GAAoC,IAAI,GAAG,EAAE,CAAA;QAC9D,sBAAiB,GAAW,CAAC,CAAA;QAC7B,sBAAiB,GAAW,CAAC,CAAA;QAC7B,sBAAiB,GAAS,IAAI,IAAI,EAAE,CAAA;IAEQ,CAAC;IAIrD,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,iBAAiB,CAAA;IAC/B,CAAC;IAED,IAAI,YAAY,CAAE,KAAa;QAC7B,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAA;IAChC,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,iBAAiB,CAAA;IAC/B,CAAC;IAED,IAAI,YAAY,CAAE,KAAa;QAC7B,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAA;IAChC,CAAC;IAEK,eAAe,CAAE,KAAa;;YAClC,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAA;QAChC,CAAC;KAAA;IAEK,eAAe,CAAE,KAAa;;YAClC,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAA;QAChC,CAAC;KAAA;IAEK,gBAAgB;;YACpB,OAAO,EAAE,IAAI,CAAC,iBAAiB,CAAA;QACjC,CAAC;KAAA;IAEK,gBAAgB;;YACpB,OAAO,EAAE,IAAI,CAAC,iBAAiB,CAAA;QACjC,CAAC;KAAA;IAID,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,iBAAiB,CAAA;IAC/B,CAAC;IAEK,KAAK;;YACT,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAA;YAC1B,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAA;YAC1B,IAAI,CAAC,iBAAiB,GAAG,IAAI,IAAI,EAAE,CAAA;YACnC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAA;QACvB,CAAC;KAAA;IAIK,GAAG,CAAE,MAA0B;;YACnC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAA;QAClD,CAAC;KAAA;IAEK,GAAG,CAAE,MAAc;;YACvB,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YACxC,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;QACvC,CAAC;KAAA;IAEK,QAAQ,CAAE,UAAkB,EAAE,QAAgB;;YAClD,MAAM,OAAO,GAAyB,EAAE,CAAA;YACxC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;iBAC1C,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,UAAU,IAAI,CAAC,IAAI,QAAQ,CAAC;iBAC7C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YACxB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;gBACrC,IAAI,MAAM,EAAE,CAAC;oBACX,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAA;gBAC9B,CAAC;YACH,CAAC;YACD,OAAO,OAAO,CAAA;QAChB,CAAC;KAAA;IAIK,UAAU;;QAEhB,CAAC;KAAA;IAEK,KAAK;;QAEX,CAAC;KAAA;IAEK,OAAO;;QAEb,CAAC;KAAA;CACF;AA7FD,gDA6FC","sourcesContent":["import { IFixSessionStore } from './fix-session-store'\nimport { SessionId } from './session-id'\nimport { IFixMsgStoreRecord } from './fix-msg-store-record'\n\n/**\n * In-memory session store for testing and development.\n * Not persistent - all data lost on dispose.\n */\nexport class MemorySessionStore implements IFixSessionStore {\n private readonly messages: Map<number, IFixMsgStoreRecord> = new Map()\n private senderSeqNumValue: number = 1\n private targetSeqNumValue: number = 1\n private creationTimeValue: Date = new Date()\n\n constructor (public readonly sessionId: SessionId) {}\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 }\n\n async setTargetSeqNum (value: number): Promise<void> {\n this.targetSeqNumValue = value\n }\n\n async nextSenderSeqNum (): Promise<number> {\n return ++this.senderSeqNumValue\n }\n\n async nextTargetSeqNum (): Promise<number> {\n return ++this.targetSeqNumValue\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.messages.clear()\n }\n\n // Message Operations\n\n async put (record: IFixMsgStoreRecord): Promise<void> {\n this.messages.set(record.seqNum, record.clone())\n }\n\n async get (seqNum: number): Promise<IFixMsgStoreRecord | null> {\n const record = this.messages.get(seqNum)\n return record ? record.clone() : null\n }\n\n async getRange (fromSeqNum: number, toSeqNum: number): Promise<IFixMsgStoreRecord[]> {\n const results: IFixMsgStoreRecord[] = []\n const keys = Array.from(this.messages.keys())\n .filter(k => k >= fromSeqNum && k <= toSeqNum)\n .sort((a, b) => a - b)\n for (const seq of keys) {\n const record = this.messages.get(seq)\n if (record) {\n results.push(record.clone())\n }\n }\n return results\n }\n\n // Lifecycle\n\n async initialize (): Promise<void> {\n // No-op for memory store\n }\n\n async flush (): Promise<void> {\n // No-op for memory store\n }\n\n async dispose (): Promise<void> {\n // No-op for memory store\n }\n}\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ISessionStreamProvider } from './session-stream-provider';
|
|
2
|
+
export declare class MemorySessionStreamProvider implements ISessionStreamProvider {
|
|
3
|
+
private bodyBuffer;
|
|
4
|
+
private headerLines;
|
|
5
|
+
private seqNumsContent;
|
|
6
|
+
private sessionTimeContent;
|
|
7
|
+
getBodyBytes(): Buffer;
|
|
8
|
+
getBodyString(): string;
|
|
9
|
+
getHeaderString(): string;
|
|
10
|
+
getHeaderLinesSnapshot(): string[];
|
|
11
|
+
getSeqNumsContent(): string | null;
|
|
12
|
+
getSessionTimeContent(): string | null;
|
|
13
|
+
openBody(): void;
|
|
14
|
+
appendBody(data: Buffer): Promise<number>;
|
|
15
|
+
readBody(offset: number, length: number): Promise<Buffer>;
|
|
16
|
+
getBodySize(): number;
|
|
17
|
+
appendHeaderLine(line: string): Promise<void>;
|
|
18
|
+
readHeaderLines(): Promise<string[]>;
|
|
19
|
+
readSeqNums(): Promise<string | null>;
|
|
20
|
+
writeSeqNums(content: string): Promise<void>;
|
|
21
|
+
readSessionTime(): Promise<string | null>;
|
|
22
|
+
writeSessionTime(content: string): Promise<void>;
|
|
23
|
+
reset(): Promise<void>;
|
|
24
|
+
flush(): Promise<void>;
|
|
25
|
+
dispose(): Promise<void>;
|
|
26
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
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.MemorySessionStreamProvider = void 0;
|
|
13
|
+
class MemorySessionStreamProvider {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.bodyBuffer = Buffer.alloc(0);
|
|
16
|
+
this.headerLines = [];
|
|
17
|
+
this.seqNumsContent = null;
|
|
18
|
+
this.sessionTimeContent = null;
|
|
19
|
+
}
|
|
20
|
+
getBodyBytes() {
|
|
21
|
+
return Buffer.from(this.bodyBuffer);
|
|
22
|
+
}
|
|
23
|
+
getBodyString() {
|
|
24
|
+
return this.bodyBuffer.toString('utf8');
|
|
25
|
+
}
|
|
26
|
+
getHeaderString() {
|
|
27
|
+
return this.headerLines.join('\n');
|
|
28
|
+
}
|
|
29
|
+
getHeaderLinesSnapshot() {
|
|
30
|
+
return [...this.headerLines];
|
|
31
|
+
}
|
|
32
|
+
getSeqNumsContent() {
|
|
33
|
+
return this.seqNumsContent;
|
|
34
|
+
}
|
|
35
|
+
getSessionTimeContent() {
|
|
36
|
+
return this.sessionTimeContent;
|
|
37
|
+
}
|
|
38
|
+
openBody() {
|
|
39
|
+
}
|
|
40
|
+
appendBody(data) {
|
|
41
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
const offset = this.bodyBuffer.length;
|
|
43
|
+
this.bodyBuffer = Buffer.concat([this.bodyBuffer, data]);
|
|
44
|
+
return offset;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
readBody(offset, length) {
|
|
48
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
49
|
+
return this.bodyBuffer.subarray(offset, offset + length);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
getBodySize() {
|
|
53
|
+
return this.bodyBuffer.length;
|
|
54
|
+
}
|
|
55
|
+
appendHeaderLine(line) {
|
|
56
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
57
|
+
this.headerLines.push(line);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
readHeaderLines() {
|
|
61
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
62
|
+
return [...this.headerLines];
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
readSeqNums() {
|
|
66
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
67
|
+
return this.seqNumsContent;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
writeSeqNums(content) {
|
|
71
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
72
|
+
this.seqNumsContent = content;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
readSessionTime() {
|
|
76
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
77
|
+
return this.sessionTimeContent;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
writeSessionTime(content) {
|
|
81
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
82
|
+
this.sessionTimeContent = content;
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
reset() {
|
|
86
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
87
|
+
this.bodyBuffer = Buffer.alloc(0);
|
|
88
|
+
this.headerLines = [];
|
|
89
|
+
this.seqNumsContent = null;
|
|
90
|
+
this.sessionTimeContent = null;
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
flush() {
|
|
94
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
dispose() {
|
|
98
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
exports.MemorySessionStreamProvider = MemorySessionStreamProvider;
|
|
103
|
+
//# sourceMappingURL=memory-session-stream-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-session-stream-provider.js","sourceRoot":"","sources":["../../src/store/memory-session-stream-provider.ts"],"names":[],"mappings":";;;;;;;;;;;;AAMA,MAAa,2BAA2B;IAAxC;QACU,eAAU,GAAW,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QACpC,gBAAW,GAAa,EAAE,CAAA;QAC1B,mBAAc,GAAkB,IAAI,CAAA;QACpC,uBAAkB,GAAkB,IAAI,CAAA;IAsFlD,CAAC;IAlFC,YAAY;QACV,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACrC,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IACzC,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACpC,CAAC;IAED,sBAAsB;QACpB,OAAO,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CAAA;IAC9B,CAAC;IAED,iBAAiB;QACf,OAAO,IAAI,CAAC,cAAc,CAAA;IAC5B,CAAC;IAED,qBAAqB;QACnB,OAAO,IAAI,CAAC,kBAAkB,CAAA;IAChC,CAAC;IAID,QAAQ;IAER,CAAC;IAEK,UAAU,CAAE,IAAY;;YAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAA;YACrC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAA;YACxD,OAAO,MAAM,CAAA;QACf,CAAC;KAAA;IAEK,QAAQ,CAAE,MAAc,EAAE,MAAc;;YAC5C,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;QAC1D,CAAC;KAAA;IAED,WAAW;QACT,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAA;IAC/B,CAAC;IAEK,gBAAgB,CAAE,IAAY;;YAClC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC7B,CAAC;KAAA;IAEK,eAAe;;YACnB,OAAO,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CAAA;QAC9B,CAAC;KAAA;IAEK,WAAW;;YACf,OAAO,IAAI,CAAC,cAAc,CAAA;QAC5B,CAAC;KAAA;IAEK,YAAY,CAAE,OAAe;;YACjC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAA;QAC/B,CAAC;KAAA;IAEK,eAAe;;YACnB,OAAO,IAAI,CAAC,kBAAkB,CAAA;QAChC,CAAC;KAAA;IAEK,gBAAgB,CAAE,OAAe;;YACrC,IAAI,CAAC,kBAAkB,GAAG,OAAO,CAAA;QACnC,CAAC;KAAA;IAEK,KAAK;;YACT,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;YACjC,IAAI,CAAC,WAAW,GAAG,EAAE,CAAA;YACrB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAA;YAC1B,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAA;QAChC,CAAC;KAAA;IAEK,KAAK;;QAEX,CAAC;KAAA;IAEK,OAAO;;QAEb,CAAC;KAAA;CACF;AA1FD,kEA0FC","sourcesContent":["import { ISessionStreamProvider } from './session-stream-provider'\n\n/**\n * In-memory implementation of ISessionStreamProvider for testing.\n * Stores all data in buffers and strings for inspection.\n */\nexport class MemorySessionStreamProvider implements ISessionStreamProvider {\n private bodyBuffer: Buffer = Buffer.alloc(0)\n private headerLines: string[] = []\n private seqNumsContent: string | null = null\n private sessionTimeContent: string | null = null\n\n // Inspection methods for tests\n\n getBodyBytes (): Buffer {\n return Buffer.from(this.bodyBuffer)\n }\n\n getBodyString (): string {\n return this.bodyBuffer.toString('utf8')\n }\n\n getHeaderString (): string {\n return this.headerLines.join('\\n')\n }\n\n getHeaderLinesSnapshot (): string[] {\n return [...this.headerLines]\n }\n\n getSeqNumsContent (): string | null {\n return this.seqNumsContent\n }\n\n getSessionTimeContent (): string | null {\n return this.sessionTimeContent\n }\n\n // ISessionStreamProvider implementation\n\n openBody (): void {\n // No-op for memory provider, body is always available\n }\n\n async appendBody (data: Buffer): Promise<number> {\n const offset = this.bodyBuffer.length\n this.bodyBuffer = Buffer.concat([this.bodyBuffer, data])\n return offset\n }\n\n async readBody (offset: number, length: number): Promise<Buffer> {\n return this.bodyBuffer.subarray(offset, offset + length)\n }\n\n getBodySize (): number {\n return this.bodyBuffer.length\n }\n\n async appendHeaderLine (line: string): Promise<void> {\n this.headerLines.push(line)\n }\n\n async readHeaderLines (): Promise<string[]> {\n return [...this.headerLines]\n }\n\n async readSeqNums (): Promise<string | null> {\n return this.seqNumsContent\n }\n\n async writeSeqNums (content: string): Promise<void> {\n this.seqNumsContent = content\n }\n\n async readSessionTime (): Promise<string | null> {\n return this.sessionTimeContent\n }\n\n async writeSessionTime (content: string): Promise<void> {\n this.sessionTimeContent = content\n }\n\n async reset (): Promise<void> {\n this.bodyBuffer = Buffer.alloc(0)\n this.headerLines = []\n this.seqNumsContent = null\n this.sessionTimeContent = null\n }\n\n async flush (): Promise<void> {\n // No-op for memory provider\n }\n\n async dispose (): Promise<void> {\n // No-op for memory provider\n }\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare class SessionId {
|
|
2
|
+
readonly beginString: string;
|
|
3
|
+
readonly senderCompID: string;
|
|
4
|
+
readonly targetCompID: string;
|
|
5
|
+
constructor(beginString: string, senderCompID: string, targetCompID: string);
|
|
6
|
+
toFilePrefix(): string;
|
|
7
|
+
getFilePath(directory: string, extension: string): string;
|
|
8
|
+
toString(): string;
|
|
9
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.SessionId = void 0;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
class SessionId {
|
|
39
|
+
constructor(beginString, senderCompID, targetCompID) {
|
|
40
|
+
this.beginString = beginString;
|
|
41
|
+
this.senderCompID = senderCompID;
|
|
42
|
+
this.targetCompID = targetCompID;
|
|
43
|
+
}
|
|
44
|
+
toFilePrefix() {
|
|
45
|
+
return `${this.beginString}-${this.senderCompID}-${this.targetCompID}`;
|
|
46
|
+
}
|
|
47
|
+
getFilePath(directory, extension) {
|
|
48
|
+
return path.join(directory, `${this.toFilePrefix()}.${extension}`);
|
|
49
|
+
}
|
|
50
|
+
toString() {
|
|
51
|
+
return this.toFilePrefix();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.SessionId = SessionId;
|
|
55
|
+
//# sourceMappingURL=session-id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-id.js","sourceRoot":"","sources":["../../src/store/session-id.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA4B;AAM5B,MAAa,SAAS;IACpB,YACkB,WAAmB,EACnB,YAAoB,EACpB,YAAoB;QAFpB,gBAAW,GAAX,WAAW,CAAQ;QACnB,iBAAY,GAAZ,YAAY,CAAQ;QACpB,iBAAY,GAAZ,YAAY,CAAQ;IACnC,CAAC;IAMJ,YAAY;QACV,OAAO,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,YAAY,EAAE,CAAA;IACxE,CAAC;IAKD,WAAW,CAAE,SAAiB,EAAE,SAAiB;QAC/C,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,SAAS,EAAE,CAAC,CAAA;IACpE,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,YAAY,EAAE,CAAA;IAC5B,CAAC;CACF;AAzBD,8BAyBC","sourcesContent":["import * as path from 'path'\n\n/**\n * Identifies a FIX session for file naming and lookup.\n * Format: {BeginString}-{SenderCompID}-{TargetCompID}\n */\nexport class SessionId {\n constructor (\n public readonly beginString: string,\n public readonly senderCompID: string,\n public readonly targetCompID: string\n ) {}\n\n /**\n * Creates a file prefix for QuickFix-compatible file naming.\n * Example: \"FIX.4.4-SENDER-TARGET\"\n */\n toFilePrefix (): string {\n return `${this.beginString}-${this.senderCompID}-${this.targetCompID}`\n }\n\n /**\n * Gets the full path for a specific file extension.\n */\n getFilePath (directory: string, extension: string): string {\n return path.join(directory, `${this.toFilePrefix()}.${extension}`)\n }\n\n toString (): string {\n return this.toFilePrefix()\n }\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface ISessionStreamProvider {
|
|
2
|
+
openBody(): void;
|
|
3
|
+
appendBody(data: Buffer): Promise<number>;
|
|
4
|
+
readBody(offset: number, length: number): Promise<Buffer>;
|
|
5
|
+
getBodySize(): number;
|
|
6
|
+
appendHeaderLine(line: string): Promise<void>;
|
|
7
|
+
readHeaderLines(): Promise<string[]>;
|
|
8
|
+
readSeqNums(): Promise<string | null>;
|
|
9
|
+
writeSeqNums(content: string): Promise<void>;
|
|
10
|
+
readSessionTime(): Promise<string | null>;
|
|
11
|
+
writeSessionTime(content: string): Promise<void>;
|
|
12
|
+
reset(): Promise<void>;
|
|
13
|
+
flush(): Promise<void>;
|
|
14
|
+
dispose(): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-stream-provider.js","sourceRoot":"","sources":["../../src/store/session-stream-provider.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Provides stream access for session store operations.\n * Allows abstraction of file I/O for testing with in-memory buffers.\n */\nexport interface ISessionStreamProvider {\n /**\n * Opens or creates a read-write buffer for the message body file.\n * Must support random-access reads (by offset+length).\n */\n openBody (): void\n\n /**\n * Appends data to the body. Returns the offset at which data was written.\n */\n appendBody (data: Buffer): Promise<number>\n\n /**\n * Reads data from the body at the given offset and length.\n */\n readBody (offset: number, length: number): Promise<Buffer>\n\n /**\n * Gets the current body size (for calculating offsets).\n */\n getBodySize (): number\n\n /**\n * Appends a line to the header index file.\n */\n appendHeaderLine (line: string): Promise<void>\n\n /**\n * Reads all lines from the header index file.\n * Returns empty array if no data exists.\n */\n readHeaderLines (): Promise<string[]>\n\n /**\n * Reads the sequence numbers string.\n * Returns null if no data exists.\n */\n readSeqNums (): Promise<string | null>\n\n /**\n * Writes the sequence numbers string.\n */\n writeSeqNums (content: string): Promise<void>\n\n /**\n * Reads the session time string.\n * Returns null if no data exists.\n */\n readSessionTime (): Promise<string | null>\n\n /**\n * Writes the session time string.\n */\n writeSessionTime (content: string): Promise<void>\n\n /**\n * Resets all streams/files for a new session.\n */\n reset (): Promise<void>\n\n /**\n * Flushes any pending writes.\n */\n flush (): Promise<void>\n\n /**\n * Disposes of all resources.\n */\n dispose (): Promise<void>\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-config.js","sourceRoot":"","sources":["../../src/store/store-config.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Configuration for session message store.\n * Add to session description JSON to enable persistent storage.\n *\n * Examples:\n * \"store\": { \"type\": \"memory\" } — explicit in-memory (default)\n * \"store\": { \"type\": \"file\" } — file store in ./store directory\n * \"store\": { \"type\": \"file\", \"directory\": \"/var/fix/sessions\" }\n *\n * Omitting the store block entirely uses in-memory storage.\n */\nexport interface StoreConfig {\n readonly type: 'memory' | 'file'\n readonly directory?: string\n}\n"]}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { MsgView } from '../../buffer';
|
|
2
2
|
import { IJsFixConfig } from '../../config';
|
|
3
3
|
import { FixSession } from '../session/fix-session';
|
|
4
|
-
import { FixMsgAsciiStoreResend, IFixMsgStore } from '../../store';
|
|
4
|
+
import { FixMsgAsciiStoreResend, IFixMsgStore, IFixSessionStore, SessionId } from '../../store';
|
|
5
5
|
import { SessionSequenceCoordinator } from '../session/session-sequence-coordinator';
|
|
6
|
+
import { ILooseObject } from '../../collections/collection';
|
|
6
7
|
export declare abstract class AsciiSession extends FixSession {
|
|
7
8
|
readonly config: IJsFixConfig;
|
|
8
9
|
heartbeat: boolean;
|
|
9
10
|
protected store: IFixMsgStore | null;
|
|
10
11
|
protected resender: FixMsgAsciiStoreResend;
|
|
11
12
|
protected readonly coordinator: SessionSequenceCoordinator;
|
|
13
|
+
protected readonly sessionStore: IFixSessionStore;
|
|
14
|
+
protected readonly sessionId: SessionId;
|
|
12
15
|
protected constructor(config: IJsFixConfig);
|
|
13
16
|
private checkSeqNo;
|
|
14
17
|
protected checkForwardMsg(msgType: string, view: MsgView): void;
|
|
@@ -17,8 +20,10 @@ export declare abstract class AsciiSession extends FixSession {
|
|
|
17
20
|
private checkIntegrity;
|
|
18
21
|
protected onResendRequest(view: MsgView): void;
|
|
19
22
|
protected onPrepareForReconnect(): void;
|
|
23
|
+
protected txOnEncoded(msgType: string, data: string, hdr: ILooseObject): void;
|
|
20
24
|
private static readonly MaxLogonRetries;
|
|
21
25
|
private static readonly MaxTimeoutRecoveryAttempts;
|
|
26
|
+
private static createStoreFactory;
|
|
22
27
|
private handleLogonRejected;
|
|
23
28
|
okForLogon(): boolean;
|
|
24
29
|
protected onSessionMsg(msgType: string, view: MsgView): void;
|
|
@@ -8,12 +8,11 @@ const tcp_1 = require("../tcp");
|
|
|
8
8
|
const tick_action_1 = require("../tick-action");
|
|
9
9
|
const segment_type_1 = require("../../buffer/segment/segment-type");
|
|
10
10
|
const session_sequence_coordinator_1 = require("../session/session-sequence-coordinator");
|
|
11
|
-
const session_sequence_store_1 = require("../session/session-sequence-store");
|
|
12
11
|
const fix_clock_1 = require("../session/fix-clock");
|
|
13
12
|
const resend_request_manager_1 = require("../session/resend-request-manager");
|
|
14
13
|
class AsciiSession extends fix_session_1.FixSession {
|
|
15
14
|
constructor(config) {
|
|
16
|
-
var _a;
|
|
15
|
+
var _a, _b;
|
|
17
16
|
super(config);
|
|
18
17
|
this.config = config;
|
|
19
18
|
this.heartbeat = true;
|
|
@@ -22,10 +21,12 @@ class AsciiSession extends fix_session_1.FixSession {
|
|
|
22
21
|
this.requestLogonType = types_1.MsgType.Logon;
|
|
23
22
|
this.store = new store_1.FixMsgMemoryStore(this.config.description.SenderCompId, this.config);
|
|
24
23
|
this.resender = new store_1.FixMsgAsciiStoreResend(this.store, this.config);
|
|
25
|
-
const
|
|
24
|
+
const storeFactory = (_a = config.sessionStoreFactory) !== null && _a !== void 0 ? _a : AsciiSession.createStoreFactory(config.description.store);
|
|
25
|
+
this.sessionId = new store_1.SessionId(config.description.BeginString, config.description.SenderCompId, config.description.TargetCompID);
|
|
26
|
+
this.sessionStore = storeFactory.create(this.sessionId);
|
|
26
27
|
const clock = new fix_clock_1.DefaultFixClock();
|
|
27
|
-
this.coordinator = new session_sequence_coordinator_1.SessionSequenceCoordinator(
|
|
28
|
-
const lastReceivedSeqNum = (
|
|
28
|
+
this.coordinator = new session_sequence_coordinator_1.SessionSequenceCoordinator(this.sessionStore, clock);
|
|
29
|
+
const lastReceivedSeqNum = (_b = config.description.LastReceivedSeqNum) !== null && _b !== void 0 ? _b : 0;
|
|
29
30
|
this.coordinator.initializeFromConfig(undefined, lastReceivedSeqNum + 1);
|
|
30
31
|
}
|
|
31
32
|
checkSeqNo(msgType, view) {
|
|
@@ -55,6 +56,13 @@ class AsciiSession extends fix_session_1.FixSession {
|
|
|
55
56
|
this.coordinator.onMessageReceived(seqNo, true);
|
|
56
57
|
return true;
|
|
57
58
|
}
|
|
59
|
+
const pendingRequests = this.coordinator.pendingResendRequests;
|
|
60
|
+
const inPendingGapRange = pendingRequests.some(p => seqNo >= p.begin && seqNo <= p.end);
|
|
61
|
+
if (inPendingGapRange) {
|
|
62
|
+
this.sessionLogger.info(`accepting delayed message seq ${seqNo} (in pending gap range)`);
|
|
63
|
+
this.coordinator.onMessageReceived(seqNo, false);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
58
66
|
this.sessionLogger.warning(`terminate as seqDelta (${seqDelta}) < 0 lastSeq = ${lastSeq} seqNo = ${seqNo}`);
|
|
59
67
|
this.stop();
|
|
60
68
|
}
|
|
@@ -85,6 +93,8 @@ class AsciiSession extends fix_session_1.FixSession {
|
|
|
85
93
|
break;
|
|
86
94
|
}
|
|
87
95
|
}
|
|
96
|
+
ret = true;
|
|
97
|
+
state.lastPeerMsgSeqNum = seqNo;
|
|
88
98
|
this.coordinator.onMessageReceived(seqNo, false);
|
|
89
99
|
}
|
|
90
100
|
else {
|
|
@@ -208,6 +218,27 @@ class AsciiSession extends fix_session_1.FixSession {
|
|
|
208
218
|
this.coordinator.prepareForReconnect();
|
|
209
219
|
this.sessionLogger.info('coordinator reset transient state for reconnect');
|
|
210
220
|
}
|
|
221
|
+
txOnEncoded(msgType, data, hdr) {
|
|
222
|
+
super.txOnEncoded(msgType, data, hdr);
|
|
223
|
+
const seqNum = hdr === null || hdr === void 0 ? void 0 : hdr.MsgSeqNum;
|
|
224
|
+
if (seqNum != null) {
|
|
225
|
+
const record = new store_1.FixMsgStoreRecord(msgType, new Date(), seqNum, undefined, data);
|
|
226
|
+
this.sessionStore.put(record).catch((e) => {
|
|
227
|
+
this.sessionLogger.warning(`failed to store message seq=${seqNum}: ${e.message}`);
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
static createStoreFactory(storeConfig) {
|
|
232
|
+
var _a, _b;
|
|
233
|
+
if (!storeConfig)
|
|
234
|
+
return new store_1.MemorySessionStoreFactory();
|
|
235
|
+
switch ((_a = storeConfig.type) === null || _a === void 0 ? void 0 : _a.toLowerCase()) {
|
|
236
|
+
case 'file':
|
|
237
|
+
return new store_1.FileSessionStoreFactory((_b = storeConfig.directory) !== null && _b !== void 0 ? _b : 'store');
|
|
238
|
+
default:
|
|
239
|
+
return new store_1.MemorySessionStoreFactory();
|
|
240
|
+
}
|
|
241
|
+
}
|
|
211
242
|
handleLogonRejected(text) {
|
|
212
243
|
if (!this.coordinator.onLogonRejectedForSequence(AsciiSession.MaxLogonRetries)) {
|
|
213
244
|
this.sessionLogger.warning(`max logon retries (${AsciiSession.MaxLogonRetries}) exceeded, giving up. Text='${text}'`);
|
|
@@ -401,6 +432,7 @@ class AsciiSession extends fix_session_1.FixSession {
|
|
|
401
432
|
const action = sessionState.calcAction(new Date());
|
|
402
433
|
const application = (_a = this.transport.config.description.application) !== null && _a !== void 0 ? _a : null;
|
|
403
434
|
const logger = this.sessionLogger;
|
|
435
|
+
this.coordinator.tick();
|
|
404
436
|
switch (action) {
|
|
405
437
|
case tick_action_1.TickAction.Nothing: {
|
|
406
438
|
break;
|