Node.js API

Install

npm install @imferno/node

Native bindings via NAPI. Provides filesystem access for path-based validation. All functions are synchronous.


validate / validatePath / validateUri

Parse and validate an IMF package in one call. This is the recommended entry point.

  • validatePath reads XML files from a local directory.
  • validateUri accepts a file:// URI, a bare path, or an s3://bucket/prefix/ URI (the prebuilt npm binary ships with S3 support enabled).
  • validate takes a filename-to-string map (no filesystem access).
import { validatePath, validateUri, formatReport } from '@imferno/node';

// Local FS path
const result = validatePath('./my-imp');

// URI form (filesystem or, with aws-s3, S3)
const result2 = validateUri('s3://my-bucket/path/to/imp/');

// Full parsed package
console.log(result.package.compositionPlaylists);

// Validation results
if (!result.validation.is_compliant) {
  for (const err of result.validation.errors) {
    console.error(err.code, err.message);
  }
}

// Pretty-print the validation report
console.log(formatReport(result));

From string content (no filesystem access):

import { validate } from '@imferno/node';

const result = validate({
  'VOLINDEX.xml': volindexXml,
  'ASSETMAP.xml': assetmapXml,
  'PKL.xml': pklXml,
  'CPL.xml': cplXml,
});

S3 input

validateUri and buildReportFromUri accept s3://bucket/prefix/ URIs out of the box. The prebuilt @imferno/node binaries on npm include the aws-s3 feature for every supported platform — no rebuild required.

S3Storage uses the default AWS credential chain:

  1. AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN env
  2. ~/.aws/credentials profile (set AWS_PROFILE to pick one)
  3. EC2 / ECS / EKS instance metadata service (IMDSv2)

Region resolution follows the standard AWS resolution order (AWS_REGION env → profile config → IMDS).

For S3-compatible endpoints (MinIO, R2, etc.), set:

AWS_ENDPOINT_URL_S3=https://my-r2-endpoint.example.com
AWS_REGION=auto

Only the IMF manifest XMLs (ASSETMAP.xml, PKL_*.xml, CPL_*.xml, VOLINDEX.xml, etc.) are fetched over the network. MXF essence files are not downloaded.

Options

const result = validatePath('./my-imp', {
  coreSpec: 'v2020',
  app2eSpec: 'v2023',
  skipDiskChecks: false,
  rules: {
    'ST2067-21:2023:7.1/AppIdMismatch': 'error',
    'IMFERNO:Package/UnreferencedAsset': 'off',
  },
});
OptionTypeDefaultDescription
coreSpec"auto" | "v2013" | "v2016" | "v2020""auto"Core constraints spec version
app2eSpec"auto" | "none" | "v2020" | "v2021" | "v2023""auto"Application profile version
skipDiskChecksbooleanfalseSkip file existence/size and MXF header checks
rulesRecord<string, string>{}ESLint-style severity overrides

parsePackage / parsePackageFromPath

Parse an IMF package without running validation. Returns the full Imferno struct.

import { parsePackageFromPath } from '@imferno/node';

const pkg = parsePackageFromPath('./my-imp');
console.log(pkg.compositionPlaylists);
console.log(pkg.packingLists);
console.log(pkg.assetMap);

From string content:

import { parsePackage } from '@imferno/node';

const pkg = parsePackage({
  'VOLINDEX.xml': volindexXml,
  'ASSETMAP.xml': assetmapXml,
  'PKL.xml': pklXml,
  'CPL.xml': cplXml,
});

buildReport / buildReportFromPath / buildReportFromUri (legacy)

Returns an ImfReport summary. Kept for backwards compatibility — prefer validate() / validatePath() / validateUri() instead.

import { buildReportFromPath, buildReportFromUri, formatReport } from '@imferno/node';

const report  = buildReportFromPath('./my-imp');
const report2 = buildReportFromUri('s3://my-bucket/path/to/imp/');
console.log(formatReport(report));

From string content:

import { buildReport } from '@imferno/node';

const report = buildReport({
  'ASSETMAP.xml': assetmapXml,
  'PKL.xml': pklXml,
  'CPL.xml': cplXml,
});

Accepts the same options as validatePath / validate.


formatReport

Pretty-print a ValidationResult or ImfReport as a human-readable string. Same output as imferno validate on the CLI.

import { validatePath, formatReport } from '@imferno/node';

const result = validatePath('./my-imp');
console.log(formatReport(result));

getVersion

import { getVersion } from '@imferno/node';
console.log(getVersion()); // "2.0.0"

codes

Typed validation code constants for use in rules config. Provides autocomplete and typo protection.

import { codes } from '@imferno/node';

codes.ST2067_2_2020.FileNotFound    // "ST2067-2:2020:8.3/FileNotFound"
codes.ST2067_21_2023.FrameRate      // "ST2067-21:2023:5.2/FrameRate"
codes.ST2067_201_2021.MCATagSymbolInvalid  // ...

See Configuration for how to use codes with rules.


ValidationResult

validate() and validatePath() return this structure:

interface ValidationResult {
  package: Imferno;      // full parsed package
  validation: {          // ValidationReport
    critical: ValidationIssue[];
    errors: ValidationIssue[];
    warnings: ValidationIssue[];
    info: ValidationIssue[];
    is_playable: boolean;
    is_compliant: boolean;
    profile: string;
    timestamp: string;
  };
}

The Imferno type contains compositionPlaylists, packingLists, assetMap, and other parsed IMF package data.


ImfReport (legacy)

buildReport() and buildReportFromPath() return this structure. For new code, prefer ValidationResult from validate().

interface ImfReport {
  package: {
    assetMapId: string;
    volumeIndex: number;
    assetCount: number;
    cplCount: number;
    issueDate: string;
    issuer: string | null;
    creator: string | null;
    pklCount: number;
    scmCount: number;
    sidecarCount: number;
    unreferencedAssets: { id: string; path: string }[];
  };
  cpls: {
    id: string;
    title: string;
    editRate: string;
    sequences: string[];
    applicationProfile: string | null;
    segmentCount: number;
    timecodeStart: string | null;
    isSupplemental: boolean;
    unresolvedAncestorAssetIds: string[];
    markers: { label: string; offset: number; annotation: string | null }[];
  }[];
  validation: {
    critical: ValidationIssue[];
    errors: ValidationIssue[];
    warnings: ValidationIssue[];
    info: ValidationIssue[];
    is_playable: boolean;
    is_compliant: boolean;
    profile: string;
    timestamp: string;
  };
}