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.
Files changed (45) hide show
  1. package/BACKPORT_PLAN.md +120 -10
  2. package/dist/dictionary/parser/quickfix/dictionary-validator.d.ts +39 -0
  3. package/dist/dictionary/parser/quickfix/dictionary-validator.js +321 -0
  4. package/dist/dictionary/parser/quickfix/dictionary-validator.js.map +1 -0
  5. package/dist/dictionary/parser/quickfix/index-visitor.d.ts +10 -0
  6. package/dist/dictionary/parser/quickfix/index-visitor.js +68 -0
  7. package/dist/dictionary/parser/quickfix/index-visitor.js.map +1 -0
  8. package/dist/dictionary/parser/quickfix/index.d.ts +7 -0
  9. package/dist/dictionary/parser/quickfix/index.js +7 -0
  10. package/dist/dictionary/parser/quickfix/index.js.map +1 -1
  11. package/dist/dictionary/parser/quickfix/quick-fix-graph-file-parser.d.ts +13 -0
  12. package/dist/dictionary/parser/quickfix/quick-fix-graph-file-parser.js +65 -0
  13. package/dist/dictionary/parser/quickfix/quick-fix-graph-file-parser.js.map +1 -0
  14. package/dist/dictionary/parser/quickfix/quick-fix-graph-parser.d.ts +73 -0
  15. package/dist/dictionary/parser/quickfix/quick-fix-graph-parser.js +363 -0
  16. package/dist/dictionary/parser/quickfix/quick-fix-graph-parser.js.map +1 -0
  17. package/dist/dictionary/parser/quickfix/sax-tree-builder.d.ts +5 -0
  18. package/dist/dictionary/parser/quickfix/sax-tree-builder.js +103 -0
  19. package/dist/dictionary/parser/quickfix/sax-tree-builder.js.map +1 -0
  20. package/dist/dictionary/parser/quickfix/validation-error.d.ts +17 -0
  21. package/dist/dictionary/parser/quickfix/validation-error.js +32 -0
  22. package/dist/dictionary/parser/quickfix/validation-error.js.map +1 -0
  23. package/dist/dictionary/parser/quickfix/x-element.d.ts +26 -0
  24. package/dist/dictionary/parser/quickfix/x-element.js +82 -0
  25. package/dist/dictionary/parser/quickfix/x-element.js.map +1 -0
  26. package/dist/store/fix-msg-ascii-store-resend.js +6 -0
  27. package/dist/store/fix-msg-ascii-store-resend.js.map +1 -1
  28. package/dist/store/store-config.d.ts +1 -0
  29. package/dist/store/store-config.js.map +1 -1
  30. package/dist/util/definition-factory.js +1 -1
  31. package/dist/util/definition-factory.js.map +1 -1
  32. package/jsfix.test_client.txt +67 -67
  33. package/jsfix.test_server.txt +64 -64
  34. package/package.json +6 -6
  35. package/src/dictionary/parser/quickfix/dictionary-validator.ts +473 -0
  36. package/src/dictionary/parser/quickfix/index-visitor.ts +100 -0
  37. package/src/dictionary/parser/quickfix/index.ts +7 -0
  38. package/src/dictionary/parser/quickfix/quick-fix-graph-file-parser.ts +63 -0
  39. package/src/dictionary/parser/quickfix/quick-fix-graph-parser.ts +450 -0
  40. package/src/dictionary/parser/quickfix/sax-tree-builder.ts +112 -0
  41. package/src/dictionary/parser/quickfix/validation-error.ts +34 -0
  42. package/src/dictionary/parser/quickfix/x-element.ts +115 -0
  43. package/src/store/fix-msg-ascii-store-resend.ts +8 -0
  44. package/src/store/store-config.ts +1 -0
  45. 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
@@ -12,4 +12,5 @@
12
12
  export interface StoreConfig {
13
13
  readonly type: 'memory' | 'file'
14
14
  readonly directory?: string
15
+ readonly resendGapFillOnly?: boolean
15
16
  }
@@ -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, QuickFixXmlFileParser, RepositoryXmlParser } from '../dictionary/parser'
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 QuickFixXmlFileParser(() => new FileDuplex(path), getLogger)
35
+ parser = new QuickFixGraphFileParser(() => new FileDuplex(path), getLogger)
36
36
  }
37
37
  return parser
38
38
  }