@xapi-js/core 1.3.0 → 1.4.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/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
-
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  //#region src/types.ts
3
3
  /**
4
4
  * Defines the possible types of rows in an X-API dataset (e.g., "insert", "update", "delete").
@@ -51,7 +51,6 @@ var InvalidXmlError = class extends Error {
51
51
  this.name = "InvalidXmlError";
52
52
  }
53
53
  };
54
-
55
54
  //#endregion
56
55
  //#region src/xapi-data.ts
57
56
  /**
@@ -317,23 +316,30 @@ var Dataset = class {
317
316
  return this.rows.length;
318
317
  }
319
318
  };
320
-
321
319
  //#endregion
322
320
  //#region src/utils.ts
323
321
  function arrayBufferToString(buffer) {
324
322
  return new TextDecoder().decode(buffer);
325
323
  }
326
324
  /**
327
- * Creates an array of entities for parsing XML, including control characters.
328
- * @returns An array of objects, each with an `entity` (e.g., "") and its `value` (e.g., "\x01").
325
+ * Pre-defined XML entities for parsing, including control characters.
326
+ * Static array to avoid repeated allocation.
329
327
  */
330
- function makeParseEntities() {
331
- const entities$1 = [];
332
- for (let i = 1; i <= 32; i++) entities$1.push({
328
+ const PARSE_ENTITIES = (() => {
329
+ const entities = [];
330
+ for (let i = 1; i <= 32; i++) entities.push({
333
331
  entity: `&#${i};`,
334
332
  value: String.fromCharCode(i)
335
333
  });
336
- return entities$1;
334
+ return entities;
335
+ })();
336
+ /**
337
+ * Creates an array of entities for parsing XML, including control characters.
338
+ * @deprecated Use PARSE_ENTITIES directly for better performance
339
+ * @returns An array of objects, each with an `entity` (e.g., "&#1;") and its `value` (e.g., "\x01").
340
+ */
341
+ function makeParseEntities() {
342
+ return PARSE_ENTITIES.slice();
337
343
  }
338
344
  /**
339
345
  * Converts a Base64 string to a Uint8Array.
@@ -462,10 +468,10 @@ function stringToReadableStream(str) {
462
468
  function convertToColumnType(value, type) {
463
469
  switch (type) {
464
470
  case "INT":
465
- case "BIGDECIMAL":
466
471
  const intValue = parseInt(value, 10);
467
472
  return isNaN(intValue) ? value : intValue;
468
473
  case "FLOAT":
474
+ case "BIGDECIMAL":
469
475
  const floatValue = parseFloat(value);
470
476
  return isNaN(floatValue) ? value : floatValue;
471
477
  case "DECIMAL":
@@ -503,14 +509,21 @@ function convertToString(value, type) {
503
509
  default: return String(value);
504
510
  }
505
511
  }
506
- const entities = makeParseEntities();
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]));
507
521
  function _unescapeXml(str) {
508
522
  if (!str) return str;
523
+ if (str.indexOf("&") === -1) return str;
509
524
  let result = str.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, "\"").replace(/&apos;/g, "'").replace(/&amp;/g, "&");
510
- const regex = new RegExp(entities.map((e) => e.entity).join("|"), "g");
511
- result = result.replace(regex, (match) => {
512
- const entity = entities.find((e) => e.entity === match);
513
- return entity ? entity.value : match;
525
+ result = result.replace(CONTROL_CHAR_ENTITY_REGEX, (match) => {
526
+ return ENTITY_MAP.get(match) || match;
514
527
  });
515
528
  return result;
516
529
  }
@@ -621,6 +634,18 @@ function parseXml(xml) {
621
634
  return new XapiXmlParser(xml).parse();
622
635
  }
623
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
+ /**
624
649
  * A lightweight XML parser optimized for X-API structure.
625
650
  */
626
651
  var XapiXmlParser = class {
@@ -636,12 +661,12 @@ var XapiXmlParser = class {
636
661
  while (this.pos < this.length) {
637
662
  this.skipWhitespace();
638
663
  if (this.pos >= this.length) break;
639
- if (this.peek(5) === "<?xml") {
664
+ if (this.matches("<?xml")) {
640
665
  this.skipUntil("?>");
641
666
  this.pos += 2;
642
667
  continue;
643
668
  }
644
- if (this.peek(4) === "<!--") {
669
+ if (this.matches("<!--")) {
645
670
  this.skipUntil("-->");
646
671
  this.pos += 3;
647
672
  continue;
@@ -659,11 +684,15 @@ var XapiXmlParser = class {
659
684
  if (this.current() === "/") return null;
660
685
  const tagName = this.parseTagName();
661
686
  if (!tagName) return null;
662
- const node = { tagName };
687
+ const node = {
688
+ tagName,
689
+ attributes: void 0,
690
+ children: void 0
691
+ };
663
692
  const attributes = this.parseAttributes();
664
693
  if (attributes && Object.keys(attributes).length > 0) node.attributes = attributes;
665
694
  this.skipWhitespace();
666
- if (this.peek(2) === "/>") {
695
+ if (this.matches("/>")) {
667
696
  this.pos += 2;
668
697
  return node;
669
698
  }
@@ -671,12 +700,12 @@ var XapiXmlParser = class {
671
700
  const children = [];
672
701
  let textContent = "";
673
702
  while (this.pos < this.length) {
674
- if (this.peek(9) === "<![CDATA[") {
703
+ if (this.matches("<![CDATA[")) {
675
704
  const cdataText = this.parseCDATA();
676
705
  if (cdataText !== null) textContent += cdataText;
677
706
  continue;
678
707
  }
679
- if (this.peek(2) === "</") {
708
+ if (this.matches("</")) {
680
709
  if (textContent) children.push(textContent);
681
710
  this.pos += 2;
682
711
  this.skipUntil(">");
@@ -699,21 +728,20 @@ var XapiXmlParser = class {
699
728
  return node;
700
729
  }
701
730
  parseTagName() {
702
- let name = "";
731
+ const start = this.pos;
703
732
  while (this.pos < this.length) {
704
- const ch = this.current();
705
- if (ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === ">" || ch === "/") break;
706
- name += ch;
733
+ const code = this.currentCharCode();
734
+ if (this.isWhitespace(code) || code === CHAR_GT || code === CHAR_SLASH) break;
707
735
  this.pos++;
708
736
  }
709
- return name;
737
+ return this.xml.substring(start, this.pos);
710
738
  }
711
739
  parseAttributes() {
712
740
  const attrs = {};
713
741
  while (this.pos < this.length) {
714
742
  this.skipWhitespace();
715
743
  const ch = this.current();
716
- if (ch === ">" || ch === "/" || this.peek(2) === "/>") break;
744
+ if (ch === ">" || ch === "/" || this.matches("/>")) break;
717
745
  const attrName = this.parseAttributeName();
718
746
  if (!attrName) break;
719
747
  this.skipWhitespace();
@@ -724,74 +752,95 @@ var XapiXmlParser = class {
724
752
  return Object.keys(attrs).length > 0 ? attrs : void 0;
725
753
  }
726
754
  parseAttributeName() {
727
- let name = "";
755
+ const start = this.pos;
728
756
  while (this.pos < this.length) {
729
- const ch = this.current();
730
- if (ch === "=" || ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === ">" || ch === "/") break;
731
- name += ch;
757
+ const code = this.currentCharCode();
758
+ if (code === CHAR_EQUALS || this.isWhitespace(code) || code === CHAR_GT || code === CHAR_SLASH) break;
732
759
  this.pos++;
733
760
  }
734
- return name;
761
+ return this.xml.substring(start, this.pos);
735
762
  }
736
763
  parseAttributeValue() {
737
- let value = "";
738
- const quote = this.current();
739
- if (quote !== "\"" && quote !== "'") {
764
+ const quoteCode = this.currentCharCode();
765
+ if (quoteCode !== CHAR_QUOTE && quoteCode !== CHAR_APOS) {
766
+ const start = this.pos;
740
767
  while (this.pos < this.length) {
741
- const ch = this.current();
742
- if (ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === ">" || ch === "/") break;
743
- value += ch;
768
+ const code = this.currentCharCode();
769
+ if (this.isWhitespace(code) || code === CHAR_GT || code === CHAR_SLASH) break;
744
770
  this.pos++;
745
771
  }
746
- return value;
772
+ return this.xml.substring(start, this.pos);
747
773
  }
748
774
  this.pos++;
775
+ const start = this.pos;
749
776
  while (this.pos < this.length) {
750
- const ch = this.current();
751
- if (ch === quote) {
777
+ if (this.currentCharCode() === quoteCode) {
778
+ const value = this.xml.substring(start, this.pos);
752
779
  this.pos++;
753
- break;
780
+ return value;
754
781
  }
755
- value += ch;
756
782
  this.pos++;
757
783
  }
758
- return value;
784
+ return this.xml.substring(start, this.pos);
759
785
  }
760
786
  parseCDATA() {
761
- if (this.peek(9) !== "<![CDATA[") return null;
787
+ if (!this.matches("<![CDATA[")) return null;
762
788
  this.pos += 9;
763
- let content = "";
764
- while (this.pos < this.length) {
765
- if (this.peek(3) === "]]>") {
766
- this.pos += 3;
767
- break;
768
- }
769
- content += this.current();
770
- this.pos++;
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;
771
794
  }
795
+ const content = this.xml.substring(this.pos, endPos);
796
+ this.pos = endPos + 3;
772
797
  return content;
773
798
  }
774
799
  skipWhitespace() {
775
800
  while (this.pos < this.length) {
776
- const ch = this.current();
777
- if (ch !== " " && ch !== " " && ch !== "\n" && ch !== "\r") break;
801
+ const code = this.currentCharCode();
802
+ if (code !== CHAR_SPACE && code !== CHAR_TAB && code !== CHAR_LF && code !== CHAR_CR) break;
778
803
  this.pos++;
779
804
  }
780
805
  }
806
+ isWhitespace(code) {
807
+ return code === CHAR_SPACE || code === CHAR_TAB || code === CHAR_LF || code === CHAR_CR;
808
+ }
781
809
  skipUntil(target) {
782
- while (this.pos < this.length) {
783
- if (this.peek(target.length) === target) break;
784
- this.pos++;
785
- }
810
+ const pos = this.findString(target);
811
+ if (pos !== -1) this.pos = pos;
812
+ else this.pos = this.length;
786
813
  }
787
814
  current() {
788
815
  return this.xml[this.pos];
789
816
  }
790
- peek(length) {
791
- return this.xml.substring(this.pos, this.pos + length);
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;
792
842
  }
793
843
  };
794
-
795
844
  //#endregion
796
845
  //#region src/handler.ts
797
846
  let _options = {
@@ -826,28 +875,31 @@ function parse(xml) {
826
875
  if (typeof child === "string") continue;
827
876
  const tagName = child.tagName;
828
877
  if (tagName === "Parameters") parseParameters(child, xapiRoot);
829
- else if (tagName === "Dataset") {
830
- if (!child.attributes || !child.attributes.id) throw new InvalidXmlError("Dataset element must have an 'id' attribute");
831
- const datasetId = child.attributes.id;
832
- const dataset = new Dataset(datasetId);
833
- xapiRoot.addDataset(dataset);
834
- const datasetChildren = child.children;
835
- let columnInfoElement;
836
- let rowsElement;
837
- if (datasetChildren) for (let j = 0; j < datasetChildren.length; j++) {
838
- const datasetChild = datasetChildren[j];
839
- if (typeof datasetChild === "string") continue;
840
- const childTagName = datasetChild.tagName;
841
- if (childTagName === "ColumnInfo") columnInfoElement = datasetChild;
842
- else if (childTagName === "Rows") rowsElement = datasetChild;
843
- if (columnInfoElement && rowsElement) break;
844
- }
845
- parseColumnInfo(columnInfoElement, dataset);
846
- parseRows(rowsElement, dataset);
847
- }
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);
848
881
  }
849
882
  return xapiRoot;
850
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
+ }
851
903
  function parseValue(value, type = "STRING") {
852
904
  value = _unescapeXml(value);
853
905
  return _options.parseToTypes ? convertToColumnType(value, type) : value;
@@ -943,7 +995,7 @@ function parseParameters(parametersElement, xapiRoot) {
943
995
  const attrs = p.attributes;
944
996
  const id = attrs?.id;
945
997
  const type = attrs?.type || "STRING";
946
- const value = p.children?.[0];
998
+ const value = p.children?.[0] ?? attrs?.value;
947
999
  xapiRoot.addParameter({
948
1000
  id,
949
1001
  type,
@@ -1021,7 +1073,111 @@ function writeColumn(builder, dataset, col) {
1021
1073
  builder.writeElementWithText("Col", { id: col.id }, convertToString(col.value, colInfo.type));
1022
1074
  } else builder.writeStartElement("Col", { id: col.id }, true);
1023
1075
  }
1024
-
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
+ };
1180
+ }
1025
1181
  //#endregion
1026
1182
  exports.ColumnTypeError = ColumnTypeError;
1027
1183
  exports.Dataset = Dataset;
@@ -1038,7 +1194,12 @@ exports.columnType = columnType;
1038
1194
  exports.convertToColumnType = convertToColumnType;
1039
1195
  exports.convertToString = convertToString;
1040
1196
  exports.dateToString = dateToString;
1197
+ exports.decodeRoot = decodeRoot;
1198
+ exports.defineDataset = defineDataset;
1199
+ exports.defineOperation = defineOperation;
1200
+ exports.defineRoot = defineRoot;
1041
1201
  exports.encodeControlChars = encodeControlChars;
1202
+ exports.encodeRoot = encodeRoot;
1042
1203
  exports.escapeXml = escapeXml;
1043
1204
  exports.initXapi = initXapi;
1044
1205
  exports.isXapiRoot = isXapiRoot;
@@ -1049,4 +1210,5 @@ exports.rowType = rowType;
1049
1210
  exports.stringToDate = stringToDate;
1050
1211
  exports.stringToReadableStream = stringToReadableStream;
1051
1212
  exports.uint8ArrayToBase64 = uint8ArrayToBase64;
1052
- exports.write = write;
1213
+ exports.write = write;
1214
+ exports.xapi = xapi;
package/dist/index.d.cts CHANGED
@@ -341,6 +341,7 @@ type XmlNode = {
341
341
  declare function arrayBufferToString(buffer: ArrayBuffer): string;
342
342
  /**
343
343
  * Creates an array of entities for parsing XML, including control characters.
344
+ * @deprecated Use PARSE_ENTITIES directly for better performance
344
345
  * @returns An array of objects, each with an `entity` (e.g., "&#1;") and its `value` (e.g., "\x01").
345
346
  */
346
347
  declare function makeParseEntities(): {
@@ -468,4 +469,78 @@ declare class XmlStringBuilder {
468
469
  */
469
470
  declare function parseXml(xml: string): XmlNode[];
470
471
  //#endregion
471
- export { Col, Column, ColumnInfo, ColumnType, ColumnTypeError, ConstColumn, Dataset, InvalidXmlError, NexaVersion, Parameter, Row, RowType, Rows, StringWritableStream, XapiOptions, XapiParameters, XapiRoot, XapiValueType, XapiVersion, XmlNode, XmlStringBuilder, XplatformVersion, _unescapeXml, arrayBufferToString, base64ToUint8Array, columnType, convertToColumnType, convertToString, dateToString, encodeControlChars, escapeXml, initXapi, isXapiRoot, makeParseEntities, parse, parseXml, rowType, stringToDate, stringToReadableStream, uint8ArrayToBase64, write };
472
+ //#region src/schema.d.ts
473
+ type XapiTypeMap = {
474
+ STRING: string;
475
+ INT: number;
476
+ FLOAT: number;
477
+ DECIMAL: number;
478
+ BIGDECIMAL: number;
479
+ DATE: Date;
480
+ DATETIME: Date;
481
+ TIME: Date;
482
+ BLOB: Uint8Array;
483
+ };
484
+ interface XapiColumnSchema<T extends ColumnType = ColumnType, Optional extends boolean = boolean> {
485
+ readonly kind: "xapi-column";
486
+ readonly type: T;
487
+ readonly size: number;
488
+ readonly optional: Optional;
489
+ }
490
+ type XapiColumns = Record<string, XapiColumnSchema>;
491
+ interface XapiDatasetSchema<Columns extends XapiColumns = XapiColumns> {
492
+ readonly kind: "xapi-dataset";
493
+ readonly columns: Columns;
494
+ }
495
+ type XapiDatasets = Record<string, XapiDatasetSchema>;
496
+ interface XapiRootSchema<Datasets extends XapiDatasets = XapiDatasets, Parameters extends XapiColumns = XapiColumns> {
497
+ readonly kind: "xapi-root";
498
+ readonly datasets: Datasets;
499
+ readonly parameters: Parameters;
500
+ }
501
+ interface XapiOperation<Request extends XapiRootSchema = XapiRootSchema, Response extends XapiRootSchema = XapiRootSchema> {
502
+ readonly kind: "xapi-operation";
503
+ readonly request: Request;
504
+ readonly response: Response;
505
+ }
506
+ type RequiredColumnKeys<Columns extends XapiColumns> = { [Key in keyof Columns]-?: Columns[Key]["optional"] extends true ? never : Key; }[keyof Columns];
507
+ type OptionalColumnKeys<Columns extends XapiColumns> = { [Key in keyof Columns]-?: Columns[Key]["optional"] extends true ? Key : never; }[keyof Columns];
508
+ type InferColumns<Columns extends XapiColumns> = { [Key in RequiredColumnKeys<Columns>]: XapiTypeMap[Columns[Key]["type"]]; } & { [Key in OptionalColumnKeys<Columns>]?: XapiTypeMap[Columns[Key]["type"]]; };
509
+ type InferDataset<Schema extends XapiDatasetSchema> = InferColumns<Schema["columns"]>[];
510
+ type InferRoot<Schema extends XapiRootSchema> = {
511
+ parameters: InferColumns<Schema["parameters"]>;
512
+ datasets: { [Key in keyof Schema["datasets"]]: InferDataset<Schema["datasets"][Key]>; };
513
+ };
514
+ type RequestOf<Operation extends XapiOperation> = InferRoot<Operation["request"]>;
515
+ type ResponseOf<Operation extends XapiOperation> = InferRoot<Operation["response"]>;
516
+ type ColumnOptions<Optional extends boolean> = {
517
+ size?: number;
518
+ optional?: Optional;
519
+ };
520
+ declare function defineDataset<const Columns extends XapiColumns>(columns: Columns): XapiDatasetSchema<Columns>;
521
+ declare function defineRoot<const Datasets extends XapiDatasets, const Parameters extends XapiColumns = Record<never, never>>(definition: {
522
+ datasets: Datasets;
523
+ parameters?: Parameters;
524
+ }): XapiRootSchema<Datasets, Parameters>;
525
+ declare function defineOperation<const Request extends XapiRootSchema, const Response extends XapiRootSchema>(definition: {
526
+ request: Request;
527
+ response: Response;
528
+ }): XapiOperation<Request, Response>;
529
+ declare const xapi: {
530
+ readonly string: <const Optional extends boolean = false>(options?: ColumnOptions<Optional>) => XapiColumnSchema<"STRING", Optional>;
531
+ readonly int: <const Optional extends boolean = false>(options?: ColumnOptions<Optional>) => XapiColumnSchema<"INT", Optional>;
532
+ readonly float: <const Optional extends boolean = false>(options?: ColumnOptions<Optional>) => XapiColumnSchema<"FLOAT", Optional>;
533
+ readonly decimal: <const Optional extends boolean = false>(options?: ColumnOptions<Optional>) => XapiColumnSchema<"DECIMAL", Optional>;
534
+ readonly bigdecimal: <const Optional extends boolean = false>(options?: ColumnOptions<Optional>) => XapiColumnSchema<"BIGDECIMAL", Optional>;
535
+ readonly date: <const Optional extends boolean = false>(options?: ColumnOptions<Optional>) => XapiColumnSchema<"DATE", Optional>;
536
+ readonly datetime: <const Optional extends boolean = false>(options?: ColumnOptions<Optional>) => XapiColumnSchema<"DATETIME", Optional>;
537
+ readonly time: <const Optional extends boolean = false>(options?: ColumnOptions<Optional>) => XapiColumnSchema<"TIME", Optional>;
538
+ readonly blob: <const Optional extends boolean = false>(options?: ColumnOptions<Optional>) => XapiColumnSchema<"BLOB", Optional>;
539
+ readonly dataset: typeof defineDataset;
540
+ readonly root: typeof defineRoot;
541
+ readonly operation: typeof defineOperation;
542
+ };
543
+ declare function encodeRoot<Schema extends XapiRootSchema>(schema: Schema, value: InferRoot<Schema>): XapiRoot;
544
+ declare function decodeRoot<Schema extends XapiRootSchema>(schema: Schema, root: XapiRoot): InferRoot<Schema>;
545
+ //#endregion
546
+ export { Col, Column, ColumnInfo, ColumnType, ColumnTypeError, ConstColumn, Dataset, InferColumns, InferDataset, InferRoot, InvalidXmlError, NexaVersion, Parameter, RequestOf, ResponseOf, Row, RowType, Rows, StringWritableStream, XapiColumnSchema, XapiColumns, XapiDatasetSchema, XapiDatasets, XapiOperation, XapiOptions, XapiParameters, XapiRoot, XapiRootSchema, XapiTypeMap, XapiValueType, XapiVersion, XmlNode, XmlStringBuilder, XplatformVersion, _unescapeXml, arrayBufferToString, base64ToUint8Array, columnType, convertToColumnType, convertToString, dateToString, decodeRoot, defineDataset, defineOperation, defineRoot, encodeControlChars, encodeRoot, escapeXml, initXapi, isXapiRoot, makeParseEntities, parse, parseXml, rowType, stringToDate, stringToReadableStream, uint8ArrayToBase64, write, xapi };