Skip to content

@statista/avro-js-adapter

Type-safe validation for Mercury Event-Bus Avro schemas.

Installation

Configure GitHub Package Registry in .npmrc:

@statista:registry=https://npm.pkg.github.com

Then install:

pnpm add @statista/avro-js-adapter

Requires Node.js 20, 22, or 24.

Quick start

import { validateEvent, validatePayload } from "@statista/avro-js-adapter";
import type { CreateData } from "@statista/avro-js-adapter/registration/enrichment/user_data/v1";

// Validate a full event
validateEvent(event);

// Validate a payload
const payload = {
  legacy_user_id: "user-123",
  company: "Statista",
  industry_id: null,
  industry: null,
  company_size: null,
  department: null,
  phone_number: null,
  role: null,
  job_title: null,
  country_iso_code: null,
} satisfies CreateData;

validatePayload(
  "com.statista.events.registration.enrichment.user_data.v1.create_data",
  payload,
);

Importing types

Shared types are exported from the package root:

import type {
  MercuryEvent,
  EventHeader,
  Metadata,
  SchemaName,
  PayloadSchemaName,
} from "@statista/avro-js-adapter";

Payload types are scoped by topic via subpath imports:

import type { CreateData } from "@statista/avro-js-adapter/registration/enrichment/user_data/v1";

The subpath pattern follows the schema directory layout: @statista/avro-js-adapter/<domain>/<entity>/<entity-class>/<version>.

Validating events

Full event

import { validateEvent, type MercuryEvent } from "@statista/avro-js-adapter";

const event: MercuryEvent = {
  event_header: {
    event_id: "550e8400-e29b-41d4-a716-446655440000",
    event: "user_enrichment",
    app_id: "webapp",
    env: "dev",
    region: "eu-central-1",
    sender: "registration-service",
    domain: "registration",
    entity: "signup",
    event_class: "register",
    parent_event_id: null,
    request_id: null,
    statista_tracking_uuid: null,
    timestamp: 1700000000000,
  },
  metadata: {
    source: "backend",
    schema_version: "1.0.0",
  },
  payload: {
    legacy_user_id: "user-123",
    industry_id: null,
    industry: null,
    company: null,
    company_size: null,
    department: null,
    phone_number: null,
    role: null,
    job_title: null,
    country_iso_code: null,
  },
};

validateEvent(event);

Payload only

import { validatePayload } from "@statista/avro-js-adapter";
import type { CreateData } from "@statista/avro-js-adapter/registration/enrichment/user_data/v1";

const payload = {
  legacy_user_id: "user-123",
  company: "Statista",
  industry_id: null,
  industry: null,
  company_size: null,
  department: null,
  phone_number: null,
  role: null,
  job_title: null,
  country_iso_code: null,
} satisfies CreateData;

validatePayload(
  "com.statista.events.registration.enrichment.user_data.v1.create_data",
  payload,
);

Handling errors

Both functions return true on success and throw on invalid data:

try {
  validateEvent(badData);
} catch (error) {
  console.error(error.message);
  // Schema validation errors for com.statista.events.MercuryEvent:
  // Validation failed at 'event_header.timestamp': expected type long, but got value 'not-a-number'
}

Available schemas

Schema name Type Import
com.statista.events.MercuryEvent Event @statista/avro-js-adapter
com.statista.events.common.EventHeader Shared @statista/avro-js-adapter
com.statista.events.common.Metadata Shared @statista/avro-js-adapter
com.statista.events.registration.enrichment.user_data.v1.create_data Payload @statista/avro-js-adapter/registration/enrichment/user_data/v1

Adding a new schema

  1. Create schemas/<domain>/<entity>/<entity-class>/v1/<event_name>.avsc
  2. Add the fully-qualified type name to the payload union in schemas/mercury_event.avsc
  3. Run pnpm build — types and validation are generated automatically