jspurefix 5.3.0 → 5.5.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 +120 -10
- package/dist/dictionary/parser/quickfix/dictionary-validator.d.ts +39 -0
- package/dist/dictionary/parser/quickfix/dictionary-validator.js +321 -0
- package/dist/dictionary/parser/quickfix/dictionary-validator.js.map +1 -0
- package/dist/dictionary/parser/quickfix/index-visitor.d.ts +10 -0
- package/dist/dictionary/parser/quickfix/index-visitor.js +68 -0
- package/dist/dictionary/parser/quickfix/index-visitor.js.map +1 -0
- package/dist/dictionary/parser/quickfix/index.d.ts +7 -0
- package/dist/dictionary/parser/quickfix/index.js +7 -0
- package/dist/dictionary/parser/quickfix/index.js.map +1 -1
- package/dist/dictionary/parser/quickfix/quick-fix-graph-file-parser.d.ts +13 -0
- package/dist/dictionary/parser/quickfix/quick-fix-graph-file-parser.js +65 -0
- package/dist/dictionary/parser/quickfix/quick-fix-graph-file-parser.js.map +1 -0
- package/dist/dictionary/parser/quickfix/quick-fix-graph-parser.d.ts +73 -0
- package/dist/dictionary/parser/quickfix/quick-fix-graph-parser.js +363 -0
- package/dist/dictionary/parser/quickfix/quick-fix-graph-parser.js.map +1 -0
- package/dist/dictionary/parser/quickfix/sax-tree-builder.d.ts +5 -0
- package/dist/dictionary/parser/quickfix/sax-tree-builder.js +103 -0
- package/dist/dictionary/parser/quickfix/sax-tree-builder.js.map +1 -0
- package/dist/dictionary/parser/quickfix/validation-error.d.ts +17 -0
- package/dist/dictionary/parser/quickfix/validation-error.js +32 -0
- package/dist/dictionary/parser/quickfix/validation-error.js.map +1 -0
- package/dist/dictionary/parser/quickfix/x-element.d.ts +26 -0
- package/dist/dictionary/parser/quickfix/x-element.js +82 -0
- package/dist/dictionary/parser/quickfix/x-element.js.map +1 -0
- package/dist/store/fix-msg-ascii-store-resend.js +6 -0
- package/dist/store/fix-msg-ascii-store-resend.js.map +1 -1
- package/dist/store/store-config.d.ts +1 -0
- package/dist/store/store-config.js.map +1 -1
- package/dist/util/definition-factory.js +1 -1
- package/dist/util/definition-factory.js.map +1 -1
- package/jsfix.test_client.txt +67 -67
- package/jsfix.test_server.txt +64 -64
- package/package.json +6 -6
- package/src/dictionary/parser/quickfix/dictionary-validator.ts +473 -0
- package/src/dictionary/parser/quickfix/index-visitor.ts +100 -0
- package/src/dictionary/parser/quickfix/index.ts +7 -0
- package/src/dictionary/parser/quickfix/quick-fix-graph-file-parser.ts +63 -0
- package/src/dictionary/parser/quickfix/quick-fix-graph-parser.ts +450 -0
- package/src/dictionary/parser/quickfix/sax-tree-builder.ts +112 -0
- package/src/dictionary/parser/quickfix/validation-error.ts +34 -0
- package/src/dictionary/parser/quickfix/x-element.ts +115 -0
- package/src/store/fix-msg-ascii-store-resend.ts +8 -0
- package/src/store/store-config.ts +1 -0
- package/src/util/definition-factory.ts +2 -2
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight in-memory XML element tree — provides DOM-like random access
|
|
3
|
+
* over XML parsed by SAX. Mirrors the C# XDocument/XElement API surface
|
|
4
|
+
* used by QuickFixXmlFileParser and DictionaryValidator.
|
|
5
|
+
*/
|
|
6
|
+
export interface XElement {
|
|
7
|
+
readonly name: string
|
|
8
|
+
readonly attributes: Record<string, string>
|
|
9
|
+
readonly children: XElement[]
|
|
10
|
+
readonly line?: number
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Query helper wrapping an XElement tree with C#-style traversal methods.
|
|
15
|
+
* Mirrors XDocument/XElement LINQ-to-XML API used in cspurefix.
|
|
16
|
+
*/
|
|
17
|
+
export class XNode {
|
|
18
|
+
constructor (public readonly element: XElement) {}
|
|
19
|
+
|
|
20
|
+
/** Attribute value by name, or undefined if not present. */
|
|
21
|
+
attribute (name: string): string | undefined {
|
|
22
|
+
return this.element.attributes[name]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Direct children with the given tag name. */
|
|
26
|
+
elements (name?: string): XNode[] {
|
|
27
|
+
const children = name
|
|
28
|
+
? this.element.children.filter(c => c.name === name)
|
|
29
|
+
: this.element.children
|
|
30
|
+
return children.map(c => new XNode(c))
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** First direct child with the given tag name, or undefined. */
|
|
34
|
+
firstElement (name: string): XNode | undefined {
|
|
35
|
+
const child = this.element.children.find(c => c.name === name)
|
|
36
|
+
return child ? new XNode(child) : undefined
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** All descendants (recursive) with the given tag name. */
|
|
40
|
+
descendants (name: string): XNode[] {
|
|
41
|
+
const result: XNode[] = []
|
|
42
|
+
this.collectDescendants(this.element, name, result)
|
|
43
|
+
return result
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** First descendant with the given tag name, or undefined. */
|
|
47
|
+
firstDescendant (name: string): XNode | undefined {
|
|
48
|
+
return this.findDescendant(this.element, name)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Shorthand: attribute value, throwing if missing. */
|
|
52
|
+
requiredAttribute (name: string): string {
|
|
53
|
+
const val = this.element.attributes[name]
|
|
54
|
+
if (val === undefined) {
|
|
55
|
+
throw new Error(`missing required attribute '${name}' on <${this.element.name}> at line ${this.element.line ?? '?'}`)
|
|
56
|
+
}
|
|
57
|
+
return val
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** The element's tag name. */
|
|
61
|
+
get name (): string {
|
|
62
|
+
return this.element.name
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** The element's source line number, if available. */
|
|
66
|
+
get line (): number | undefined {
|
|
67
|
+
return this.element.line
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private collectDescendants (el: XElement, name: string, result: XNode[]): void {
|
|
71
|
+
for (const child of el.children) {
|
|
72
|
+
if (child.name === name) {
|
|
73
|
+
result.push(new XNode(child))
|
|
74
|
+
}
|
|
75
|
+
this.collectDescendants(child, name, result)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private findDescendant (el: XElement, name: string): XNode | undefined {
|
|
80
|
+
for (const child of el.children) {
|
|
81
|
+
if (child.name === name) {
|
|
82
|
+
return new XNode(child)
|
|
83
|
+
}
|
|
84
|
+
const found = this.findDescendant(child, name)
|
|
85
|
+
if (found) return found
|
|
86
|
+
}
|
|
87
|
+
return undefined
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Parsed XML document — wraps the root element with query methods.
|
|
93
|
+
* Equivalent to C# XDocument.
|
|
94
|
+
*/
|
|
95
|
+
export class XDocument {
|
|
96
|
+
public readonly root: XNode
|
|
97
|
+
|
|
98
|
+
constructor (rootElement: XElement) {
|
|
99
|
+
this.root = new XNode(rootElement)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** All descendants of the root with the given tag name (including the root itself if it matches). */
|
|
103
|
+
descendants (name: string): XNode[] {
|
|
104
|
+
const result: XNode[] = []
|
|
105
|
+
if (this.root.name === name) result.push(this.root)
|
|
106
|
+
result.push(...this.root.descendants(name))
|
|
107
|
+
return result
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** First descendant of the root with the given tag name (including the root itself if it matches). */
|
|
111
|
+
firstDescendant (name: string): XNode | undefined {
|
|
112
|
+
if (this.root.name === name) return this.root
|
|
113
|
+
return this.root.firstDescendant(name)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -13,6 +13,14 @@ export class FixMsgAsciiStoreResend {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
public async getResendRequest (startSeq: number, endSeq: number): Promise<IFixMsgStoreRecord[]> {
|
|
16
|
+
// Safety feature: If ResendGapFillOnly is enabled, ALWAYS send GapFill instead of
|
|
17
|
+
// replaying stored messages. This prevents accidental duplicate order execution.
|
|
18
|
+
if (this.config.description.store?.resendGapFillOnly === true) {
|
|
19
|
+
const gapFillOnly: IFixMsgStoreRecord[] = []
|
|
20
|
+
this.gap(startSeq, endSeq + 1, gapFillOnly)
|
|
21
|
+
return gapFillOnly
|
|
22
|
+
}
|
|
23
|
+
|
|
16
24
|
// need to cover request from start to end where any missing numbers are
|
|
17
25
|
// included as gaps to allow vector of messages to be sent by the session
|
|
18
26
|
// on a request
|
|
@@ -3,7 +3,7 @@ import { FixDefinitions } from '../dictionary/definition'
|
|
|
3
3
|
import { GetJsFixLogger, makeEmptyLogger } from '../config'
|
|
4
4
|
import * as path from 'path'
|
|
5
5
|
import * as fs from 'fs'
|
|
6
|
-
import { FixXsdParser,
|
|
6
|
+
import { FixXsdParser, QuickFixGraphFileParser, RepositoryXmlParser } from '../dictionary/parser'
|
|
7
7
|
import { IDictionaryPath } from './dictionary-path'
|
|
8
8
|
import { FileDuplex } from '../transport'
|
|
9
9
|
|
|
@@ -32,7 +32,7 @@ export class DefinitionFactory {
|
|
|
32
32
|
} else if (fs.lstatSync(path).isDirectory()) {
|
|
33
33
|
parser = new RepositoryXmlParser(path, getLogger)
|
|
34
34
|
} else {
|
|
35
|
-
parser = new
|
|
35
|
+
parser = new QuickFixGraphFileParser(() => new FileDuplex(path), getLogger)
|
|
36
36
|
}
|
|
37
37
|
return parser
|
|
38
38
|
}
|