Skip to content

edi://

Producer that parses EDI (and the other formats omniparser understands — CSV, fixed-length, XML, JSON) into JSON, and generates ANSI X12 interchanges from a structured payload.

Parsing is powered by omniparser, a native-Go streaming ETL engine driven by a JSON schema (schema version omni.2.1). omniparser handles things a naive split-on-delimiter parser cannot: hierarchical segment groups / loops, component / repetition delimiters, release / escape characters, occurrence validation, and field-level transforms via XPath + custom funcs. When no schema is supplied the component falls back to a schemaless structural parse (segment / element split) for quick inspection.

Generation produces an X12 interchange (ISA / GS / ST … SE / GE / IEA) from a structured payload. omniparser is parse-only, so this path is hand-rolled.

Producer-only — CreateConsumer returns ErrConsumerNotSupported.

URI shape

edi://<name>?op=parse&schema=schemas/x12_214.json
edi://<name>?op=parse&dialect=edifact                     # schemaless structural parse
edi://<name>?op=generate&senderId=ME&receiverId=YOU&version=00501

The <name> segment is a logical label (used in caching + logs). It doesn't need to match any external identifier.

Parameters

Param Type Default Producer/Consumer/Both Description
op enum parse Producer parse (EDI → JSON via omniparser) or generate (structured payload → X12 interchange).
schema string — Producer Path to an omniparser JSON schema. Drives op=parse. Mutually exclusive with schemaInline.
schemaInline string — Producer Inline omniparser JSON schema (URL-encoded).
dialect enum x12 Producer Delimiter preset for schemaless parsing and X12 generation: x12 or edifact.
skipErrors boolean false Producer On op=parse, skip records that fail transform (continuable errors). Count surfaces in the edi.error_count header.
unwrap boolean false Producer On op=parse, if exactly one record is produced, set the body to that object rather than a one-element array.
senderId string — Producer op=generate: ISA06 / GS02.
receiverId string — Producer op=generate: ISA08 / GS03.
version string 00501 Producer op=generate: X12 version. ISA12 uses the first 5 chars; GS08 is padded to 6 (00501 → 005010).
functionalId string PO Producer op=generate: GS01 functional identifier code (PO, SH, IN, QM, ...).
usageIndicator enum P Producer op=generate: ISA15. P=production, T=test.
elementSeparator string dialect default Producer Override element separator (x12 *, edifact +).
segmentTerminator string dialect default Producer Override segment terminator (x12 ~, edifact ').
componentSeparator string : Producer Override component separator.
repetitionSeparator string U Producer op=generate: ISA11 value.

Schema source resolution (op=parse)

  1. URI param schema=<file path>
  2. URI param schemaInline=<raw JSON> (URL-encoded)
  3. Exchange header edi.schema (inline JSON)
  4. Exchange header edi.schemaPath (file path)
  5. None → schemaless structural parse

Headers

Header Direction Description
edi.schema Read Inline omniparser schema (per-exchange override).
edi.schemaPath Read File path to omniparser schema.
edi.engine Written omniparser (schema-driven) or structural (schemaless fallback).
edi.operation Written parse or generate.
edi.record_count Written parse — record count.
edi.error_count Written parse — count of skipped per-record errors (when skipErrors=true).
edi.segment_count Written parse (structural only) — number of segments.
edi.transaction_set Written generate — transaction set id (e.g. 850).
edi.control_number Written generate — ISA13 control number.
Content-Type Written application/json (parse) or application/edi-x12 (generate).

Examples

Schema-driven parse:

workflows:
  - id: x12-214-parse
    trigger:
      uri: file:///inbound/?include=.*\.edi$&move=processed
    steps:
      - target: edi://x12-214?op=parse&schema=schemas/x12_214.json&unwrap=true
      - target: direct://route-shipment-status

Schemaless inspection of an EDIFACT file:

- target: edi://inspect?op=parse&dialect=edifact
- log: { message: "got an EDIFACT interchange", level: INFO }

Generate an X12 850 (purchase order):

- set-body:
    starlang: |
      %sl 2.0
      output application/json
      input payload
      ---
      {
        "transaction_set": "850",
        "segments": [
          { "segment_id": "BEG", "elements": ["00", "SA", payload.po, "", payload.date] },
          { "segment_id": "REF", "elements": ["DP", payload.dept] },
          { "segment_id": "PER", "elements": ["BD", payload.contact] }
        ]
      }
- target: edi://orders-out?op=generate&senderId=ACME&receiverId=VENDOR&version=00501&functionalId=PO

Use a schema chosen at runtime via header:

- set-header:
    name: edi.schemaPath
    starlang: 'lookup_schema(header("Content-Type"))'
- target: edi://parse-any?op=parse

Behavior notes

  • Schema caching — omniparser.Schema is thread-safe and reusable; the endpoint caches one schema per unique schema content (schemaMu + schemaCache).
  • Schemaless fallback delimiters — driven by dialect. If the configured terminator isn't found in the input, the parser falls back to newline splitting (common in samples).
  • Continuable errors — only per-record ErrTransformFailed is skipped when skipErrors=true; everything else aborts immediately (otherwise the loop would repeat forever on a fatal input issue).
  • Generation is hand-rolled — omniparser doesn't generate. The X12 builder emits ISA / GS / ST → body segments → SE / GE / IEA, with \n after each ~-terminated segment for readability. Customise via elementSeparator / segmentTerminator overrides.
  • unwrap is a per-exchange convenience for upstream steps that expect a single object rather than a one-element array.

Source

pkg/component/edi/edi.go, pkg/component/edi/starlang_func.go (Helix-bridge omniparser extension exposing starlang as a custom_func).

See also