{"id":13577816,"url":"https://github.com/tdecaluwe/node-edifact","last_synced_at":"2025-04-05T15:31:30.195Z","repository":{"id":54957032,"uuid":"45476533","full_name":"tdecaluwe/node-edifact","owner":"tdecaluwe","description":"Javascript stream parser for UN/EDIFACT documents.","archived":false,"fork":false,"pushed_at":"2021-01-19T20:33:07.000Z","size":176,"stargazers_count":51,"open_issues_count":8,"forks_count":12,"subscribers_count":7,"default_branch":"development","last_synced_at":"2025-03-08T17:53:16.250Z","etag":null,"topics":["edi","edifact"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/edifact","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tdecaluwe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-11-03T15:40:54.000Z","updated_at":"2025-02-18T05:39:07.000Z","dependencies_parsed_at":"2022-08-14T07:20:49.350Z","dependency_job_id":null,"html_url":"https://github.com/tdecaluwe/node-edifact","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tdecaluwe%2Fnode-edifact","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tdecaluwe%2Fnode-edifact/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tdecaluwe%2Fnode-edifact/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tdecaluwe%2Fnode-edifact/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tdecaluwe","download_url":"https://codeload.github.com/tdecaluwe/node-edifact/tar.gz/refs/heads/development","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247358742,"owners_count":20926277,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["edi","edifact"],"created_at":"2024-08-01T15:01:24.580Z","updated_at":"2025-04-05T15:31:29.575Z","avatar_url":"https://github.com/tdecaluwe.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","Libraries"],"sub_categories":["Javascript"],"readme":"[![view on npm](http://img.shields.io/npm/v/edifact.svg)](https://www.npmjs.org/package/edifact)\n[![npm module downloads per month](http://img.shields.io/npm/dm/edifact.svg)](https://www.npmjs.org/package/edifact)\n[![circleci status](https://img.shields.io/circleci/project/github/tdecaluwe/node-edifact.svg)](https://circleci.com/gh/tdecaluwe/node-edifact)\n\n# node-edifact\n\nCurrently supported functionality:\n\n* An ES6 streaming parser reading UN/EDIFACT messages.\n* Provide your own event listeners to get the parser to do something useful.\n* Construct structured javascript objects from UN/EDIFACT messages.\n* Support for the UNA header and custom separators.\n* Validating data elements and components accepted by a given segment.\n* Parsing and checking standard UN/EDIFACT messages with segment tables.\n\nThis library further intends to support:\n\n* Writing and constructing UN/EDIFACT messages.\n* Out of the box support for envelopes.\n\n## Usage\n\nThis example parses a document and translates it to a javascript array `result`\ncontaining segments. Each segment is an object containing a `name` and an\n`elements` array. An element is an array of components.\n\n```javascript\nvar Parser = require('edifact/parser.js');\nvar Validator = require('edifact/validator.js');\n\nvar doc = ...;\n\nvar validator = new Validator();\nvar parser = new Parser(validator);\n\n// Provide some segment and element definitions.\nvalidator.define(...);\n\n// Parsed segments will be collected in the result array.\nvar result = [], elements, components;\n\nparser.on('opensegment', function (segment) {\n  // Started a new segment.\n  elements = [];\n  result.push({ name: segment, elements: elements });\n});\n\nparser.on('element', function () {\n  // Parsed a new element.\n  components = [];\n  elements.push(components);\n});\n\nparser.on('component', function (data) {\n  // Got a new component.\n  components.push(value);\n});\n\nparser.on('closesegment', function () {\n  // Closed a segment.\n});\n\nparser.write(doc)\nparser.end();\n```\n\n## Installation\n\nThe module can be installed through:\n\n```shell\nnpm install edifact\n```\n\nIts only dependency is the node `events` library. Keep in mind that this is an\nES6 library. It currently can be used with node 6.4 or higher. A suite of tests\nis included which can be run with the `jasmine-es6` package.\n\n## Overview\n\nThis module is built around a central `Parser` class which provides the core\nUN/EDIFACT parsing functionality. It exposes two methods, the `write()` method\nto write some data to the parser and the `end()` method to close an EDI\ninterchange. Data read by the parser can be read by using hooks which will be\ncalled on specific parsing events.\n\n### Configuring the parser\n\nThe `Parser` class currently supports any of the `UNOA`, `UNOB`, `UNOC`, `UNOY`\nand `UCS2` encoding levels. Furthermore, the parser will read any custom\ndelimiters from the `UNA` header. If such a header is not present in the\ndocument, the delimiters can also be configured manually. The delimiters should\nbe specified using their character codes. An example:\n\n```javascript\nlet parser = new Parser();\n\nparser.encoding('UNOC');\nparser.configure({\n  segmentTerminator: 39,\n  dataElementSeparator: 43,\n  componentDataSeparator: 58,\n  decimalMark: 46,\n  releaseCharacter: 63,\n});\n```\n\n### Parsing events\n\nThe parser can be used by listening to the following events:\n\n| Event | Description |\n| ----: | :---------- |\n| `opensegment` | A new segment is started. The name of the segment is passed as the argument. |\n| `element` | A new element is added. This only marks the start of the element, the data will follow through the `component` events. |\n| `component` | A component is added to the element. The data is passed on as an argument. |\n| `closesegment` | The current segment is terminated. |\n\nFor all textual fields the data will be passed on literally to the `component`\nevent handler. For numeric fields, the decimal mark will be replaced by a point\n(`12,4` becomes `12.4` if the decimal mark is a comma). Keep in mind though that\nall components will be parsed as alphanumeric fields unless a validator is\nused! Only if the component is defined as numeric in the validator can it be\nparsed as such.\n\n### Converting EDIFACT to JSON\n\nWhile the `Parser` class offers a flexible option to write your own EDIFACT\napplications, you might only be looking for an easy way read EDIFACT documents.\nThe `Reader` class offers an easy to use interface:\n\n```javascript\nlet reader = new Reader({ autoDetectEncoding: true });\nlet result = reader.parse(document);\n```\n\nThe `parse()` method returns an array of segments. Each segment is an object\ncontaining a segment `name` and the list of `elements` as an array of arrays\nwith the actual component data.\n\n### Performance\n\nParsing speed including validation but without matching against a segment table\nis around 20Mbps. Around 30% of the time spent seems to be needed for the\nvalidation part.\n\nIf performance is critical the event callbacks can also be directly defined as\nmethods on the `Parser` instance. Defining an event callback `on('opensegment',\ncallback)` then becomes:\n\n```javascript\nlet parser = new Parser();\nlet callback = function (segment) { ... };\n\nparser.onopensegment = callback;\n```\n\nKeep in mind that this avoids any `opensegment` events to be produced and as\nsuch, also its associated overhead.\n\n## Message validation\n\nThe validation of the message can be seen as two independent tasks:\n\n* On the one hand the data contained in the elements and components need to\nbe validated against their format.\n* On the other hand the structure of the segments needs to be validated.\n\n### Data validation\n\nValidation of the element and component data can be achieved through the\n`Validator` class:\n\n```javascript\nvar validator = new Validator();\nvar parser = new Parser();\n\nvalidator.define(segments);\nvalidator.define(elements);\n```\n\nHowever the `Validator` instance will only validate elements and components\nfrom segments and elements with a corresponding definition. These definitions\ncan be provided through the `define()` method. Read on to learn more about their\nsyntax.\n\n### Segment and element definitions\n\nDefinitions can be provided to describe the structure of segments and elements.\nAn example of a segment definition:\n\n```json\n{\n  \"BGM\": {\n    \"requires\": 0,\n    \"elements\": [\"C002\", \"C106\", \"1225\", \"4343\"]\n  }\n}\n```\n\nThe `elements` array contains the names of the elements that should be\nprovided. The `requires` property indicates the number of elements which are\nrequired to obtain a valid segment. Any additional elements are considered\noptional. Definitions can also be provided to define the structure of the\nelements:\n\n```json\n{\n  \"C002\": {\n    \"requires\": 4,\n    \"components\": [\"an..3\", \"an..17\", \"an..3\", \"an..35\"]\n  },\n  \"C106\": {\n    \"requires\": 3,\n    \"components\": [\"an..35\", \"an..9\", \"an..6\"]\n  }\n}\n```\n\nAn incomplete set of definitions is included with the library in the files\n`segments.js` and `elements.js` and can be included as follows:\n\n```javascript\nvar segments = require('edifact/segments');\nvar elements = require('edifact/elements');\n```\n\nA working example using segment and element definitions can be found in the\n`examples` directory.\n\n### Structural validation\n\nUsing a parser in conjuction with a `Validator` instance allows validation of\nisolated segments, elements and components. However, the parser can also be\nextended to validate the message structure. This can be accomplished by using a\n`Tracker` instance that will validate the received segments against a segment\ntable. A set of example EDIFACT messages is included in the module in JSON\nformat. To extend your parser, the segment can be passed on to the `Tracker` in\nthe `opensegment` event handler:\n\n```javascript\nvar table = require('edifact/messages/APERAK');\n\nvar parser = new Parser();\nvar tracker = new Tracker(table);\n\nparser.on('opensegment', function (segment) {\n  if (tracker.accept(segment)) doSomething(); // The segment matches.\n});\n\ntracker.on('error', function (segment) {\n  // Handle the error. Reject the message or ignore the segment.\n});\n```\n\nInvalid input will generally fall in one of the following categories:\n\n* A mandatory segment is skipped.\n* An invalid segment is provided in the input.\n* A segment is repeated too much.\n\nHowever, the `Tracker` instance cannot generally discern between those cases\nsince it will simply run through the segment table until a match is found. It\nwill as a consequence fail in one of the following ways:\n\n* The end of the segment table is reached.\n* The provided segment doesn't match a mandatory segment in the segment table.\n* If either of the above conditions results from a segment that exceeded its\nallowed number of repetitions, the `Tracker` instance will detect this and\ntrigger a more appropriate error.\n\nWhen such a situation is encountered, an `error` event will be fired. It is up\nto the user to handle the error. In the error handler, the current segment can\nbe accessed through `this.segment`. The current position in the segment table\ncan be retrieved through `this.pointer`.\n\nIf you want to build your own segment tables, please take a look in the\n`messages` folder to get the syntax right. Every segment in the segment table is\nof the following format:\n\n```json\n{ \"content\": \"UNH\", \"mandatory\": true, \"repetition\": 1 }\n```\n\nA segment group can be written as follows:\n\n```json\n{ \"content\": [\n  { \"content\": \"NAD\", \"mandatory\": true, \"repetition\": 1 },\n  { \"content\": \"CTA\", \"mandatory\": false, \"repetition\": 9 },\n  { \"content\": \"COM\", \"mandatory\": false, \"repetition\": 9 }\n], \"mandatory\": false, \"repetition\": 9 }\n```\n\n## Classes\n\n| Class | Description |\n| ----: | :---------- |\n| [Parser](#Parser) | The `Parser` class encapsulates an online parsing algorithm. By itself it doesn't do anything useful, however the parser can be extended through several event callbacks. |\n| [Reader](#Reader) | The `Reader` offers a fast an easy to use interface to convert EDIFACT messages to a JSON structure. |\n| [Tracker](#Tracker) | A utility class which validates segment order against a given message structure. |\n| [Validator](#Validator) | The `Validator` can be used as an add-on to the `Parser` class, to enable validation of segments, elements and components. This class implements a tolerant validator, only segments and elements for which definitions are provided will be validated. Other segments or elements will pass through untouched. Validation includes:\u003cul\u003e\u003cli\u003eChecking data element counts, including mandatory elements.\u003c/li\u003e\u003cli\u003eChecking component counts, including mandatory components.\u003c/li\u003e\u003cli\u003eChecking components against their required format.\u003c/li\u003e |\n| [Counter](#Counter) | The `Counter` class can be used as a validator for the `Parser` class. However it doesn't perform any validation, it only keeps track of segment, element and component counts. Component counts are reset when starting a new element, just like element counts are reset when closing the segment. |\n\n## Reference\n\n\u003ca name=\"Parser\"\u003e\u003c/a\u003e\n### Parser\n\nA parser capable of accepting data formatted as an UN/EDIFACT interchange. The\nconstructor accepts a `Validator` instance as an optional argument:\n\n```\nnew Parser([validator])\n```\n\n| Function | Description |\n| -------: | :---------- |\n| `configure(config)` | Configure any custom delimiters |\n| `encoding(level)` | Set one of the predefined encoding levels |\n| `on(event,callback)` | Add a listener for a specific event. The event can be any of `opensegment`, `element`, `component` and `closesegment` |\n| `write(chunk)` | Write a chunk of data to the parser |\n| `end()` | Terminate the EDI interchange |\n\n\u003ca name=\"Parser\"\u003e\u003c/a\u003e\n### Reader\n\nThe `Reader` offers a fast an easy to use interface to convert EDIFACT messages\nto a JSON structure. Furthermore, the `Reader` class can also autodetect the\nmessage encoding (this feature can be turned off by passing\n`autoDetectEncoding: false` as an option to the constructor).\n\n```\nnew Reader(options)\n```\n\n| Function | Description |\n| -------: | :---------- |\n| `parse(document)` | Parse a document and return the result as an array of segments. |\n| `define(definitions)` | Provide the underlying `Validator` instance with definitions. |\n\n\u003ca name=\"Tracker\"\u003e\u003c/a\u003e\n### Tracker\n\nA utility class which validates segment order against a given message\nstructure. The constructor accepts a segment table as it's first argument:\n\n```\nnew Tracker(table)\n```\n\n| Function | Description |\n| -------: | :---------- |\n| `accept(segment)` | Match a segment to the message structure and update the current position of the tracker |\n| `on(event,callback)` | Use this to add a listener for the `error` event |\n| `reset()` | Reset the tracker to the initial position of the current segment table |\n\n\u003ca name=\"Validator\"\u003e\u003c/a\u003e\n### Validator\n\nThe `Validator` can be used to validate segments, elements and components. It\nkeeps track of element and component counts and will ensure the correct data\nsyntax.\n\nNote that the `Validator` will not throw any errors though, since it only keeps\nthe `Parser` from consuming any invalid data. It will be the parser that throws\nthe error when it encounters data that it cannot consume.\n\n```\nnew Validator()\n```\n\n| Function | Description |\n| -------: | :---------- |\n| `disable()` | Disable validation |\n| `enable()` | Enable validation |\n| `define(definitions)` | Provision the validator with an array of segment and element definitions |\n| `onopensegment(segment)` | Start validation of a new segment |\n| `onelement()` | Add an element |\n| `onopencomponent(tokenizer)` | Open a component |\n| `onclosecomponent(tokenizer)` | Close a component |\n| `onclosesegment()` | Finish the segment |\n\nThe `tokenizer` argument to both `onopencomponent()` and `onclosecomponent()`\nshould provide three methods `alpha()`, `alphanumeric()`, and `numeric()`\nallowing the mode of the buffer to be set. It should also expose a `length`\nproperty to check the length of the data currently in the buffer.\n\n\u003ca name=\"Counter\"\u003e\u003c/a\u003e\n### Counter\n\nThe `Counter` class implements the same interface as `the `Validator` class and\ncan also be used as a validator when constructing a new `Parser` instance.\nHowever it doesn't perform any validation. It only keeps track of segment,\nelement and component counts. Component counts are reset when starting a new\nelement, just like element counts are reset when closing the segment.\n\n```\nnew Counter()\n```\n\n| Function | Description |\n| -------: | :---------- |\n| `onopensegment()` | Start a new segment |\n| `onelement()` | Add an element |\n| `onopencomponent()` | Open a component |\n| `onclosecomponent()` | Close a component |\n| `onclosesegment()` | Finish the segment |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftdecaluwe%2Fnode-edifact","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftdecaluwe%2Fnode-edifact","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftdecaluwe%2Fnode-edifact/lists"}