@xapi-js/core 1.0.0 → 1.1.1
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 +191 -2
- 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/package.json +5 -3
package/README.md
CHANGED
|
@@ -5,12 +5,107 @@ This package provides core utilities and types for working with X-API data.
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
+
# npm
|
|
9
|
+
npm install @xapi-ts/core
|
|
10
|
+
|
|
11
|
+
# yarn
|
|
12
|
+
yarn add @xapi-ts/core
|
|
13
|
+
|
|
14
|
+
# pnpm
|
|
8
15
|
pnpm add @xapi-ts/core
|
|
16
|
+
|
|
17
|
+
# bun
|
|
18
|
+
bun add @xapi-ts/core
|
|
19
|
+
|
|
20
|
+
# deno
|
|
21
|
+
deno add @xapi-ts/core
|
|
9
22
|
```
|
|
10
23
|
|
|
11
24
|
## Usage
|
|
12
25
|
|
|
13
|
-
|
|
26
|
+
`@xapi-ts/core` provides the fundamental classes and functions for working with X-API data.
|
|
27
|
+
|
|
28
|
+
### Parsing X-API XML
|
|
29
|
+
|
|
30
|
+
You can parse an X-API XML string into an `XapiRoot` object:
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { parse, XapiRoot } from '@xapi-ts/core';
|
|
34
|
+
|
|
35
|
+
const xmlString = `<?xml version="1.0" encoding="UTF-8"?>
|
|
36
|
+
<Root xmlns="http://www.tobesoft.com/platform/Dataset" ver="4000">
|
|
37
|
+
<Parameters>
|
|
38
|
+
<Parameter id="service">stock</Parameter>
|
|
39
|
+
<Parameter id="method">search</Parameter>
|
|
40
|
+
</Parameters>
|
|
41
|
+
</Root>`;
|
|
42
|
+
|
|
43
|
+
async function parseXapi() {
|
|
44
|
+
const xapi = await parse(xmlString);
|
|
45
|
+
console.log('Service:', xapi.getParameter('service')?.value);
|
|
46
|
+
console.log('Method:', xapi.getParameter('method')?.value);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
parseXapi();
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Creating and Manipulating XapiRoot
|
|
53
|
+
|
|
54
|
+
You can create an `XapiRoot` object and add parameters and datasets programmatically:
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { XapiRoot, Dataset } from '@xapi-ts/core';
|
|
58
|
+
|
|
59
|
+
const xapi = new XapiRoot();
|
|
60
|
+
|
|
61
|
+
// Add parameters
|
|
62
|
+
xapi.addParameter({ id: 'resultCode', value: '0' });
|
|
63
|
+
xapi.addParameter({ id: 'resultMsg', value: 'SUCCESS' });
|
|
64
|
+
|
|
65
|
+
// Create and add a dataset
|
|
66
|
+
const usersDataset = new Dataset('users');
|
|
67
|
+
usersDataset.addColumn({ id: 'id', type: 'INT' });
|
|
68
|
+
usersDataset.addColumn({ id: 'name', type: 'STRING' });
|
|
69
|
+
|
|
70
|
+
usersDataset.newRow();
|
|
71
|
+
usersDataset.setColumn(0, 'id', 1);
|
|
72
|
+
usersDataset.setColumn(0, 'name', 'Alice');
|
|
73
|
+
|
|
74
|
+
usersDataset.newRow();
|
|
75
|
+
usersDataset.setColumn(1, 'id', 2);
|
|
76
|
+
usersDataset.setColumn(1, 'name', 'Bob');
|
|
77
|
+
|
|
78
|
+
xapi.addDataset(usersDataset);
|
|
79
|
+
|
|
80
|
+
console.log('XapiRoot created:', xapi);
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Serializing XapiRoot to XML
|
|
84
|
+
|
|
85
|
+
You can serialize an `XapiRoot` object back into an X-API XML string:
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { writeString, XapiRoot, Dataset } from '@xapi-ts/core';
|
|
89
|
+
|
|
90
|
+
const xapi = new XapiRoot();
|
|
91
|
+
xapi.addParameter({ id: 'status', value: 'OK' });
|
|
92
|
+
|
|
93
|
+
const productsDataset = new Dataset('products');
|
|
94
|
+
productsDataset.addColumn({ id: 'productId', type: 'STRING' });
|
|
95
|
+
productsDataset.addColumn({ id: 'price', type: 'INT' });
|
|
96
|
+
productsDataset.newRow();
|
|
97
|
+
productsDataset.setColumn(0, 'productId', 'P001');
|
|
98
|
+
productsDataset.setColumn(0, 'price', 1000);
|
|
99
|
+
xapi.addDataset(productsDataset);
|
|
100
|
+
|
|
101
|
+
async function writeXapi() {
|
|
102
|
+
const xmlOutput = await writeString(xapi);
|
|
103
|
+
console.log('생성된 XML:
|
|
104
|
+
', xmlOutput);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
writeXapi();
|
|
108
|
+
```
|
|
14
109
|
|
|
15
110
|
---
|
|
16
111
|
|
|
@@ -21,9 +116,103 @@ pnpm add @xapi-ts/core
|
|
|
21
116
|
## 설치
|
|
22
117
|
|
|
23
118
|
```bash
|
|
119
|
+
# npm
|
|
120
|
+
npm install @xapi-ts/core
|
|
121
|
+
|
|
122
|
+
# yarn
|
|
123
|
+
yarn add @xapi-ts/core
|
|
124
|
+
|
|
125
|
+
# pnpm
|
|
24
126
|
pnpm add @xapi-ts/core
|
|
127
|
+
|
|
128
|
+
# bun
|
|
129
|
+
bun add @xapi-ts/core
|
|
130
|
+
|
|
131
|
+
# deno
|
|
132
|
+
deno add @xapi-ts/core
|
|
25
133
|
```
|
|
26
134
|
|
|
27
135
|
## 사용법
|
|
28
136
|
|
|
29
|
-
|
|
137
|
+
`@xapi-ts/core`는 X-API 데이터를 다루기 위한 기본적인 클래스와 함수를 제공합니다.
|
|
138
|
+
|
|
139
|
+
### X-API XML 파싱
|
|
140
|
+
|
|
141
|
+
X-API XML 문자열을 `XapiRoot` 객체로 파싱할 수 있습니다:
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import { parse, XapiRoot } from '@xapi-ts/core';
|
|
145
|
+
|
|
146
|
+
const xmlString = `<?xml version="1.0" encoding="UTF-8"?>
|
|
147
|
+
<Root xmlns="http://www.tobesoft.com/platform/Dataset" ver="4000">
|
|
148
|
+
<Parameters>
|
|
149
|
+
<Parameter id="service">stock</Parameter>
|
|
150
|
+
<Parameter id="method">search</Parameter>
|
|
151
|
+
</Parameters>
|
|
152
|
+
</Root>`;
|
|
153
|
+
|
|
154
|
+
async function parseXapi() {
|
|
155
|
+
const xapi = await parse(xmlString);
|
|
156
|
+
console.log('서비스:', xapi.getParameter('service')?.value);
|
|
157
|
+
console.log('메서드:', xapi.getParameter('method')?.value);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
parseXapi();
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### XapiRoot 생성 및 조작
|
|
164
|
+
|
|
165
|
+
`XapiRoot` 객체를 생성하고 매개변수 및 데이터셋을 프로그래밍 방식으로 추가할 수 있습니다:
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
import { XapiRoot, Dataset } from '@xapi-ts/core';
|
|
169
|
+
|
|
170
|
+
const xapi = new XapiRoot();
|
|
171
|
+
|
|
172
|
+
// 매개변수 추가
|
|
173
|
+
xapi.addParameter({ id: 'resultCode', value: '0' });
|
|
174
|
+
xapi.addParameter({ id: 'resultMsg', value: 'SUCCESS' });
|
|
175
|
+
|
|
176
|
+
// 데이터셋 생성 및 추가
|
|
177
|
+
const usersDataset = new Dataset('users');
|
|
178
|
+
usersDataset.addColumn({ id: 'id', type: 'INT' });
|
|
179
|
+
usersDataset.addColumn({ id: 'name', type: 'STRING' });
|
|
180
|
+
let rowIdx: number;
|
|
181
|
+
rowIdx = usersDataset.newRow();
|
|
182
|
+
usersDataset.setColumn(rowIdx, 'id', 1);
|
|
183
|
+
usersDataset.setColumn(rowIdx, 'name', 'Alice');
|
|
184
|
+
|
|
185
|
+
rowIdx = usersDataset.newRow();
|
|
186
|
+
usersDataset.setColumn(rowIdx, 'id', 2);
|
|
187
|
+
usersDataset.setColumn(rowIdx, 'name', 'Bob');
|
|
188
|
+
|
|
189
|
+
xapi.addDataset(usersDataset);
|
|
190
|
+
|
|
191
|
+
console.log('XapiRoot 생성됨:', xapi);
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### XapiRoot를 XML로 직렬화
|
|
195
|
+
|
|
196
|
+
`XapiRoot` 객체를 X-API XML 문자열로 다시 직렬화할 수 있습니다:
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
import { write, XapiRoot, Dataset } from '@xapi-ts/core';
|
|
200
|
+
|
|
201
|
+
const xapi = new XapiRoot();
|
|
202
|
+
xapi.addParameter({ id: 'status', value: 'OK' });
|
|
203
|
+
|
|
204
|
+
const productsDataset = new Dataset('products');
|
|
205
|
+
productsDataset.addColumn({ id: 'productId', type: 'STRING' });
|
|
206
|
+
productsDataset.addColumn({ id: 'price', type: 'INT' });
|
|
207
|
+
productsDataset.newRow();
|
|
208
|
+
productsDataset.setColumn(0, 'productId', 'P001');
|
|
209
|
+
productsDataset.setColumn(0, 'price', 1000);
|
|
210
|
+
xapi.addDataset(productsDataset);
|
|
211
|
+
|
|
212
|
+
async function writeXapi() {
|
|
213
|
+
const xmlOutput = await write(xapi);
|
|
214
|
+
console.log('생성된 XML:\n', xmlOutput);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
writeXapi();
|
|
218
|
+
```
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -22,10 +32,13 @@ var index_exports = {};
|
|
|
22
32
|
__export(index_exports, {
|
|
23
33
|
ColumnTypeError: () => ColumnTypeError,
|
|
24
34
|
Dataset: () => Dataset,
|
|
35
|
+
InvalidXmlError: () => InvalidXmlError,
|
|
25
36
|
NexaVersion: () => NexaVersion,
|
|
26
37
|
StringWritableStream: () => StringWritableStream,
|
|
27
38
|
XapiRoot: () => XapiRoot,
|
|
28
39
|
XplatformVersion: () => XplatformVersion,
|
|
40
|
+
_unescapeXml: () => _unescapeXml,
|
|
41
|
+
arrayBufferToString: () => arrayBufferToString,
|
|
29
42
|
base64ToUint8Array: () => base64ToUint8Array,
|
|
30
43
|
columnType: () => columnType,
|
|
31
44
|
convertToColumnType: () => convertToColumnType,
|
|
@@ -34,7 +47,7 @@ __export(index_exports, {
|
|
|
34
47
|
initXapi: () => initXapi,
|
|
35
48
|
makeParseEntities: () => makeParseEntities,
|
|
36
49
|
makeWriterEntities: () => makeWriterEntities,
|
|
37
|
-
parse: () =>
|
|
50
|
+
parse: () => parse2,
|
|
38
51
|
rowType: () => rowType,
|
|
39
52
|
stringToDate: () => stringToDate,
|
|
40
53
|
stringToReadableStream: () => stringToReadableStream,
|
|
@@ -46,6 +59,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
46
59
|
|
|
47
60
|
// src/handler.ts
|
|
48
61
|
var import_stax_xml = require("stax-xml");
|
|
62
|
+
var txml = __toESM(require("txml"), 1);
|
|
49
63
|
|
|
50
64
|
// src/types.ts
|
|
51
65
|
var rowType = ["insert", "update", "delete"];
|
|
@@ -64,21 +78,31 @@ var ColumnTypeError = class extends Error {
|
|
|
64
78
|
this.name = "ColumnTypeError";
|
|
65
79
|
}
|
|
66
80
|
};
|
|
81
|
+
var InvalidXmlError = class extends Error {
|
|
82
|
+
constructor(message) {
|
|
83
|
+
super(message);
|
|
84
|
+
this.name = "InvalidXmlError";
|
|
85
|
+
}
|
|
86
|
+
};
|
|
67
87
|
|
|
68
88
|
// src/utils.ts
|
|
89
|
+
function arrayBufferToString(buffer) {
|
|
90
|
+
const decoder = new TextDecoder();
|
|
91
|
+
return decoder.decode(buffer);
|
|
92
|
+
}
|
|
69
93
|
function makeParseEntities() {
|
|
70
|
-
const
|
|
94
|
+
const entities2 = [];
|
|
71
95
|
for (let i = 1; i <= 32; i++) {
|
|
72
|
-
|
|
96
|
+
entities2.push({ entity: `&#${i};`, value: String.fromCharCode(i) });
|
|
73
97
|
}
|
|
74
|
-
return
|
|
98
|
+
return entities2;
|
|
75
99
|
}
|
|
76
100
|
function makeWriterEntities() {
|
|
77
|
-
const
|
|
101
|
+
const entities2 = [];
|
|
78
102
|
for (let i = 1; i <= 32; i++) {
|
|
79
|
-
|
|
103
|
+
entities2.push({ entity: `&#${i};`, value: String.fromCharCode(i) });
|
|
80
104
|
}
|
|
81
|
-
return
|
|
105
|
+
return entities2;
|
|
82
106
|
}
|
|
83
107
|
function base64ToUint8Array(base64String) {
|
|
84
108
|
const binaryString = atob(base64String);
|
|
@@ -156,6 +180,7 @@ function dateToString(date, type) {
|
|
|
156
180
|
}
|
|
157
181
|
}
|
|
158
182
|
var StringWritableStream = class extends WritableStream {
|
|
183
|
+
result = "";
|
|
159
184
|
constructor() {
|
|
160
185
|
const decoder = new TextDecoder();
|
|
161
186
|
super({
|
|
@@ -166,7 +191,6 @@ var StringWritableStream = class extends WritableStream {
|
|
|
166
191
|
this.result += decoder.decode();
|
|
167
192
|
}
|
|
168
193
|
});
|
|
169
|
-
this.result = "";
|
|
170
194
|
}
|
|
171
195
|
/**
|
|
172
196
|
* Returns the collected string result.
|
|
@@ -227,23 +251,34 @@ function convertToString(value, type) {
|
|
|
227
251
|
return dateToString(value, type);
|
|
228
252
|
case "BLOB":
|
|
229
253
|
return uint8ArrayToBase64(value);
|
|
254
|
+
case "STRING":
|
|
255
|
+
return String(value);
|
|
230
256
|
default:
|
|
231
257
|
return String(value);
|
|
232
258
|
}
|
|
233
259
|
}
|
|
260
|
+
var entities = makeParseEntities();
|
|
261
|
+
function _unescapeXml(str) {
|
|
262
|
+
if (!str) return str;
|
|
263
|
+
const regex = new RegExp(entities.map((e) => e.entity).join("|"), "g");
|
|
264
|
+
return str.replace(regex, (match) => {
|
|
265
|
+
const entity = entities.find((e) => e.entity === match);
|
|
266
|
+
return entity ? entity.value : match;
|
|
267
|
+
});
|
|
268
|
+
}
|
|
234
269
|
|
|
235
270
|
// src/xapi-data.ts
|
|
236
271
|
var XapiRoot = class {
|
|
272
|
+
/** An array of datasets within the X-API root. */
|
|
273
|
+
datasets = [];
|
|
274
|
+
/** Parameters associated with the X-API root. */
|
|
275
|
+
parameters = { params: [] };
|
|
237
276
|
/**
|
|
238
277
|
* Creates an instance of XapiRoot.
|
|
239
278
|
* @param datasets - Initial array of datasets.
|
|
240
279
|
* @param parameters - Initial parameters.
|
|
241
280
|
*/
|
|
242
281
|
constructor(datasets = [], parameters = { params: [] }) {
|
|
243
|
-
/** An array of datasets within the X-API root. */
|
|
244
|
-
this.datasets = [];
|
|
245
|
-
/** Parameters associated with the X-API root. */
|
|
246
|
-
this.parameters = { params: [] };
|
|
247
282
|
this.datasets = datasets;
|
|
248
283
|
this.parameters = parameters;
|
|
249
284
|
}
|
|
@@ -331,6 +366,13 @@ var XapiRoot = class {
|
|
|
331
366
|
}
|
|
332
367
|
};
|
|
333
368
|
var Dataset = class {
|
|
369
|
+
/** The ID of the dataset. */
|
|
370
|
+
id;
|
|
371
|
+
constColumns = [];
|
|
372
|
+
columns = [];
|
|
373
|
+
/** An array of rows in the dataset. */
|
|
374
|
+
rows = [];
|
|
375
|
+
_columnIndexMap = /* @__PURE__ */ new Map();
|
|
334
376
|
/**
|
|
335
377
|
* Creates an instance of Dataset.
|
|
336
378
|
* @param id - The ID of the dataset.
|
|
@@ -339,11 +381,6 @@ var Dataset = class {
|
|
|
339
381
|
* @param rows - Initial array of rows.
|
|
340
382
|
*/
|
|
341
383
|
constructor(id, constColumns = [], columns = [], rows = []) {
|
|
342
|
-
this.constColumns = [];
|
|
343
|
-
this.columns = [];
|
|
344
|
-
/** An array of rows in the dataset. */
|
|
345
|
-
this.rows = [];
|
|
346
|
-
this._columnIndexMap = /* @__PURE__ */ new Map();
|
|
347
384
|
this.id = id;
|
|
348
385
|
this.constColumns = constColumns;
|
|
349
386
|
this.columns = columns;
|
|
@@ -524,127 +561,105 @@ function initXapi(options) {
|
|
|
524
561
|
...options
|
|
525
562
|
};
|
|
526
563
|
}
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
if (typeof reader === "string") {
|
|
530
|
-
_stream = new ReadableStream({
|
|
531
|
-
start(controller) {
|
|
532
|
-
controller.enqueue(new TextEncoder().encode(reader));
|
|
533
|
-
controller.close();
|
|
534
|
-
}
|
|
535
|
-
});
|
|
536
|
-
} else {
|
|
537
|
-
_stream = reader;
|
|
538
|
-
}
|
|
539
|
-
const xmlParser = new import_stax_xml.StaxXmlParser(_stream, {
|
|
540
|
-
addEntities: makeParseEntities(),
|
|
541
|
-
encoding: "UTF-8"
|
|
542
|
-
});
|
|
564
|
+
function parse2(xml) {
|
|
565
|
+
const parsedXml = txml.parse(xml);
|
|
543
566
|
const xapiRoot = new XapiRoot();
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
type: startEvent.attributes["type"] || "STRING",
|
|
557
|
-
value: _options.parseToTypes ? convertToColumnType(paramValue, startEvent.attributes["type"] || "STRING") : paramValue
|
|
558
|
-
});
|
|
559
|
-
break;
|
|
560
|
-
case "Dataset":
|
|
561
|
-
xapiRoot.addDataset(await parseDataset(startEvent, xmlParser));
|
|
562
|
-
break;
|
|
567
|
+
const rootElement = parsedXml.find((node) => {
|
|
568
|
+
const rootNode = node;
|
|
569
|
+
return rootNode.tagName === "Root";
|
|
570
|
+
});
|
|
571
|
+
if (rootElement === void 0) return xapiRoot;
|
|
572
|
+
const parametersElement = rootElement.children?.find((node) => node.tagName === "Parameters");
|
|
573
|
+
parseParameters(parametersElement, xapiRoot);
|
|
574
|
+
const datasetsElements = rootElement.children?.filter((node) => node.tagName === "Dataset");
|
|
575
|
+
if (datasetsElements && datasetsElements?.length && datasetsElements.length > 0) {
|
|
576
|
+
for (const datasetsElement of datasetsElements) {
|
|
577
|
+
if (!datasetsElement.attributes || !datasetsElement.attributes.id) {
|
|
578
|
+
throw new InvalidXmlError("Dataset element must have an 'id' attribute");
|
|
563
579
|
}
|
|
580
|
+
const datasetId = datasetsElement.attributes?.id;
|
|
581
|
+
const dataset = new Dataset(datasetId);
|
|
582
|
+
xapiRoot.addDataset(dataset);
|
|
583
|
+
const columnInfoElement = datasetsElement.children?.find((node) => node.tagName === "ColumnInfo");
|
|
584
|
+
parseColumnInfo(columnInfoElement, dataset);
|
|
585
|
+
const rowsElement = datasetsElement.children?.find((node) => node.tagName === "Rows");
|
|
586
|
+
parseRows(rowsElement, dataset);
|
|
564
587
|
}
|
|
565
588
|
}
|
|
566
589
|
return xapiRoot;
|
|
567
590
|
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
591
|
+
function parseValue(value, type = "STRING") {
|
|
592
|
+
value = _unescapeXml(value);
|
|
593
|
+
return _options.parseToTypes ? convertToColumnType(value, type) : value;
|
|
594
|
+
}
|
|
595
|
+
function parseColumnInfo(columnInfoElement, dataset) {
|
|
596
|
+
if (!columnInfoElement) throw new InvalidXmlError("ColumnInfo element is missing in the dataset");
|
|
597
|
+
columnInfoElement.children?.forEach((colInfo) => {
|
|
598
|
+
if (colInfo.tagName === "ConstColumn") {
|
|
599
|
+
dataset.addConstColumn({
|
|
600
|
+
id: colInfo.attributes?.id,
|
|
601
|
+
size: parseInt(colInfo.attributes?.size || "0", 10),
|
|
602
|
+
type: colInfo.attributes?.type || "STRING",
|
|
603
|
+
value: parseValue(colInfo.attributes?.value, colInfo.attributes?.type)
|
|
604
|
+
});
|
|
605
|
+
} else if (colInfo.tagName === "Column") {
|
|
606
|
+
dataset.addColumn({
|
|
607
|
+
id: colInfo.attributes?.id,
|
|
608
|
+
size: parseInt(colInfo.attributes?.size || "0", 10),
|
|
609
|
+
type: colInfo.attributes?.type || "STRING"
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
function parseRows(rowsElement, dataset) {
|
|
615
|
+
rowsElement?.children?.forEach((r) => {
|
|
616
|
+
if (r.tagName === "Row") {
|
|
617
|
+
const rowIndex = dataset.newRow();
|
|
618
|
+
dataset.rows[rowIndex].type = r.attributes?.type || void 0;
|
|
619
|
+
r.children?.forEach((col) => {
|
|
620
|
+
if (col.tagName === "Col") {
|
|
621
|
+
const colId = col.attributes?.id;
|
|
622
|
+
const value = col.children?.[0];
|
|
623
|
+
const columnInfo = dataset.getColumnInfo(colId);
|
|
624
|
+
if (!columnInfo) throw new InvalidXmlError(`Column with id ${colId} not found in dataset ${dataset.id}`);
|
|
625
|
+
const castedValue = parseValue(value, columnInfo.type);
|
|
626
|
+
dataset.rows[rowIndex].cols.push({ id: colId, value: castedValue });
|
|
627
|
+
} else if (col.tagName === "OrgRow") {
|
|
628
|
+
dataset.rows[rowIndex].orgRow = [];
|
|
629
|
+
col.children?.forEach((orgCol) => {
|
|
630
|
+
if (orgCol.tagName === "Col") {
|
|
631
|
+
const colId = orgCol.attributes?.id;
|
|
632
|
+
const value = orgCol.children?.[0];
|
|
633
|
+
const columnInfo = dataset.getColumnInfo(colId);
|
|
634
|
+
const castedValue = parseValue(value, columnInfo.type);
|
|
635
|
+
if (dataset && dataset.rows && dataset.rows[rowIndex] && dataset.rows[rowIndex].orgRow) {
|
|
636
|
+
dataset.rows[rowIndex].orgRow.push({ id: colId, value: castedValue });
|
|
637
|
+
}
|
|
638
|
+
}
|
|
590
639
|
});
|
|
591
|
-
break;
|
|
592
|
-
case "Row":
|
|
593
|
-
currentRowIndex = dataset.newRow();
|
|
594
|
-
dataset.rows[currentRowIndex].type = startEvent.attributes["type"] || void 0;
|
|
595
|
-
break;
|
|
596
|
-
case "Col": {
|
|
597
|
-
await parseCol(xmlParser, startEvent, dataset, currentRowIndex, false);
|
|
598
|
-
break;
|
|
599
640
|
}
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
for await (const orgRowEvent of xmlParser) {
|
|
606
|
-
if (orgRowEvent.type === import_stax_xml.XmlEventType.END_ELEMENT && orgRowEvent.localName === "OrgRow") {
|
|
607
|
-
break;
|
|
608
|
-
}
|
|
609
|
-
if (orgRowEvent.type === import_stax_xml.XmlEventType.START_ELEMENT && orgRowEvent.localName === "Col") {
|
|
610
|
-
const orgColEvent = orgRowEvent;
|
|
611
|
-
await parseCol(xmlParser, orgColEvent, dataset, currentRowIndex, true);
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
}
|
|
641
|
+
});
|
|
642
|
+
} else if (r.tagName === "Col") {
|
|
643
|
+
throw new InvalidXmlError("Row must be defined before Col");
|
|
644
|
+
} else if (r.tagName === "OrgRow") {
|
|
645
|
+
throw new InvalidXmlError("Row must be defined before OrgRow");
|
|
615
646
|
}
|
|
616
|
-
}
|
|
617
|
-
return dataset;
|
|
647
|
+
});
|
|
618
648
|
}
|
|
619
|
-
|
|
620
|
-
if (
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
value = colCharEvent.value;
|
|
632
|
-
} else if (colCharEvent.type === import_stax_xml.XmlEventType.CHARACTERS) {
|
|
633
|
-
value = colCharEvent.value;
|
|
634
|
-
}
|
|
635
|
-
let castedValue = value;
|
|
636
|
-
if (_options.parseToTypes) {
|
|
637
|
-
const columnInfo = dataset.getColumnInfo(colId);
|
|
638
|
-
if (!columnInfo || columnType.includes(columnInfo.type) === false) {
|
|
639
|
-
throw new Error(`Column type for ${colId} not found in dataset ${dataset.id}`);
|
|
649
|
+
function parseParameters(parametersElement, xapiRoot) {
|
|
650
|
+
if (!parametersElement) return;
|
|
651
|
+
parametersElement.children?.forEach((p) => {
|
|
652
|
+
if (p.tagName === "Parameter") {
|
|
653
|
+
const id = p.attributes?.id;
|
|
654
|
+
const type = p.attributes?.type || "STRING";
|
|
655
|
+
const value = p.children?.[0];
|
|
656
|
+
xapiRoot.addParameter({
|
|
657
|
+
id,
|
|
658
|
+
type,
|
|
659
|
+
value: parseValue(value, type)
|
|
660
|
+
});
|
|
640
661
|
}
|
|
641
|
-
|
|
642
|
-
}
|
|
643
|
-
if (!isOrgRow) {
|
|
644
|
-
dataset.rows[currentRowIndex].cols.push({ id: colId, value: castedValue });
|
|
645
|
-
} else {
|
|
646
|
-
dataset.rows[currentRowIndex].orgRow.push({ id: colId, value: castedValue });
|
|
647
|
-
}
|
|
662
|
+
});
|
|
648
663
|
}
|
|
649
664
|
async function writeString(root) {
|
|
650
665
|
const stringStream = new StringWritableStream();
|
|
@@ -765,10 +780,13 @@ async function writeColumn(writer, dataset, col) {
|
|
|
765
780
|
0 && (module.exports = {
|
|
766
781
|
ColumnTypeError,
|
|
767
782
|
Dataset,
|
|
783
|
+
InvalidXmlError,
|
|
768
784
|
NexaVersion,
|
|
769
785
|
StringWritableStream,
|
|
770
786
|
XapiRoot,
|
|
771
787
|
XplatformVersion,
|
|
788
|
+
_unescapeXml,
|
|
789
|
+
arrayBufferToString,
|
|
772
790
|
base64ToUint8Array,
|
|
773
791
|
columnType,
|
|
774
792
|
convertToColumnType,
|
package/dist/index.d.cts
CHANGED
|
@@ -127,6 +127,9 @@ interface XapiOptions {
|
|
|
127
127
|
declare class ColumnTypeError extends Error {
|
|
128
128
|
constructor(message: string);
|
|
129
129
|
}
|
|
130
|
+
declare class InvalidXmlError extends Error {
|
|
131
|
+
constructor(message: string);
|
|
132
|
+
}
|
|
130
133
|
|
|
131
134
|
/**
|
|
132
135
|
* Represents the root of an X-API XML structure, containing datasets and parameters.
|
|
@@ -312,17 +315,19 @@ declare class Dataset {
|
|
|
312
315
|
/**
|
|
313
316
|
* Initializes the X-API handler with the provided options.
|
|
314
317
|
* @param options - The options to initialize the X-API handler.
|
|
318
|
+
* @returns void
|
|
315
319
|
*/
|
|
316
320
|
declare function initXapi(options: XapiOptions): void;
|
|
317
321
|
/**
|
|
318
|
-
* Parses an XML
|
|
319
|
-
* @param
|
|
322
|
+
* Parses an XML string into an XapiRoot object using txml.
|
|
323
|
+
* @param xml - The string containing the XML data.
|
|
320
324
|
* @returns A Promise that resolves to an XapiRoot object.
|
|
321
325
|
*/
|
|
322
|
-
declare function parse(
|
|
326
|
+
declare function parse(xml: string): XapiRoot;
|
|
323
327
|
declare function writeString(root: XapiRoot): Promise<string>;
|
|
324
328
|
declare function write(stream: WritableStream<Uint8Array>, root: XapiRoot): Promise<void>;
|
|
325
329
|
|
|
330
|
+
declare function arrayBufferToString(buffer: ArrayBuffer): string;
|
|
326
331
|
/**
|
|
327
332
|
* Creates an array of entities for parsing XML, including control characters.
|
|
328
333
|
* @returns An array of objects, each with an `entity` (e.g., "") and its `value` (e.g., "\x01").
|
|
@@ -398,5 +403,6 @@ declare function convertToColumnType(value: XapiValueType, type: ColumnType): Xa
|
|
|
398
403
|
* @returns The string representation of the value.
|
|
399
404
|
*/
|
|
400
405
|
declare function convertToString(value: XapiValueType, type: ColumnType): string;
|
|
406
|
+
declare function _unescapeXml(str?: string): string | undefined;
|
|
401
407
|
|
|
402
|
-
export { type Col, type Column, type ColumnInfo, type ColumnType, ColumnTypeError, type ConstColumn, Dataset, NexaVersion, type Parameter, type Row, type RowType, type Rows, StringWritableStream, type XapiOptions, type XapiParameters, XapiRoot, type XapiValueType, type XapiVersion, XplatformVersion, base64ToUint8Array, columnType, convertToColumnType, convertToString, dateToString, initXapi, makeParseEntities, makeWriterEntities, parse, rowType, stringToDate, stringToReadableStream, uint8ArrayToBase64, write, writeString };
|
|
408
|
+
export { type Col, type Column, type ColumnInfo, type ColumnType, ColumnTypeError, type ConstColumn, Dataset, InvalidXmlError, NexaVersion, type Parameter, type Row, type RowType, type Rows, StringWritableStream, type XapiOptions, type XapiParameters, XapiRoot, type XapiValueType, type XapiVersion, XplatformVersion, _unescapeXml, arrayBufferToString, base64ToUint8Array, columnType, convertToColumnType, convertToString, dateToString, initXapi, makeParseEntities, makeWriterEntities, parse, rowType, stringToDate, stringToReadableStream, uint8ArrayToBase64, write, writeString };
|
package/dist/index.d.ts
CHANGED
|
@@ -127,6 +127,9 @@ interface XapiOptions {
|
|
|
127
127
|
declare class ColumnTypeError extends Error {
|
|
128
128
|
constructor(message: string);
|
|
129
129
|
}
|
|
130
|
+
declare class InvalidXmlError extends Error {
|
|
131
|
+
constructor(message: string);
|
|
132
|
+
}
|
|
130
133
|
|
|
131
134
|
/**
|
|
132
135
|
* Represents the root of an X-API XML structure, containing datasets and parameters.
|
|
@@ -312,17 +315,19 @@ declare class Dataset {
|
|
|
312
315
|
/**
|
|
313
316
|
* Initializes the X-API handler with the provided options.
|
|
314
317
|
* @param options - The options to initialize the X-API handler.
|
|
318
|
+
* @returns void
|
|
315
319
|
*/
|
|
316
320
|
declare function initXapi(options: XapiOptions): void;
|
|
317
321
|
/**
|
|
318
|
-
* Parses an XML
|
|
319
|
-
* @param
|
|
322
|
+
* Parses an XML string into an XapiRoot object using txml.
|
|
323
|
+
* @param xml - The string containing the XML data.
|
|
320
324
|
* @returns A Promise that resolves to an XapiRoot object.
|
|
321
325
|
*/
|
|
322
|
-
declare function parse(
|
|
326
|
+
declare function parse(xml: string): XapiRoot;
|
|
323
327
|
declare function writeString(root: XapiRoot): Promise<string>;
|
|
324
328
|
declare function write(stream: WritableStream<Uint8Array>, root: XapiRoot): Promise<void>;
|
|
325
329
|
|
|
330
|
+
declare function arrayBufferToString(buffer: ArrayBuffer): string;
|
|
326
331
|
/**
|
|
327
332
|
* Creates an array of entities for parsing XML, including control characters.
|
|
328
333
|
* @returns An array of objects, each with an `entity` (e.g., "") and its `value` (e.g., "\x01").
|
|
@@ -398,5 +403,6 @@ declare function convertToColumnType(value: XapiValueType, type: ColumnType): Xa
|
|
|
398
403
|
* @returns The string representation of the value.
|
|
399
404
|
*/
|
|
400
405
|
declare function convertToString(value: XapiValueType, type: ColumnType): string;
|
|
406
|
+
declare function _unescapeXml(str?: string): string | undefined;
|
|
401
407
|
|
|
402
|
-
export { type Col, type Column, type ColumnInfo, type ColumnType, ColumnTypeError, type ConstColumn, Dataset, NexaVersion, type Parameter, type Row, type RowType, type Rows, StringWritableStream, type XapiOptions, type XapiParameters, XapiRoot, type XapiValueType, type XapiVersion, XplatformVersion, base64ToUint8Array, columnType, convertToColumnType, convertToString, dateToString, initXapi, makeParseEntities, makeWriterEntities, parse, rowType, stringToDate, stringToReadableStream, uint8ArrayToBase64, write, writeString };
|
|
408
|
+
export { type Col, type Column, type ColumnInfo, type ColumnType, ColumnTypeError, type ConstColumn, Dataset, InvalidXmlError, NexaVersion, type Parameter, type Row, type RowType, type Rows, StringWritableStream, type XapiOptions, type XapiParameters, XapiRoot, type XapiValueType, type XapiVersion, XplatformVersion, _unescapeXml, arrayBufferToString, base64ToUint8Array, columnType, convertToColumnType, convertToString, dateToString, initXapi, makeParseEntities, makeWriterEntities, parse, rowType, stringToDate, stringToReadableStream, uint8ArrayToBase64, write, writeString };
|
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,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xapi-js/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.1.1",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -32,12 +32,14 @@
|
|
|
32
32
|
"typescript": "^5.3.3"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"stax-xml": "^0.2.4"
|
|
35
|
+
"stax-xml": "^0.2.4",
|
|
36
|
+
"txml": "^5.1.1"
|
|
36
37
|
},
|
|
37
38
|
"scripts": {
|
|
38
39
|
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
39
40
|
"test": "vitest run",
|
|
40
41
|
"test:watch": "vitest",
|
|
41
|
-
"coverage": "vitest run --coverage"
|
|
42
|
+
"coverage": "vitest run --coverage",
|
|
43
|
+
"benchmark": "node test/performance.test.mjs"
|
|
42
44
|
}
|
|
43
45
|
}
|