Files
2026-03-13 09:53:40 +01:00

185 lines
8.2 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Parser = void 0;
const configuration_1 = require("./configuration");
const tokenizer_1 = require("./tokenizer");
const events_1 = require("events");
const separators_1 = require("./edi/separators");
var States;
(function (States) {
States[States["EMPTY"] = 0] = "EMPTY";
States[States["SEGMENT"] = 1] = "SEGMENT";
States[States["ELEMENT"] = 2] = "ELEMENT";
States[States["COMPONENT"] = 3] = "COMPONENT";
States[States["MODESET"] = 4] = "MODESET";
States[States["DATA"] = 5] = "DATA";
States[States["CONTINUED"] = 6] = "CONTINUED";
})(States || (States = {}));
class Parser extends events_1.EventEmitter {
constructor(configuration) {
super();
this.errors = {
incompleteMessage: function () {
return new Error("Cannot close an incomplete message");
},
invalidCharacter: function (character, index) {
let message = "";
message += "Invalid character " + character;
message += ` at position ${index}`;
return new Error(message);
},
invalidControlAfterSegment: function (segment, character) {
let message = "";
message += "Invalid character '" + character;
message += "' after reading segment name " + segment;
return new Error(message);
}
};
events_1.EventEmitter.apply(this);
if (configuration) {
this.configuration = configuration;
}
else {
this.configuration = new configuration_1.Configuration();
}
this.validator = this.configuration.validator;
this.tokenizer = new tokenizer_1.Tokenizer(this.configuration);
this.state = States.EMPTY;
}
separators() {
const builder = new separators_1.EdifactSeparatorsBuilder();
builder.elementSeparator(String.fromCharCode(this.configuration.config.dataElementSeparator));
builder.componentSeparator(String.fromCharCode(this.configuration.config.componentDataSeparator));
builder.decimalSeparator(String.fromCharCode(this.configuration.config.decimalMark));
builder.releaseIndicator(String.fromCharCode(this.configuration.config.releaseCharacter));
builder.segmentTerminator(String.fromCharCode(this.configuration.config.segmentTerminator));
return builder.build();
}
onOpenSegment(segment) {
this.emit("openSegment", segment);
}
onCloseSegment() {
this.emit("closeSegment");
}
onElement() {
this.emit("element");
}
onComponent(data) {
this.emit("component", data);
}
updateCharset(charset) {
const previous = this.configuration.charset;
this.configuration.updateCharset(charset);
if (this.configuration.charset !== previous) {
this.tokenizer.setCharsetBasedOnConfig(this.configuration);
}
}
end() {
if (this.state !== States.SEGMENT || this.tokenizer.buffer !== "") {
throw this.errors.incompleteMessage();
}
else {
this.state = States.EMPTY;
}
}
una(chunk) {
if (/^UNA.... ./g.test(chunk)) {
this.configuration.config.componentDataSeparator = chunk.charCodeAt(3);
this.configuration.config.dataElementSeparator = chunk.charCodeAt(4);
this.configuration.config.decimalMark = chunk.charCodeAt(5);
this.configuration.config.releaseCharacter = chunk.charCodeAt(6);
this.configuration.config.segmentTerminator = chunk.charCodeAt(8);
return true;
}
else {
return false;
}
}
write(chunk) {
let index = 0;
if (this.state === States.CONTINUED) {
this.state = States.MODESET;
}
while (index < chunk.length) {
switch (this.state) {
case States.EMPTY:
index = this.una(chunk) ? 9 : 0;
this.state = States.SEGMENT;
case States.SEGMENT:
index = this.tokenizer.segment(chunk, index);
switch (chunk.charCodeAt(index) || this.configuration.config.endOfTag) {
case this.configuration.config.dataElementSeparator:
this.validator.onOpenSegment(this.tokenizer.buffer);
this.onOpenSegment(this.tokenizer.buffer);
this.state = States.ELEMENT;
this.tokenizer.buffer = "";
break;
case this.configuration.config.segmentTerminator:
this.validator.onOpenSegment(this.tokenizer.buffer);
this.onOpenSegment(this.tokenizer.buffer);
this.validator.onCloseSegment("");
this.onCloseSegment();
this.state = States.SEGMENT;
this.tokenizer.buffer = "";
break;
case this.configuration.config.endOfTag:
case this.configuration.config.carriageReturn:
case this.configuration.config.lineFeed:
break;
default:
throw this.errors.invalidControlAfterSegment(this.tokenizer.buffer, chunk.charAt(index));
}
break;
case States.ELEMENT:
this.validator.onElement();
this.onElement();
case States.COMPONENT:
this.validator.onOpenComponent(this.tokenizer);
case States.MODESET:
case States.DATA:
index = this.tokenizer.data(chunk, index);
switch (chunk.charCodeAt(index) || this.configuration.config.endOfTag) {
case this.configuration.config.componentDataSeparator:
this.validator.onCloseComponent(this.tokenizer);
this.onComponent(this.tokenizer.buffer);
this.state = States.COMPONENT;
this.tokenizer.buffer = "";
break;
case this.configuration.config.dataElementSeparator:
this.validator.onCloseComponent(this.tokenizer);
this.onComponent(this.tokenizer.buffer);
this.state = States.ELEMENT;
this.tokenizer.buffer = "";
break;
case this.configuration.config.segmentTerminator:
this.validator.onCloseComponent(this.tokenizer);
this.onComponent(this.tokenizer.buffer);
this.validator.onCloseSegment("");
this.onCloseSegment();
this.state = States.SEGMENT;
this.tokenizer.buffer = "";
break;
case this.configuration.config.decimalMark:
this.tokenizer.decimal(chunk, index);
this.state = States.DATA;
break;
case this.configuration.config.releaseCharacter:
index++;
this.tokenizer.release(chunk, index);
this.state = States.DATA;
break;
case this.configuration.config.endOfTag:
case this.configuration.config.carriageReturn:
case this.configuration.config.lineFeed:
this.state = States.DATA;
break;
default:
throw this.errors.invalidCharacter(chunk.charAt(index), index);
}
}
index++;
}
}
}
exports.Parser = Parser;
//# sourceMappingURL=parser.js.map