@xapi-js/core 1.2.0 → 1.4.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/LICENSE +21 -21
- package/README.md +21 -1
- package/dist/index.cjs +610 -218
- package/dist/index.d.cts +160 -26
- package/dist/index.d.ts +160 -26
- package/dist/index.js +599 -192
- package/package.json +2 -6
package/dist/index.cjs
CHANGED
|
@@ -1,31 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
-
key = keys[i];
|
|
11
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
-
get: ((k) => from[k]).bind(null, key),
|
|
13
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
-
value: mod,
|
|
20
|
-
enumerable: true
|
|
21
|
-
}) : target, mod));
|
|
22
|
-
|
|
23
|
-
//#endregion
|
|
24
|
-
let stax_xml = require("stax-xml");
|
|
25
|
-
stax_xml = __toESM(stax_xml);
|
|
26
|
-
let txml = require("txml");
|
|
27
|
-
txml = __toESM(txml);
|
|
28
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
29
2
|
//#region src/types.ts
|
|
30
3
|
/**
|
|
31
4
|
* Defines the possible types of rows in an X-API dataset (e.g., "insert", "update", "delete").
|
|
@@ -78,7 +51,6 @@ var InvalidXmlError = class extends Error {
|
|
|
78
51
|
this.name = "InvalidXmlError";
|
|
79
52
|
}
|
|
80
53
|
};
|
|
81
|
-
|
|
82
54
|
//#endregion
|
|
83
55
|
//#region src/xapi-data.ts
|
|
84
56
|
/**
|
|
@@ -163,18 +135,18 @@ var XapiRoot = class {
|
|
|
163
135
|
return this.datasets.length;
|
|
164
136
|
}
|
|
165
137
|
/**
|
|
166
|
-
*
|
|
167
|
-
* @returns An
|
|
138
|
+
* Returns all parameters as an array.
|
|
139
|
+
* @returns An array of parameters.
|
|
168
140
|
*/
|
|
169
|
-
|
|
170
|
-
|
|
141
|
+
getParameters() {
|
|
142
|
+
return this.parameters.params;
|
|
171
143
|
}
|
|
172
144
|
/**
|
|
173
|
-
*
|
|
174
|
-
* @returns An
|
|
145
|
+
* Returns all datasets as an array.
|
|
146
|
+
* @returns An array of datasets.
|
|
175
147
|
*/
|
|
176
|
-
|
|
177
|
-
|
|
148
|
+
getDatasets() {
|
|
149
|
+
return this.datasets;
|
|
178
150
|
}
|
|
179
151
|
};
|
|
180
152
|
/**
|
|
@@ -302,25 +274,25 @@ var Dataset = class {
|
|
|
302
274
|
} else throw new Error(`Row index ${rowIdx} out of bounds in dataset ${this.id}`);
|
|
303
275
|
}
|
|
304
276
|
/**
|
|
305
|
-
*
|
|
306
|
-
* @returns An
|
|
277
|
+
* Returns all constant column definitions as an array.
|
|
278
|
+
* @returns An array of constant columns.
|
|
307
279
|
*/
|
|
308
|
-
|
|
309
|
-
|
|
280
|
+
getConstColumns() {
|
|
281
|
+
return this.constColumns;
|
|
310
282
|
}
|
|
311
283
|
/**
|
|
312
|
-
*
|
|
313
|
-
* @returns An
|
|
284
|
+
* Returns all column definitions as an array.
|
|
285
|
+
* @returns An array of columns.
|
|
314
286
|
*/
|
|
315
|
-
|
|
316
|
-
|
|
287
|
+
getColumns() {
|
|
288
|
+
return this.columns;
|
|
317
289
|
}
|
|
318
290
|
/**
|
|
319
|
-
*
|
|
320
|
-
* @returns An
|
|
291
|
+
* Returns all rows in the dataset as an array.
|
|
292
|
+
* @returns An array of rows.
|
|
321
293
|
*/
|
|
322
|
-
|
|
323
|
-
|
|
294
|
+
getRows() {
|
|
295
|
+
return this.rows;
|
|
324
296
|
}
|
|
325
297
|
/**
|
|
326
298
|
* Returns the number of column definitions.
|
|
@@ -344,35 +316,30 @@ var Dataset = class {
|
|
|
344
316
|
return this.rows.length;
|
|
345
317
|
}
|
|
346
318
|
};
|
|
347
|
-
|
|
348
319
|
//#endregion
|
|
349
320
|
//#region src/utils.ts
|
|
350
321
|
function arrayBufferToString(buffer) {
|
|
351
322
|
return new TextDecoder().decode(buffer);
|
|
352
323
|
}
|
|
353
324
|
/**
|
|
354
|
-
*
|
|
355
|
-
*
|
|
325
|
+
* Pre-defined XML entities for parsing, including control characters.
|
|
326
|
+
* Static array to avoid repeated allocation.
|
|
356
327
|
*/
|
|
357
|
-
|
|
358
|
-
const entities
|
|
359
|
-
for (let i = 1; i <= 32; i++) entities
|
|
328
|
+
const PARSE_ENTITIES = (() => {
|
|
329
|
+
const entities = [];
|
|
330
|
+
for (let i = 1; i <= 32; i++) entities.push({
|
|
360
331
|
entity: `&#${i};`,
|
|
361
332
|
value: String.fromCharCode(i)
|
|
362
333
|
});
|
|
363
|
-
return entities
|
|
364
|
-
}
|
|
334
|
+
return entities;
|
|
335
|
+
})();
|
|
365
336
|
/**
|
|
366
|
-
* Creates an array of entities for
|
|
337
|
+
* Creates an array of entities for parsing XML, including control characters.
|
|
338
|
+
* @deprecated Use PARSE_ENTITIES directly for better performance
|
|
367
339
|
* @returns An array of objects, each with an `entity` (e.g., "") and its `value` (e.g., "\x01").
|
|
368
340
|
*/
|
|
369
|
-
function
|
|
370
|
-
|
|
371
|
-
for (let i = 1; i <= 32; i++) entities$1.push({
|
|
372
|
-
entity: `&#${i};`,
|
|
373
|
-
value: String.fromCharCode(i)
|
|
374
|
-
});
|
|
375
|
-
return entities$1;
|
|
341
|
+
function makeParseEntities() {
|
|
342
|
+
return PARSE_ENTITIES.slice();
|
|
376
343
|
}
|
|
377
344
|
/**
|
|
378
345
|
* Converts a Base64 string to a Uint8Array.
|
|
@@ -501,10 +468,10 @@ function stringToReadableStream(str) {
|
|
|
501
468
|
function convertToColumnType(value, type) {
|
|
502
469
|
switch (type) {
|
|
503
470
|
case "INT":
|
|
504
|
-
case "BIGDECIMAL":
|
|
505
471
|
const intValue = parseInt(value, 10);
|
|
506
472
|
return isNaN(intValue) ? value : intValue;
|
|
507
473
|
case "FLOAT":
|
|
474
|
+
case "BIGDECIMAL":
|
|
508
475
|
const floatValue = parseFloat(value);
|
|
509
476
|
return isNaN(floatValue) ? value : floatValue;
|
|
510
477
|
case "DECIMAL":
|
|
@@ -542,19 +509,338 @@ function convertToString(value, type) {
|
|
|
542
509
|
default: return String(value);
|
|
543
510
|
}
|
|
544
511
|
}
|
|
545
|
-
|
|
512
|
+
/**
|
|
513
|
+
* Pre-compiled regex for control character entities.
|
|
514
|
+
* Created once to avoid repeated compilation.
|
|
515
|
+
*/
|
|
516
|
+
const CONTROL_CHAR_ENTITY_REGEX = new RegExp(PARSE_ENTITIES.map((e) => e.entity.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|"), "g");
|
|
517
|
+
/**
|
|
518
|
+
* Map for fast entity lookup during decoding.
|
|
519
|
+
*/
|
|
520
|
+
const ENTITY_MAP = new Map(PARSE_ENTITIES.map((e) => [e.entity, e.value]));
|
|
546
521
|
function _unescapeXml(str) {
|
|
547
522
|
if (!str) return str;
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
return
|
|
523
|
+
if (str.indexOf("&") === -1) return str;
|
|
524
|
+
let result = str.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, "\"").replace(/'/g, "'").replace(/&/g, "&");
|
|
525
|
+
result = result.replace(CONTROL_CHAR_ENTITY_REGEX, (match) => {
|
|
526
|
+
return ENTITY_MAP.get(match) || match;
|
|
552
527
|
});
|
|
528
|
+
return result;
|
|
553
529
|
}
|
|
554
530
|
function isXapiRoot(value) {
|
|
555
531
|
return value instanceof XapiRoot;
|
|
556
532
|
}
|
|
557
|
-
|
|
533
|
+
/**
|
|
534
|
+
* Escapes XML special characters in a string.
|
|
535
|
+
* @param str - The string to escape.
|
|
536
|
+
* @returns The escaped string.
|
|
537
|
+
*/
|
|
538
|
+
function escapeXml(str) {
|
|
539
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Encodes control characters as XML entities, excluding standard whitespace.
|
|
543
|
+
* Encodes 0x01-0x08, 0x0B-0x0C, 0x0E-0x1F but NOT 0x09 (tab), 0x0A (LF), 0x0D (CR), 0x20 (space).
|
|
544
|
+
* @param str - The string to encode.
|
|
545
|
+
* @returns The encoded string.
|
|
546
|
+
*/
|
|
547
|
+
function encodeControlChars(str) {
|
|
548
|
+
let result = "";
|
|
549
|
+
for (let i = 0; i < str.length; i++) {
|
|
550
|
+
const charCode = str.charCodeAt(i);
|
|
551
|
+
if (charCode >= 1 && charCode <= 8 || charCode >= 11 && charCode <= 12 || charCode >= 14 && charCode <= 31) result += `&#${charCode};`;
|
|
552
|
+
else result += str[i];
|
|
553
|
+
}
|
|
554
|
+
return result;
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* A string builder for generating formatted XML.
|
|
558
|
+
*/
|
|
559
|
+
var XmlStringBuilder = class {
|
|
560
|
+
lines = [];
|
|
561
|
+
indentLevel = 0;
|
|
562
|
+
indentString = " ";
|
|
563
|
+
/**
|
|
564
|
+
* Writes the XML declaration.
|
|
565
|
+
* @param version - The XML version (default: "1.0").
|
|
566
|
+
* @param encoding - The encoding (default: "UTF-8").
|
|
567
|
+
*/
|
|
568
|
+
writeDeclaration(version = "1.0", encoding = "UTF-8") {
|
|
569
|
+
this.lines.push(`<?xml version="${version}" encoding="${encoding}"?>`);
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Writes a start element tag.
|
|
573
|
+
* @param name - The element name.
|
|
574
|
+
* @param attributes - Optional attributes object.
|
|
575
|
+
* @param selfClosing - Whether to create a self-closing tag.
|
|
576
|
+
*/
|
|
577
|
+
writeStartElement(name, attributes, selfClosing) {
|
|
578
|
+
let tag = `${this.indentString.repeat(this.indentLevel)}<${name}`;
|
|
579
|
+
if (attributes) for (const [key, value] of Object.entries(attributes)) {
|
|
580
|
+
const encodedValue = encodeControlChars(escapeXml(value));
|
|
581
|
+
tag += ` ${key}="${encodedValue}"`;
|
|
582
|
+
}
|
|
583
|
+
if (selfClosing) {
|
|
584
|
+
tag += "/>";
|
|
585
|
+
this.lines.push(tag);
|
|
586
|
+
} else {
|
|
587
|
+
tag += ">";
|
|
588
|
+
this.lines.push(tag);
|
|
589
|
+
this.indentLevel++;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Writes an end element tag.
|
|
594
|
+
* @param name - The element name.
|
|
595
|
+
*/
|
|
596
|
+
writeEndElement(name) {
|
|
597
|
+
this.indentLevel--;
|
|
598
|
+
const indent = this.indentString.repeat(this.indentLevel);
|
|
599
|
+
this.lines.push(`${indent}</${name}>`);
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Writes an element with text content.
|
|
603
|
+
* @param name - The element name.
|
|
604
|
+
* @param attributes - Optional attributes object.
|
|
605
|
+
* @param text - The text content.
|
|
606
|
+
*/
|
|
607
|
+
writeElementWithText(name, attributes, text) {
|
|
608
|
+
let tag = `${this.indentString.repeat(this.indentLevel)}<${name}`;
|
|
609
|
+
if (attributes) for (const [key, value] of Object.entries(attributes)) {
|
|
610
|
+
const encodedValue = encodeControlChars(escapeXml(value));
|
|
611
|
+
tag += ` ${key}="${encodedValue}"`;
|
|
612
|
+
}
|
|
613
|
+
const encodedText = encodeControlChars(escapeXml(text));
|
|
614
|
+
tag += `>${encodedText}</${name}>`;
|
|
615
|
+
this.lines.push(tag);
|
|
616
|
+
}
|
|
617
|
+
/**
|
|
618
|
+
* Returns the generated XML string.
|
|
619
|
+
* @returns The complete XML string with line breaks.
|
|
620
|
+
*/
|
|
621
|
+
toString() {
|
|
622
|
+
return this.lines.join("\n") + "\n";
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
/**
|
|
626
|
+
* Parses XML string into an XML node structure.
|
|
627
|
+
* This is a lightweight parser optimized for X-API XML structure.
|
|
628
|
+
*
|
|
629
|
+
* @param xml - The XML string to parse.
|
|
630
|
+
* @returns An array of parsed XML nodes.
|
|
631
|
+
*/
|
|
632
|
+
function parseXml(xml) {
|
|
633
|
+
if (!xml || xml.trim() === "") return [];
|
|
634
|
+
return new XapiXmlParser(xml).parse();
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Character codes for fast comparison
|
|
638
|
+
*/
|
|
639
|
+
const CHAR_SPACE = 32;
|
|
640
|
+
const CHAR_TAB = 9;
|
|
641
|
+
const CHAR_LF = 10;
|
|
642
|
+
const CHAR_CR = 13;
|
|
643
|
+
const CHAR_GT = 62;
|
|
644
|
+
const CHAR_SLASH = 47;
|
|
645
|
+
const CHAR_EQUALS = 61;
|
|
646
|
+
const CHAR_QUOTE = 34;
|
|
647
|
+
const CHAR_APOS = 39;
|
|
648
|
+
/**
|
|
649
|
+
* A lightweight XML parser optimized for X-API structure.
|
|
650
|
+
*/
|
|
651
|
+
var XapiXmlParser = class {
|
|
652
|
+
xml;
|
|
653
|
+
pos = 0;
|
|
654
|
+
length;
|
|
655
|
+
constructor(xml) {
|
|
656
|
+
this.xml = xml;
|
|
657
|
+
this.length = xml.length;
|
|
658
|
+
}
|
|
659
|
+
parse() {
|
|
660
|
+
const nodes = [];
|
|
661
|
+
while (this.pos < this.length) {
|
|
662
|
+
this.skipWhitespace();
|
|
663
|
+
if (this.pos >= this.length) break;
|
|
664
|
+
if (this.matches("<?xml")) {
|
|
665
|
+
this.skipUntil("?>");
|
|
666
|
+
this.pos += 2;
|
|
667
|
+
continue;
|
|
668
|
+
}
|
|
669
|
+
if (this.matches("<!--")) {
|
|
670
|
+
this.skipUntil("-->");
|
|
671
|
+
this.pos += 3;
|
|
672
|
+
continue;
|
|
673
|
+
}
|
|
674
|
+
if (this.current() === "<") {
|
|
675
|
+
const node = this.parseElement();
|
|
676
|
+
if (node) nodes.push(node);
|
|
677
|
+
} else this.pos++;
|
|
678
|
+
}
|
|
679
|
+
return nodes;
|
|
680
|
+
}
|
|
681
|
+
parseElement() {
|
|
682
|
+
if (this.current() !== "<") return null;
|
|
683
|
+
this.pos++;
|
|
684
|
+
if (this.current() === "/") return null;
|
|
685
|
+
const tagName = this.parseTagName();
|
|
686
|
+
if (!tagName) return null;
|
|
687
|
+
const node = {
|
|
688
|
+
tagName,
|
|
689
|
+
attributes: void 0,
|
|
690
|
+
children: void 0
|
|
691
|
+
};
|
|
692
|
+
const attributes = this.parseAttributes();
|
|
693
|
+
if (attributes && Object.keys(attributes).length > 0) node.attributes = attributes;
|
|
694
|
+
this.skipWhitespace();
|
|
695
|
+
if (this.matches("/>")) {
|
|
696
|
+
this.pos += 2;
|
|
697
|
+
return node;
|
|
698
|
+
}
|
|
699
|
+
if (this.current() === ">") this.pos++;
|
|
700
|
+
const children = [];
|
|
701
|
+
let textContent = "";
|
|
702
|
+
while (this.pos < this.length) {
|
|
703
|
+
if (this.matches("<![CDATA[")) {
|
|
704
|
+
const cdataText = this.parseCDATA();
|
|
705
|
+
if (cdataText !== null) textContent += cdataText;
|
|
706
|
+
continue;
|
|
707
|
+
}
|
|
708
|
+
if (this.matches("</")) {
|
|
709
|
+
if (textContent) children.push(textContent);
|
|
710
|
+
this.pos += 2;
|
|
711
|
+
this.skipUntil(">");
|
|
712
|
+
this.pos++;
|
|
713
|
+
break;
|
|
714
|
+
}
|
|
715
|
+
if (this.current() === "<") {
|
|
716
|
+
if (textContent.trim()) {
|
|
717
|
+
children.push(textContent);
|
|
718
|
+
textContent = "";
|
|
719
|
+
}
|
|
720
|
+
const child = this.parseElement();
|
|
721
|
+
if (child) children.push(child);
|
|
722
|
+
} else {
|
|
723
|
+
textContent += this.current();
|
|
724
|
+
this.pos++;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
if (children.length > 0) node.children = children;
|
|
728
|
+
return node;
|
|
729
|
+
}
|
|
730
|
+
parseTagName() {
|
|
731
|
+
const start = this.pos;
|
|
732
|
+
while (this.pos < this.length) {
|
|
733
|
+
const code = this.currentCharCode();
|
|
734
|
+
if (this.isWhitespace(code) || code === CHAR_GT || code === CHAR_SLASH) break;
|
|
735
|
+
this.pos++;
|
|
736
|
+
}
|
|
737
|
+
return this.xml.substring(start, this.pos);
|
|
738
|
+
}
|
|
739
|
+
parseAttributes() {
|
|
740
|
+
const attrs = {};
|
|
741
|
+
while (this.pos < this.length) {
|
|
742
|
+
this.skipWhitespace();
|
|
743
|
+
const ch = this.current();
|
|
744
|
+
if (ch === ">" || ch === "/" || this.matches("/>")) break;
|
|
745
|
+
const attrName = this.parseAttributeName();
|
|
746
|
+
if (!attrName) break;
|
|
747
|
+
this.skipWhitespace();
|
|
748
|
+
if (this.current() === "=") this.pos++;
|
|
749
|
+
this.skipWhitespace();
|
|
750
|
+
attrs[attrName] = this.parseAttributeValue();
|
|
751
|
+
}
|
|
752
|
+
return Object.keys(attrs).length > 0 ? attrs : void 0;
|
|
753
|
+
}
|
|
754
|
+
parseAttributeName() {
|
|
755
|
+
const start = this.pos;
|
|
756
|
+
while (this.pos < this.length) {
|
|
757
|
+
const code = this.currentCharCode();
|
|
758
|
+
if (code === CHAR_EQUALS || this.isWhitespace(code) || code === CHAR_GT || code === CHAR_SLASH) break;
|
|
759
|
+
this.pos++;
|
|
760
|
+
}
|
|
761
|
+
return this.xml.substring(start, this.pos);
|
|
762
|
+
}
|
|
763
|
+
parseAttributeValue() {
|
|
764
|
+
const quoteCode = this.currentCharCode();
|
|
765
|
+
if (quoteCode !== CHAR_QUOTE && quoteCode !== CHAR_APOS) {
|
|
766
|
+
const start = this.pos;
|
|
767
|
+
while (this.pos < this.length) {
|
|
768
|
+
const code = this.currentCharCode();
|
|
769
|
+
if (this.isWhitespace(code) || code === CHAR_GT || code === CHAR_SLASH) break;
|
|
770
|
+
this.pos++;
|
|
771
|
+
}
|
|
772
|
+
return this.xml.substring(start, this.pos);
|
|
773
|
+
}
|
|
774
|
+
this.pos++;
|
|
775
|
+
const start = this.pos;
|
|
776
|
+
while (this.pos < this.length) {
|
|
777
|
+
if (this.currentCharCode() === quoteCode) {
|
|
778
|
+
const value = this.xml.substring(start, this.pos);
|
|
779
|
+
this.pos++;
|
|
780
|
+
return value;
|
|
781
|
+
}
|
|
782
|
+
this.pos++;
|
|
783
|
+
}
|
|
784
|
+
return this.xml.substring(start, this.pos);
|
|
785
|
+
}
|
|
786
|
+
parseCDATA() {
|
|
787
|
+
if (!this.matches("<![CDATA[")) return null;
|
|
788
|
+
this.pos += 9;
|
|
789
|
+
const endPos = this.findString("]]>");
|
|
790
|
+
if (endPos === -1) {
|
|
791
|
+
const content = this.xml.substring(this.pos);
|
|
792
|
+
this.pos = this.length;
|
|
793
|
+
return content;
|
|
794
|
+
}
|
|
795
|
+
const content = this.xml.substring(this.pos, endPos);
|
|
796
|
+
this.pos = endPos + 3;
|
|
797
|
+
return content;
|
|
798
|
+
}
|
|
799
|
+
skipWhitespace() {
|
|
800
|
+
while (this.pos < this.length) {
|
|
801
|
+
const code = this.currentCharCode();
|
|
802
|
+
if (code !== CHAR_SPACE && code !== CHAR_TAB && code !== CHAR_LF && code !== CHAR_CR) break;
|
|
803
|
+
this.pos++;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
isWhitespace(code) {
|
|
807
|
+
return code === CHAR_SPACE || code === CHAR_TAB || code === CHAR_LF || code === CHAR_CR;
|
|
808
|
+
}
|
|
809
|
+
skipUntil(target) {
|
|
810
|
+
const pos = this.findString(target);
|
|
811
|
+
if (pos !== -1) this.pos = pos;
|
|
812
|
+
else this.pos = this.length;
|
|
813
|
+
}
|
|
814
|
+
current() {
|
|
815
|
+
return this.xml[this.pos];
|
|
816
|
+
}
|
|
817
|
+
currentCharCode() {
|
|
818
|
+
return this.xml.charCodeAt(this.pos);
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* Checks if the string at the given position matches the target string.
|
|
822
|
+
* This avoids creating substring instances for comparison.
|
|
823
|
+
* @param str - The target string to match
|
|
824
|
+
* @param pos - The position to check from (default: current position)
|
|
825
|
+
*/
|
|
826
|
+
matches(str, pos = this.pos) {
|
|
827
|
+
const len = str.length;
|
|
828
|
+
if (pos + len > this.length) return false;
|
|
829
|
+
for (let i = 0; i < len; i++) if (this.xml.charCodeAt(pos + i) !== str.charCodeAt(i)) return false;
|
|
830
|
+
return true;
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* Finds the position of a target string starting from the given position.
|
|
834
|
+
* @param str - The string to find
|
|
835
|
+
* @param startPos - Starting position (default: current position)
|
|
836
|
+
* @returns The position where the string is found, or -1 if not found
|
|
837
|
+
*/
|
|
838
|
+
findString(str, startPos = this.pos) {
|
|
839
|
+
const maxPos = this.length - str.length;
|
|
840
|
+
for (let pos = startPos; pos <= maxPos; pos++) if (this.matches(str, pos)) return pos;
|
|
841
|
+
return -1;
|
|
842
|
+
}
|
|
843
|
+
};
|
|
558
844
|
//#endregion
|
|
559
845
|
//#region src/handler.ts
|
|
560
846
|
let _options = {
|
|
@@ -570,12 +856,12 @@ function initXapi(options) {
|
|
|
570
856
|
_options = { ...options };
|
|
571
857
|
}
|
|
572
858
|
/**
|
|
573
|
-
* Parses an XML string into an XapiRoot object using
|
|
859
|
+
* Parses an XML string into an XapiRoot object using custom parser.
|
|
574
860
|
* @param xml - The string containing the XML data.
|
|
575
|
-
* @returns
|
|
861
|
+
* @returns An XapiRoot object.
|
|
576
862
|
*/
|
|
577
863
|
function parse(xml) {
|
|
578
|
-
const parsedXml =
|
|
864
|
+
const parsedXml = parseXml(xml);
|
|
579
865
|
const xapiRoot = new XapiRoot();
|
|
580
866
|
let rootElement;
|
|
581
867
|
for (let i = 0; i < parsedXml.length; i++) if (parsedXml[i].tagName === "Root") {
|
|
@@ -586,121 +872,130 @@ function parse(xml) {
|
|
|
586
872
|
const rootChildren = rootElement.children;
|
|
587
873
|
if (rootChildren && rootChildren.length > 0) for (let i = 0; i < rootChildren.length; i++) {
|
|
588
874
|
const child = rootChildren[i];
|
|
875
|
+
if (typeof child === "string") continue;
|
|
589
876
|
const tagName = child.tagName;
|
|
590
877
|
if (tagName === "Parameters") parseParameters(child, xapiRoot);
|
|
591
|
-
else if (tagName === "
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
const dataset = new Dataset(datasetId);
|
|
595
|
-
xapiRoot.addDataset(dataset);
|
|
596
|
-
const datasetChildren = child.children;
|
|
597
|
-
let columnInfoElement;
|
|
598
|
-
let rowsElement;
|
|
599
|
-
if (datasetChildren) for (let j = 0; j < datasetChildren.length; j++) {
|
|
600
|
-
const datasetChild = datasetChildren[j];
|
|
601
|
-
const childTagName = datasetChild.tagName;
|
|
602
|
-
if (childTagName === "ColumnInfo") columnInfoElement = datasetChild;
|
|
603
|
-
else if (childTagName === "Rows") rowsElement = datasetChild;
|
|
604
|
-
if (columnInfoElement && rowsElement) break;
|
|
605
|
-
}
|
|
606
|
-
parseColumnInfo(columnInfoElement, dataset);
|
|
607
|
-
parseRows(rowsElement, dataset);
|
|
608
|
-
}
|
|
878
|
+
else if (tagName === "Datasets") {
|
|
879
|
+
for (const datasetElement of child.children ?? []) if (typeof datasetElement !== "string" && datasetElement.tagName === "Dataset") parseDataset(datasetElement, xapiRoot);
|
|
880
|
+
} else if (tagName === "Dataset") parseDataset(child, xapiRoot);
|
|
609
881
|
}
|
|
610
882
|
return xapiRoot;
|
|
611
883
|
}
|
|
884
|
+
function parseDataset(child, xapiRoot) {
|
|
885
|
+
if (!child.attributes || !child.attributes.id) throw new InvalidXmlError("Dataset element must have an 'id' attribute");
|
|
886
|
+
const datasetId = child.attributes.id;
|
|
887
|
+
const dataset = new Dataset(datasetId);
|
|
888
|
+
xapiRoot.addDataset(dataset);
|
|
889
|
+
const datasetChildren = child.children;
|
|
890
|
+
let columnInfoElement;
|
|
891
|
+
let rowsElement;
|
|
892
|
+
if (datasetChildren) for (let j = 0; j < datasetChildren.length; j++) {
|
|
893
|
+
const datasetChild = datasetChildren[j];
|
|
894
|
+
if (typeof datasetChild === "string") continue;
|
|
895
|
+
const childTagName = datasetChild.tagName;
|
|
896
|
+
if (childTagName === "ColumnInfo") columnInfoElement = datasetChild;
|
|
897
|
+
else if (childTagName === "Rows") rowsElement = datasetChild;
|
|
898
|
+
if (columnInfoElement && rowsElement) break;
|
|
899
|
+
}
|
|
900
|
+
parseColumnInfo(columnInfoElement, dataset);
|
|
901
|
+
parseRows(rowsElement, dataset);
|
|
902
|
+
}
|
|
612
903
|
function parseValue(value, type = "STRING") {
|
|
613
904
|
value = _unescapeXml(value);
|
|
614
905
|
return _options.parseToTypes ? convertToColumnType(value, type) : value;
|
|
615
906
|
}
|
|
616
907
|
function parseColumnInfo(columnInfoElement, dataset) {
|
|
617
|
-
if (!columnInfoElement) throw new InvalidXmlError("ColumnInfo element is missing in the dataset");
|
|
908
|
+
if (!columnInfoElement || typeof columnInfoElement === "string") throw new InvalidXmlError("ColumnInfo element is missing in the dataset");
|
|
618
909
|
const children = columnInfoElement.children;
|
|
619
910
|
if (!children) return;
|
|
620
911
|
for (let i = 0; i < children.length; i++) {
|
|
621
912
|
const colInfo = children[i];
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
913
|
+
if (typeof colInfo !== "string") {
|
|
914
|
+
const tagName = colInfo.tagName;
|
|
915
|
+
if (tagName === "ConstColumn") {
|
|
916
|
+
const attrs = colInfo.attributes;
|
|
917
|
+
const sizeStr = attrs?.size;
|
|
918
|
+
dataset.addConstColumn({
|
|
919
|
+
id: attrs?.id,
|
|
920
|
+
size: sizeStr ? parseInt(sizeStr, 10) : 0,
|
|
921
|
+
type: attrs?.type || "STRING",
|
|
922
|
+
value: parseValue(attrs?.value, attrs?.type)
|
|
923
|
+
});
|
|
924
|
+
} else if (tagName === "Column") {
|
|
925
|
+
const attrs = colInfo.attributes;
|
|
926
|
+
const sizeStr = attrs?.size;
|
|
927
|
+
dataset.addColumn({
|
|
928
|
+
id: attrs?.id,
|
|
929
|
+
size: sizeStr ? parseInt(sizeStr, 10) : 0,
|
|
930
|
+
type: attrs?.type || "STRING"
|
|
931
|
+
});
|
|
932
|
+
}
|
|
640
933
|
}
|
|
641
934
|
}
|
|
642
935
|
}
|
|
643
936
|
function parseRows(rowsElement, dataset) {
|
|
937
|
+
if (typeof rowsElement === "string") return;
|
|
644
938
|
const rows = rowsElement?.children;
|
|
645
939
|
if (!rows) return;
|
|
646
940
|
const datasetRows = dataset.rows;
|
|
647
941
|
for (let i = 0; i < rows.length; i++) {
|
|
648
942
|
const r = rows[i];
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
const columnInfo = dataset.getColumnInfo(colId);
|
|
663
|
-
if (!columnInfo) throw new InvalidXmlError(`Column with id ${colId} not found in dataset ${dataset.id}`);
|
|
664
|
-
const castedValue = parseValue(value, columnInfo.type);
|
|
665
|
-
currentRow.cols.push({
|
|
666
|
-
id: colId,
|
|
667
|
-
value: castedValue
|
|
668
|
-
});
|
|
669
|
-
} else if (colTagName === "OrgRow") {
|
|
670
|
-
const orgRow = [];
|
|
671
|
-
currentRow.orgRow = orgRow;
|
|
672
|
-
const orgCols = col.children;
|
|
673
|
-
if (!orgCols) continue;
|
|
674
|
-
for (let k = 0; k < orgCols.length; k++) {
|
|
675
|
-
const orgCol = orgCols[k];
|
|
676
|
-
if (orgCol.tagName === "Col") {
|
|
677
|
-
const colId = orgCol.attributes?.id;
|
|
678
|
-
const value = orgCol.children?.[0];
|
|
943
|
+
if (typeof r !== "string") {
|
|
944
|
+
const tagName = r.tagName;
|
|
945
|
+
if (tagName === "Row") {
|
|
946
|
+
const currentRow = datasetRows[dataset.newRow()];
|
|
947
|
+
currentRow.type = r.attributes?.type || void 0;
|
|
948
|
+
const cols = r.children;
|
|
949
|
+
if (cols) for (let j = 0; j < cols.length; j++) {
|
|
950
|
+
const col = cols[j];
|
|
951
|
+
if (typeof col !== "string") {
|
|
952
|
+
const colTagName = col.tagName;
|
|
953
|
+
if (colTagName === "Col") {
|
|
954
|
+
const colId = col.attributes?.id;
|
|
955
|
+
const value = col.children?.[0];
|
|
679
956
|
const columnInfo = dataset.getColumnInfo(colId);
|
|
957
|
+
if (!columnInfo) throw new InvalidXmlError(`Column with id ${colId} not found in dataset ${dataset.id}`);
|
|
680
958
|
const castedValue = parseValue(value, columnInfo.type);
|
|
681
|
-
|
|
959
|
+
currentRow.cols.push({
|
|
682
960
|
id: colId,
|
|
683
961
|
value: castedValue
|
|
684
962
|
});
|
|
963
|
+
} else if (colTagName === "OrgRow") {
|
|
964
|
+
const orgRow = [];
|
|
965
|
+
currentRow.orgRow = orgRow;
|
|
966
|
+
const orgCols = col.children;
|
|
967
|
+
if (orgCols) for (let k = 0; k < orgCols.length; k++) {
|
|
968
|
+
const orgCol = orgCols[k];
|
|
969
|
+
if (typeof orgCol !== "string" && orgCol.tagName === "Col") {
|
|
970
|
+
const colId = orgCol.attributes?.id;
|
|
971
|
+
const value = orgCol.children?.[0];
|
|
972
|
+
const castedValue = parseValue(value, dataset.getColumnInfo(colId).type);
|
|
973
|
+
orgRow.push({
|
|
974
|
+
id: colId,
|
|
975
|
+
value: castedValue
|
|
976
|
+
});
|
|
977
|
+
}
|
|
978
|
+
}
|
|
685
979
|
}
|
|
686
980
|
}
|
|
687
981
|
}
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
|
|
982
|
+
} else if (tagName === "Col") throw new InvalidXmlError("Row must be defined before Col");
|
|
983
|
+
else if (tagName === "OrgRow") throw new InvalidXmlError("Row must be defined before OrgRow");
|
|
984
|
+
}
|
|
691
985
|
}
|
|
692
986
|
}
|
|
693
987
|
function parseParameters(parametersElement, xapiRoot) {
|
|
988
|
+
if (typeof parametersElement === "string") return;
|
|
694
989
|
if (!parametersElement) return;
|
|
695
990
|
const children = parametersElement.children;
|
|
696
991
|
if (!children) return;
|
|
697
992
|
for (let i = 0; i < children.length; i++) {
|
|
698
993
|
const p = children[i];
|
|
699
|
-
if (p.tagName === "Parameter") {
|
|
994
|
+
if (typeof p !== "string" && p.tagName === "Parameter") {
|
|
700
995
|
const attrs = p.attributes;
|
|
701
996
|
const id = attrs?.id;
|
|
702
997
|
const type = attrs?.type || "STRING";
|
|
703
|
-
const value = p.children?.[0];
|
|
998
|
+
const value = p.children?.[0] ?? attrs?.value;
|
|
704
999
|
xapiRoot.addParameter({
|
|
705
1000
|
id,
|
|
706
1001
|
type,
|
|
@@ -710,91 +1005,179 @@ function parseParameters(parametersElement, xapiRoot) {
|
|
|
710
1005
|
}
|
|
711
1006
|
}
|
|
712
1007
|
function write(root) {
|
|
713
|
-
const
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
indentString: " ",
|
|
717
|
-
prettyPrint: true
|
|
718
|
-
});
|
|
719
|
-
writer.writeStartDocument("1.0", "UTF-8");
|
|
720
|
-
writer.writeStartElement("Root", { attributes: {
|
|
1008
|
+
const builder = new XmlStringBuilder();
|
|
1009
|
+
builder.writeDeclaration("1.0", "UTF-8");
|
|
1010
|
+
builder.writeStartElement("Root", {
|
|
721
1011
|
xmlns: _options.xapiVersion?.xmlns || NexaVersion.xmlns,
|
|
722
1012
|
version: _options.xapiVersion?.version || NexaVersion.version
|
|
723
|
-
}
|
|
724
|
-
if (root.parameterSize() > 0) writeParameters(
|
|
1013
|
+
});
|
|
1014
|
+
if (root.parameterSize() > 0) writeParameters(builder, root.getParameters());
|
|
725
1015
|
if (root.datasetSize() > 0) {
|
|
726
|
-
|
|
727
|
-
for (const dataset of root.
|
|
728
|
-
|
|
1016
|
+
builder.writeStartElement("Datasets");
|
|
1017
|
+
for (const dataset of root.getDatasets()) writeDataset(builder, dataset);
|
|
1018
|
+
builder.writeEndElement("Datasets");
|
|
729
1019
|
}
|
|
730
|
-
|
|
731
|
-
return
|
|
1020
|
+
builder.writeEndElement("Root");
|
|
1021
|
+
return builder.toString();
|
|
732
1022
|
}
|
|
733
|
-
function writeParameters(
|
|
734
|
-
if (
|
|
735
|
-
|
|
736
|
-
for (const parameter of
|
|
737
|
-
|
|
738
|
-
if (parameter.type !== void 0)
|
|
739
|
-
if (parameter.value !== void 0) if (typeof parameter.value === "string")
|
|
740
|
-
else if (parameter.value instanceof Date)
|
|
741
|
-
else if (parameter.value instanceof Uint8Array)
|
|
742
|
-
else
|
|
743
|
-
|
|
1023
|
+
function writeParameters(builder, parameters) {
|
|
1024
|
+
if (parameters) {
|
|
1025
|
+
builder.writeStartElement("Parameters");
|
|
1026
|
+
for (const parameter of parameters) {
|
|
1027
|
+
const attrs = { id: parameter.id };
|
|
1028
|
+
if (parameter.type !== void 0) attrs.type = parameter.type;
|
|
1029
|
+
if (parameter.value !== void 0) if (typeof parameter.value === "string") attrs.value = parameter.value;
|
|
1030
|
+
else if (parameter.value instanceof Date) attrs.value = dateToString(parameter.value, parameter.type);
|
|
1031
|
+
else if (parameter.value instanceof Uint8Array) attrs.value = uint8ArrayToBase64(parameter.value);
|
|
1032
|
+
else attrs.value = String(parameter.value);
|
|
1033
|
+
builder.writeStartElement("Parameter", attrs, true);
|
|
744
1034
|
}
|
|
745
|
-
|
|
1035
|
+
builder.writeEndElement("Parameters");
|
|
746
1036
|
}
|
|
747
1037
|
}
|
|
748
|
-
function writeDataset(
|
|
749
|
-
|
|
1038
|
+
function writeDataset(builder, dataset) {
|
|
1039
|
+
builder.writeStartElement("Dataset", { id: dataset.id });
|
|
750
1040
|
if (dataset.constColumnSize() > 0 || dataset.columnSize() > 0) {
|
|
751
|
-
|
|
752
|
-
for (const constCol of dataset.
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
size: String(col.size),
|
|
765
|
-
type: col.type
|
|
766
|
-
},
|
|
767
|
-
selfClosing: true
|
|
768
|
-
});
|
|
769
|
-
writer.writeEndElement();
|
|
1041
|
+
builder.writeStartElement("ColumnInfo");
|
|
1042
|
+
for (const constCol of dataset.getConstColumns()) builder.writeStartElement("ConstColumn", {
|
|
1043
|
+
id: constCol.id,
|
|
1044
|
+
size: String(constCol.size),
|
|
1045
|
+
type: constCol.type,
|
|
1046
|
+
value: constCol.value !== void 0 ? String(constCol.value) : ""
|
|
1047
|
+
}, true);
|
|
1048
|
+
for (const col of dataset.getColumns()) builder.writeStartElement("Column", {
|
|
1049
|
+
id: col.id,
|
|
1050
|
+
size: String(col.size),
|
|
1051
|
+
type: col.type
|
|
1052
|
+
}, true);
|
|
1053
|
+
builder.writeEndElement("ColumnInfo");
|
|
770
1054
|
}
|
|
771
|
-
|
|
772
|
-
for (const row of dataset.
|
|
773
|
-
if (row.type)
|
|
774
|
-
else
|
|
775
|
-
for (const col of row.cols) writeColumn(
|
|
1055
|
+
builder.writeStartElement("Rows");
|
|
1056
|
+
for (const row of dataset.getRows()) {
|
|
1057
|
+
if (row.type) builder.writeStartElement("Row", { type: row.type });
|
|
1058
|
+
else builder.writeStartElement("Row");
|
|
1059
|
+
for (const col of row.cols) writeColumn(builder, dataset, col);
|
|
776
1060
|
if (row.orgRow && row.orgRow.length > 0) {
|
|
777
|
-
|
|
778
|
-
for (const orgCol of row.orgRow) writeColumn(
|
|
779
|
-
|
|
1061
|
+
builder.writeStartElement("OrgRow");
|
|
1062
|
+
for (const orgCol of row.orgRow) writeColumn(builder, dataset, orgCol);
|
|
1063
|
+
builder.writeEndElement("OrgRow");
|
|
780
1064
|
}
|
|
781
|
-
|
|
1065
|
+
builder.writeEndElement("Row");
|
|
782
1066
|
}
|
|
783
|
-
|
|
784
|
-
|
|
1067
|
+
builder.writeEndElement("Rows");
|
|
1068
|
+
builder.writeEndElement("Dataset");
|
|
785
1069
|
}
|
|
786
|
-
function writeColumn(
|
|
1070
|
+
function writeColumn(builder, dataset, col) {
|
|
787
1071
|
if (col.value !== void 0 && col.value !== null) {
|
|
788
1072
|
const colInfo = dataset.getColumnInfo(col.id);
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
1073
|
+
builder.writeElementWithText("Col", { id: col.id }, convertToString(col.value, colInfo.type));
|
|
1074
|
+
} else builder.writeStartElement("Col", { id: col.id }, true);
|
|
1075
|
+
}
|
|
1076
|
+
//#endregion
|
|
1077
|
+
//#region src/schema.ts
|
|
1078
|
+
const defaultSizes = {
|
|
1079
|
+
STRING: 256,
|
|
1080
|
+
INT: 10,
|
|
1081
|
+
FLOAT: 20,
|
|
1082
|
+
DECIMAL: 20,
|
|
1083
|
+
BIGDECIMAL: 30,
|
|
1084
|
+
DATE: 8,
|
|
1085
|
+
DATETIME: 17,
|
|
1086
|
+
TIME: 6,
|
|
1087
|
+
BLOB: 1e3
|
|
1088
|
+
};
|
|
1089
|
+
function column(type, options = {}) {
|
|
1090
|
+
return {
|
|
1091
|
+
kind: "xapi-column",
|
|
1092
|
+
type,
|
|
1093
|
+
size: options.size ?? defaultSizes[type],
|
|
1094
|
+
optional: options.optional ?? false
|
|
1095
|
+
};
|
|
1096
|
+
}
|
|
1097
|
+
function defineDataset(columns) {
|
|
1098
|
+
return {
|
|
1099
|
+
kind: "xapi-dataset",
|
|
1100
|
+
columns
|
|
1101
|
+
};
|
|
1102
|
+
}
|
|
1103
|
+
function defineRoot(definition) {
|
|
1104
|
+
return {
|
|
1105
|
+
kind: "xapi-root",
|
|
1106
|
+
datasets: definition.datasets,
|
|
1107
|
+
parameters: definition.parameters ?? {}
|
|
1108
|
+
};
|
|
1109
|
+
}
|
|
1110
|
+
function defineOperation(definition) {
|
|
1111
|
+
return {
|
|
1112
|
+
kind: "xapi-operation",
|
|
1113
|
+
...definition
|
|
1114
|
+
};
|
|
1115
|
+
}
|
|
1116
|
+
const xapi = {
|
|
1117
|
+
string: (options) => column("STRING", options),
|
|
1118
|
+
int: (options) => column("INT", options),
|
|
1119
|
+
float: (options) => column("FLOAT", options),
|
|
1120
|
+
decimal: (options) => column("DECIMAL", options),
|
|
1121
|
+
bigdecimal: (options) => column("BIGDECIMAL", options),
|
|
1122
|
+
date: (options) => column("DATE", options),
|
|
1123
|
+
datetime: (options) => column("DATETIME", options),
|
|
1124
|
+
time: (options) => column("TIME", options),
|
|
1125
|
+
blob: (options) => column("BLOB", options),
|
|
1126
|
+
dataset: defineDataset,
|
|
1127
|
+
root: defineRoot,
|
|
1128
|
+
operation: defineOperation
|
|
1129
|
+
};
|
|
1130
|
+
function encodeRoot(schema, value) {
|
|
1131
|
+
const root = new XapiRoot();
|
|
1132
|
+
for (const [id, parameterSchema] of Object.entries(schema.parameters)) {
|
|
1133
|
+
const parameterValue = value.parameters[id];
|
|
1134
|
+
if (parameterValue !== void 0 || !parameterSchema.optional) root.addParameter({
|
|
1135
|
+
id,
|
|
1136
|
+
type: parameterSchema.type,
|
|
1137
|
+
value: parameterValue
|
|
1138
|
+
});
|
|
1139
|
+
}
|
|
1140
|
+
for (const [datasetId, datasetSchema] of Object.entries(schema.datasets)) {
|
|
1141
|
+
const dataset = new Dataset(datasetId);
|
|
1142
|
+
for (const [id, columnSchema] of Object.entries(datasetSchema.columns)) dataset.addColumn({
|
|
1143
|
+
id,
|
|
1144
|
+
type: columnSchema.type,
|
|
1145
|
+
size: columnSchema.size
|
|
1146
|
+
});
|
|
1147
|
+
const rows = value.datasets[datasetId];
|
|
1148
|
+
for (const row of rows) {
|
|
1149
|
+
const rowIndex = dataset.newRow();
|
|
1150
|
+
for (const id of Object.keys(datasetSchema.columns)) dataset.setColumn(rowIndex, id, row[id]);
|
|
1151
|
+
}
|
|
1152
|
+
root.addDataset(dataset);
|
|
1153
|
+
}
|
|
1154
|
+
return root;
|
|
1155
|
+
}
|
|
1156
|
+
function decodeRoot(schema, root) {
|
|
1157
|
+
const parameters = {};
|
|
1158
|
+
for (const id of Object.keys(schema.parameters)) {
|
|
1159
|
+
const value = root.getParameter(id)?.value;
|
|
1160
|
+
if (value !== void 0) parameters[id] = value;
|
|
1161
|
+
}
|
|
1162
|
+
const datasets = {};
|
|
1163
|
+
for (const [datasetId, datasetSchema] of Object.entries(schema.datasets)) {
|
|
1164
|
+
const dataset = root.getDataset(datasetId);
|
|
1165
|
+
if (!dataset) {
|
|
1166
|
+
datasets[datasetId] = [];
|
|
1167
|
+
continue;
|
|
1168
|
+
}
|
|
1169
|
+
const constants = Object.fromEntries(dataset.getConstColumns().map(({ id, value }) => [id, value]));
|
|
1170
|
+
datasets[datasetId] = dataset.getRows().map((row) => {
|
|
1171
|
+
const value = { ...constants };
|
|
1172
|
+
for (const column of row.cols) if (column.id in datasetSchema.columns) value[column.id] = column.value;
|
|
1173
|
+
return value;
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
return {
|
|
1177
|
+
parameters,
|
|
1178
|
+
datasets
|
|
1179
|
+
};
|
|
796
1180
|
}
|
|
797
|
-
|
|
798
1181
|
//#endregion
|
|
799
1182
|
exports.ColumnTypeError = ColumnTypeError;
|
|
800
1183
|
exports.Dataset = Dataset;
|
|
@@ -802,6 +1185,7 @@ exports.InvalidXmlError = InvalidXmlError;
|
|
|
802
1185
|
exports.NexaVersion = NexaVersion;
|
|
803
1186
|
exports.StringWritableStream = StringWritableStream;
|
|
804
1187
|
exports.XapiRoot = XapiRoot;
|
|
1188
|
+
exports.XmlStringBuilder = XmlStringBuilder;
|
|
805
1189
|
exports.XplatformVersion = XplatformVersion;
|
|
806
1190
|
exports._unescapeXml = _unescapeXml;
|
|
807
1191
|
exports.arrayBufferToString = arrayBufferToString;
|
|
@@ -810,13 +1194,21 @@ exports.columnType = columnType;
|
|
|
810
1194
|
exports.convertToColumnType = convertToColumnType;
|
|
811
1195
|
exports.convertToString = convertToString;
|
|
812
1196
|
exports.dateToString = dateToString;
|
|
1197
|
+
exports.decodeRoot = decodeRoot;
|
|
1198
|
+
exports.defineDataset = defineDataset;
|
|
1199
|
+
exports.defineOperation = defineOperation;
|
|
1200
|
+
exports.defineRoot = defineRoot;
|
|
1201
|
+
exports.encodeControlChars = encodeControlChars;
|
|
1202
|
+
exports.encodeRoot = encodeRoot;
|
|
1203
|
+
exports.escapeXml = escapeXml;
|
|
813
1204
|
exports.initXapi = initXapi;
|
|
814
1205
|
exports.isXapiRoot = isXapiRoot;
|
|
815
1206
|
exports.makeParseEntities = makeParseEntities;
|
|
816
|
-
exports.makeWriterEntities = makeWriterEntities;
|
|
817
1207
|
exports.parse = parse;
|
|
1208
|
+
exports.parseXml = parseXml;
|
|
818
1209
|
exports.rowType = rowType;
|
|
819
1210
|
exports.stringToDate = stringToDate;
|
|
820
1211
|
exports.stringToReadableStream = stringToReadableStream;
|
|
821
1212
|
exports.uint8ArrayToBase64 = uint8ArrayToBase64;
|
|
822
|
-
exports.write = write;
|
|
1213
|
+
exports.write = write;
|
|
1214
|
+
exports.xapi = xapi;
|