@xapi-js/core 1.0.0 → 1.1.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/README.md +217 -29
- package/dist/api-ISSD7HZ6.js +134436 -0
- package/dist/chunk-GI5RMYH6.js +37 -0
- package/dist/index.cjs +145 -127
- package/dist/index.d.cts +10 -4
- package/dist/index.d.ts +10 -4
- package/dist/index.js +133 -128
- package/dist/performance.test.js +2485 -0
- package/package.json +8 -3
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/handler.ts
|
|
2
|
-
import {
|
|
2
|
+
import { StaxXmlWriter } from "stax-xml";
|
|
3
|
+
import * as txml from "txml";
|
|
3
4
|
|
|
4
5
|
// src/types.ts
|
|
5
6
|
var rowType = ["insert", "update", "delete"];
|
|
@@ -18,21 +19,31 @@ var ColumnTypeError = class extends Error {
|
|
|
18
19
|
this.name = "ColumnTypeError";
|
|
19
20
|
}
|
|
20
21
|
};
|
|
22
|
+
var InvalidXmlError = class extends Error {
|
|
23
|
+
constructor(message) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = "InvalidXmlError";
|
|
26
|
+
}
|
|
27
|
+
};
|
|
21
28
|
|
|
22
29
|
// src/utils.ts
|
|
30
|
+
function arrayBufferToString(buffer) {
|
|
31
|
+
const decoder = new TextDecoder();
|
|
32
|
+
return decoder.decode(buffer);
|
|
33
|
+
}
|
|
23
34
|
function makeParseEntities() {
|
|
24
|
-
const
|
|
35
|
+
const entities2 = [];
|
|
25
36
|
for (let i = 1; i <= 32; i++) {
|
|
26
|
-
|
|
37
|
+
entities2.push({ entity: `&#${i};`, value: String.fromCharCode(i) });
|
|
27
38
|
}
|
|
28
|
-
return
|
|
39
|
+
return entities2;
|
|
29
40
|
}
|
|
30
41
|
function makeWriterEntities() {
|
|
31
|
-
const
|
|
42
|
+
const entities2 = [];
|
|
32
43
|
for (let i = 1; i <= 32; i++) {
|
|
33
|
-
|
|
44
|
+
entities2.push({ entity: `&#${i};`, value: String.fromCharCode(i) });
|
|
34
45
|
}
|
|
35
|
-
return
|
|
46
|
+
return entities2;
|
|
36
47
|
}
|
|
37
48
|
function base64ToUint8Array(base64String) {
|
|
38
49
|
const binaryString = atob(base64String);
|
|
@@ -110,6 +121,7 @@ function dateToString(date, type) {
|
|
|
110
121
|
}
|
|
111
122
|
}
|
|
112
123
|
var StringWritableStream = class extends WritableStream {
|
|
124
|
+
result = "";
|
|
113
125
|
constructor() {
|
|
114
126
|
const decoder = new TextDecoder();
|
|
115
127
|
super({
|
|
@@ -120,7 +132,6 @@ var StringWritableStream = class extends WritableStream {
|
|
|
120
132
|
this.result += decoder.decode();
|
|
121
133
|
}
|
|
122
134
|
});
|
|
123
|
-
this.result = "";
|
|
124
135
|
}
|
|
125
136
|
/**
|
|
126
137
|
* Returns the collected string result.
|
|
@@ -181,23 +192,34 @@ function convertToString(value, type) {
|
|
|
181
192
|
return dateToString(value, type);
|
|
182
193
|
case "BLOB":
|
|
183
194
|
return uint8ArrayToBase64(value);
|
|
195
|
+
case "STRING":
|
|
196
|
+
return String(value);
|
|
184
197
|
default:
|
|
185
198
|
return String(value);
|
|
186
199
|
}
|
|
187
200
|
}
|
|
201
|
+
var entities = makeParseEntities();
|
|
202
|
+
function _unescapeXml(str) {
|
|
203
|
+
if (!str) return str;
|
|
204
|
+
const regex = new RegExp(entities.map((e) => e.entity).join("|"), "g");
|
|
205
|
+
return str.replace(regex, (match) => {
|
|
206
|
+
const entity = entities.find((e) => e.entity === match);
|
|
207
|
+
return entity ? entity.value : match;
|
|
208
|
+
});
|
|
209
|
+
}
|
|
188
210
|
|
|
189
211
|
// src/xapi-data.ts
|
|
190
212
|
var XapiRoot = class {
|
|
213
|
+
/** An array of datasets within the X-API root. */
|
|
214
|
+
datasets = [];
|
|
215
|
+
/** Parameters associated with the X-API root. */
|
|
216
|
+
parameters = { params: [] };
|
|
191
217
|
/**
|
|
192
218
|
* Creates an instance of XapiRoot.
|
|
193
219
|
* @param datasets - Initial array of datasets.
|
|
194
220
|
* @param parameters - Initial parameters.
|
|
195
221
|
*/
|
|
196
222
|
constructor(datasets = [], parameters = { params: [] }) {
|
|
197
|
-
/** An array of datasets within the X-API root. */
|
|
198
|
-
this.datasets = [];
|
|
199
|
-
/** Parameters associated with the X-API root. */
|
|
200
|
-
this.parameters = { params: [] };
|
|
201
223
|
this.datasets = datasets;
|
|
202
224
|
this.parameters = parameters;
|
|
203
225
|
}
|
|
@@ -285,6 +307,13 @@ var XapiRoot = class {
|
|
|
285
307
|
}
|
|
286
308
|
};
|
|
287
309
|
var Dataset = class {
|
|
310
|
+
/** The ID of the dataset. */
|
|
311
|
+
id;
|
|
312
|
+
constColumns = [];
|
|
313
|
+
columns = [];
|
|
314
|
+
/** An array of rows in the dataset. */
|
|
315
|
+
rows = [];
|
|
316
|
+
_columnIndexMap = /* @__PURE__ */ new Map();
|
|
288
317
|
/**
|
|
289
318
|
* Creates an instance of Dataset.
|
|
290
319
|
* @param id - The ID of the dataset.
|
|
@@ -293,11 +322,6 @@ var Dataset = class {
|
|
|
293
322
|
* @param rows - Initial array of rows.
|
|
294
323
|
*/
|
|
295
324
|
constructor(id, constColumns = [], columns = [], rows = []) {
|
|
296
|
-
this.constColumns = [];
|
|
297
|
-
this.columns = [];
|
|
298
|
-
/** An array of rows in the dataset. */
|
|
299
|
-
this.rows = [];
|
|
300
|
-
this._columnIndexMap = /* @__PURE__ */ new Map();
|
|
301
325
|
this.id = id;
|
|
302
326
|
this.constColumns = constColumns;
|
|
303
327
|
this.columns = columns;
|
|
@@ -478,127 +502,105 @@ function initXapi(options) {
|
|
|
478
502
|
...options
|
|
479
503
|
};
|
|
480
504
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
if (typeof reader === "string") {
|
|
484
|
-
_stream = new ReadableStream({
|
|
485
|
-
start(controller) {
|
|
486
|
-
controller.enqueue(new TextEncoder().encode(reader));
|
|
487
|
-
controller.close();
|
|
488
|
-
}
|
|
489
|
-
});
|
|
490
|
-
} else {
|
|
491
|
-
_stream = reader;
|
|
492
|
-
}
|
|
493
|
-
const xmlParser = new StaxXmlParser(_stream, {
|
|
494
|
-
addEntities: makeParseEntities(),
|
|
495
|
-
encoding: "UTF-8"
|
|
496
|
-
});
|
|
505
|
+
function parse2(xml) {
|
|
506
|
+
const parsedXml = txml.parse(xml);
|
|
497
507
|
const xapiRoot = new XapiRoot();
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
type: startEvent.attributes["type"] || "STRING",
|
|
511
|
-
value: _options.parseToTypes ? convertToColumnType(paramValue, startEvent.attributes["type"] || "STRING") : paramValue
|
|
512
|
-
});
|
|
513
|
-
break;
|
|
514
|
-
case "Dataset":
|
|
515
|
-
xapiRoot.addDataset(await parseDataset(startEvent, xmlParser));
|
|
516
|
-
break;
|
|
508
|
+
const rootElement = parsedXml.find((node) => {
|
|
509
|
+
const rootNode = node;
|
|
510
|
+
return rootNode.tagName === "Root";
|
|
511
|
+
});
|
|
512
|
+
if (rootElement === void 0) return xapiRoot;
|
|
513
|
+
const parametersElement = rootElement.children?.find((node) => node.tagName === "Parameters");
|
|
514
|
+
parseParameters(parametersElement, xapiRoot);
|
|
515
|
+
const datasetsElements = rootElement.children?.filter((node) => node.tagName === "Dataset");
|
|
516
|
+
if (datasetsElements && datasetsElements?.length && datasetsElements.length > 0) {
|
|
517
|
+
for (const datasetsElement of datasetsElements) {
|
|
518
|
+
if (!datasetsElement.attributes || !datasetsElement.attributes.id) {
|
|
519
|
+
throw new InvalidXmlError("Dataset element must have an 'id' attribute");
|
|
517
520
|
}
|
|
521
|
+
const datasetId = datasetsElement.attributes?.id;
|
|
522
|
+
const dataset = new Dataset(datasetId);
|
|
523
|
+
xapiRoot.addDataset(dataset);
|
|
524
|
+
const columnInfoElement = datasetsElement.children?.find((node) => node.tagName === "ColumnInfo");
|
|
525
|
+
parseColumnInfo(columnInfoElement, dataset);
|
|
526
|
+
const rowsElement = datasetsElement.children?.find((node) => node.tagName === "Rows");
|
|
527
|
+
parseRows(rowsElement, dataset);
|
|
518
528
|
}
|
|
519
529
|
}
|
|
520
530
|
return xapiRoot;
|
|
521
531
|
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
532
|
+
function parseValue(value, type = "STRING") {
|
|
533
|
+
value = _unescapeXml(value);
|
|
534
|
+
return _options.parseToTypes ? convertToColumnType(value, type) : value;
|
|
535
|
+
}
|
|
536
|
+
function parseColumnInfo(columnInfoElement, dataset) {
|
|
537
|
+
if (!columnInfoElement) throw new InvalidXmlError("ColumnInfo element is missing in the dataset");
|
|
538
|
+
columnInfoElement.children?.forEach((colInfo) => {
|
|
539
|
+
if (colInfo.tagName === "ConstColumn") {
|
|
540
|
+
dataset.addConstColumn({
|
|
541
|
+
id: colInfo.attributes?.id,
|
|
542
|
+
size: parseInt(colInfo.attributes?.size || "0", 10),
|
|
543
|
+
type: colInfo.attributes?.type || "STRING",
|
|
544
|
+
value: parseValue(colInfo.attributes?.value, colInfo.attributes?.type)
|
|
545
|
+
});
|
|
546
|
+
} else if (colInfo.tagName === "Column") {
|
|
547
|
+
dataset.addColumn({
|
|
548
|
+
id: colInfo.attributes?.id,
|
|
549
|
+
size: parseInt(colInfo.attributes?.size || "0", 10),
|
|
550
|
+
type: colInfo.attributes?.type || "STRING"
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
function parseRows(rowsElement, dataset) {
|
|
556
|
+
rowsElement?.children?.forEach((r) => {
|
|
557
|
+
if (r.tagName === "Row") {
|
|
558
|
+
const rowIndex = dataset.newRow();
|
|
559
|
+
dataset.rows[rowIndex].type = r.attributes?.type || void 0;
|
|
560
|
+
r.children?.forEach((col) => {
|
|
561
|
+
if (col.tagName === "Col") {
|
|
562
|
+
const colId = col.attributes?.id;
|
|
563
|
+
const value = col.children?.[0];
|
|
564
|
+
const columnInfo = dataset.getColumnInfo(colId);
|
|
565
|
+
if (!columnInfo) throw new InvalidXmlError(`Column with id ${colId} not found in dataset ${dataset.id}`);
|
|
566
|
+
const castedValue = parseValue(value, columnInfo.type);
|
|
567
|
+
dataset.rows[rowIndex].cols.push({ id: colId, value: castedValue });
|
|
568
|
+
} else if (col.tagName === "OrgRow") {
|
|
569
|
+
dataset.rows[rowIndex].orgRow = [];
|
|
570
|
+
col.children?.forEach((orgCol) => {
|
|
571
|
+
if (orgCol.tagName === "Col") {
|
|
572
|
+
const colId = orgCol.attributes?.id;
|
|
573
|
+
const value = orgCol.children?.[0];
|
|
574
|
+
const columnInfo = dataset.getColumnInfo(colId);
|
|
575
|
+
const castedValue = parseValue(value, columnInfo.type);
|
|
576
|
+
if (dataset && dataset.rows && dataset.rows[rowIndex] && dataset.rows[rowIndex].orgRow) {
|
|
577
|
+
dataset.rows[rowIndex].orgRow.push({ id: colId, value: castedValue });
|
|
578
|
+
}
|
|
579
|
+
}
|
|
544
580
|
});
|
|
545
|
-
break;
|
|
546
|
-
case "Row":
|
|
547
|
-
currentRowIndex = dataset.newRow();
|
|
548
|
-
dataset.rows[currentRowIndex].type = startEvent.attributes["type"] || void 0;
|
|
549
|
-
break;
|
|
550
|
-
case "Col": {
|
|
551
|
-
await parseCol(xmlParser, startEvent, dataset, currentRowIndex, false);
|
|
552
|
-
break;
|
|
553
581
|
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
for await (const orgRowEvent of xmlParser) {
|
|
560
|
-
if (orgRowEvent.type === XmlEventType.END_ELEMENT && orgRowEvent.localName === "OrgRow") {
|
|
561
|
-
break;
|
|
562
|
-
}
|
|
563
|
-
if (orgRowEvent.type === XmlEventType.START_ELEMENT && orgRowEvent.localName === "Col") {
|
|
564
|
-
const orgColEvent = orgRowEvent;
|
|
565
|
-
await parseCol(xmlParser, orgColEvent, dataset, currentRowIndex, true);
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
}
|
|
582
|
+
});
|
|
583
|
+
} else if (r.tagName === "Col") {
|
|
584
|
+
throw new InvalidXmlError("Row must be defined before Col");
|
|
585
|
+
} else if (r.tagName === "OrgRow") {
|
|
586
|
+
throw new InvalidXmlError("Row must be defined before OrgRow");
|
|
569
587
|
}
|
|
570
|
-
}
|
|
571
|
-
return dataset;
|
|
588
|
+
});
|
|
572
589
|
}
|
|
573
|
-
|
|
574
|
-
if (
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
value = colCharEvent.value;
|
|
586
|
-
} else if (colCharEvent.type === XmlEventType.CHARACTERS) {
|
|
587
|
-
value = colCharEvent.value;
|
|
588
|
-
}
|
|
589
|
-
let castedValue = value;
|
|
590
|
-
if (_options.parseToTypes) {
|
|
591
|
-
const columnInfo = dataset.getColumnInfo(colId);
|
|
592
|
-
if (!columnInfo || columnType.includes(columnInfo.type) === false) {
|
|
593
|
-
throw new Error(`Column type for ${colId} not found in dataset ${dataset.id}`);
|
|
590
|
+
function parseParameters(parametersElement, xapiRoot) {
|
|
591
|
+
if (!parametersElement) return;
|
|
592
|
+
parametersElement.children?.forEach((p) => {
|
|
593
|
+
if (p.tagName === "Parameter") {
|
|
594
|
+
const id = p.attributes?.id;
|
|
595
|
+
const type = p.attributes?.type || "STRING";
|
|
596
|
+
const value = p.children?.[0];
|
|
597
|
+
xapiRoot.addParameter({
|
|
598
|
+
id,
|
|
599
|
+
type,
|
|
600
|
+
value: parseValue(value, type)
|
|
601
|
+
});
|
|
594
602
|
}
|
|
595
|
-
|
|
596
|
-
}
|
|
597
|
-
if (!isOrgRow) {
|
|
598
|
-
dataset.rows[currentRowIndex].cols.push({ id: colId, value: castedValue });
|
|
599
|
-
} else {
|
|
600
|
-
dataset.rows[currentRowIndex].orgRow.push({ id: colId, value: castedValue });
|
|
601
|
-
}
|
|
603
|
+
});
|
|
602
604
|
}
|
|
603
605
|
async function writeString(root) {
|
|
604
606
|
const stringStream = new StringWritableStream();
|
|
@@ -718,10 +720,13 @@ async function writeColumn(writer, dataset, col) {
|
|
|
718
720
|
export {
|
|
719
721
|
ColumnTypeError,
|
|
720
722
|
Dataset,
|
|
723
|
+
InvalidXmlError,
|
|
721
724
|
NexaVersion,
|
|
722
725
|
StringWritableStream,
|
|
723
726
|
XapiRoot,
|
|
724
727
|
XplatformVersion,
|
|
728
|
+
_unescapeXml,
|
|
729
|
+
arrayBufferToString,
|
|
725
730
|
base64ToUint8Array,
|
|
726
731
|
columnType,
|
|
727
732
|
convertToColumnType,
|
|
@@ -730,7 +735,7 @@ export {
|
|
|
730
735
|
initXapi,
|
|
731
736
|
makeParseEntities,
|
|
732
737
|
makeWriterEntities,
|
|
733
|
-
parse,
|
|
738
|
+
parse2 as parse,
|
|
734
739
|
rowType,
|
|
735
740
|
stringToDate,
|
|
736
741
|
stringToReadableStream,
|