npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

rescript-eventor

v0.2.0

Published

Typed Eventor REST API client for ReScript

Downloads

589

Readme

rescript-eventor

npm license

Typed Eventor REST API client for ReScript. Returns either native ReScript record types or parsed IOF XML 3.0 types via rescript-iof-xml.

References:

Installation

rescript-iof-xml is a required peer-style runtime dependency and is installed alongside:

npm install --save-exact rescript-eventor rescript-iof-xml

Add both to rescript.json:

{
  "dependencies": ["rescript-eventor", "rescript-iof-xml"]
}

Usage

let config = Eventor.makeConfig(~apiKey="your-api-key", ())

let result = await Eventor.getEvents(
  config,
  {
    ...Eventor.eventsParams,
    fromDate: Some(Date.makeWithYMD(~year=2024, ~month=0, ~date=1)),
    toDate: Some(Date.makeWithYMD(~year=2024, ~month=11, ~date=31)),
    classificationIds: Some([
      EventClassificationFilter.National,
      EventClassificationFilter.Regional,
    ]),
  },
)

switch result {
| Ok(events) => Console.log(events)
| Error(msg) => Console.error(msg)
}

Eventor.eventsParams and Eventor.entriesParams are pre-built records with every field set to its zero value (None / false), so you only need to spell out the fields you care about.

TypeScript

The package provides a public rescript-eventor/Eventor entry point with TypeScript declarations and object-based options.

import {
  EventClassificationFilter,
  getEvents,
  makeConfig,
} from "rescript-eventor/Eventor";

const config = makeConfig({ apiKey: "your-api-key" });
const result = await getEvents(config, {
  fromDate: new Date("2026-01-01"),
  classificationIds: [EventClassificationFilter.National],
});

if (result.TAG === "Ok") {
  console.log(result._0);
} else {
  console.error(result._0);
}

Browsers provide DOMParser natively.

Node.js consumers must install a DOMParser-compatible implementation on globalThis.DOMParser before calling an endpoint, as described by rescript-iof-xml.

API

All endpoint functions return promise<result<'a, string>>. The Error payload is either an HTTP <status>: <statusText> string or a network error message.

| Function | Returns | Notes | | --- | --- | --- | | Eventor.makeConfig(~apiKey, ~baseUrl=?, ()) | config | baseUrl defaults to the Norwegian Eventor. | | Eventor.getEvents(config, params) | array<NativeEvent.t> | See eventsParams below. | | Eventor.getEvent(config, ~eventId, ()) | NativeEvent.t | | | Eventor.getEntries(config, params) | array<NativeEntry.t> | See entriesParams below. | | Eventor.getCompetitors(config, ~organisationId, ()) | array<NativeCompetitor.t> | | | Eventor.getOrganisations(config, ~includeProperties=?, ()) | array<NativeOrganisation.t> | | | Eventor.getEventClasses(config, ~eventId, ()) | array<NativeEventClass.t> | | | Eventor.getPersons(config, ~organisationId, ~includeContactDetails=?, ~includePersonProperties=?, ~includePersonIdentifiers=?, ()) | array<NativePerson.t> | | | Eventor.getStarts(config, ~eventId, ()) | IofXml.StartList.t | Parsed IOF XML 3.0. | | Eventor.getResults(config, ~eventId, ~includeSplitTimes=?, ()) | IofXml.ResultList.t | Parsed IOF XML 3.0. |

eventsParams

| Field | Type | Description | | --- | --- | --- | | fromDate / toDate | option<Date.t> | Date range filter (formatted as local time). | | fromModifyDate / toModifyDate | option<Date.t> | Modification date range filter. | | eventIds | option<array<string>> | Filter by specific event IDs. | | organisationIds | option<array<string>> | Filter by organiser organisation IDs. | | classificationIds | option<array<EventClassificationFilter.t>> | Filter by classification level. International events cannot be selected because Eventor rejects classification ID 0 as a filter. | | includeEntryBreaks | bool | Include entry deadline info. | | includeAttributes | bool | Include event attributes. | | parentIds | option<array<string>> | Filter by parent event IDs. |

entriesParams

| Field | Type | Description | | --- | --- | --- | | organisationIds | option<array<string>> | Filter by organisation IDs. | | eventIds | option<array<string>> | Filter by event IDs. | | eventClassIds | option<array<string>> | Filter by event class IDs. | | fromEventDate / toEventDate | option<Date.t> | Event date range filter. | | fromEntryDate / toEntryDate | option<Date.t> | Entry creation date filter. | | fromModifyDate / toModifyDate | option<Date.t> | Modification date filter. | | includePersonElement | bool | Embed the full <Person> element under each <Competitor> (name, birth date, sex, nationality). When set, NativeEntry.t.person is populated. | | includeOrganisationElement | bool | Embed the full <Organisation> element under each <Competitor> (name, short name, country). When set, NativeEntry.t.organisation is populated. | | includeEventElement | bool | Embed the full <Event> element under each <Entry> (name, dates, classification, races). When set, NativeEntry.t.event is populated. |

EventClassification.t

A variant type representing event classification levels returned by Eventor:

type t = International | Championship | National | Regional | Nearby | Club

It is available on parsed events via NativeEvent.t.classification.

EventClassificationFilter.t

A variant type representing the classification levels accepted by Eventor's /events filter:

type t = Championship | National | Regional | Nearby | Club

Use it in event queries:

classificationIds: Some([
  EventClassificationFilter.National,
  EventClassificationFilter.Regional,
])

International events use classification ID 0 in responses, but Eventor rejects classificationIds=0, so International intentionally is not a filter variant.

IOF XML 3.0 variants

Eventor also exposes IOF XML 3.0 variants of several endpoints. Eventor-specific data is preserved in <Extensions> elements under the namespace http://eventor.orientering.se/iofxmlextensions (e.g. EventRaceId, StartListExists, Discipline, LightCondition), so these endpoints are non-lossy.

  • Eventor.getEventsIofXml(config, params) / getEventsIofXmlRaw — /events/iofxml
  • Eventor.getEventIofXml(config, ~eventId, ()) / getEventIofXmlRaw — /event/iofxml/{id}
  • Eventor.getOrganisationsIofXmlRaw(config, ~includeProperties=?, ()) — /organisations/iofxml
  • Eventor.getStartsIofXml(config, ~eventId, ~eventRaceId=?, ()) / getStartsIofXmlRaw — /starts/event/iofxml
  • Eventor.getResultsIofXml(config, ~eventId, ~eventRaceId=?, ~includeSplitTimes=?, ~totalResult=?, ()) / getResultsIofXmlRaw — /results/event/iofxml

The typed variants return the IOF-standard fields only and do not carry the Eventor extensions. To read the extensions, take a *Raw variant's XML and pass each <Event>/<Race> element to IofXml.EventorExtensions.fromElement (added in rescript-iof-xml v0.0.4).

Base URLs

  • Norway (default): https://eventor.orientering.no/api
  • Sweden: https://eventor.orientering.se/api
  • Australia: https://eventor.orienteering.asn.au/api
  • International: https://eventor.orienteering.sport/api

Pass via ~baseUrl to makeConfig.

Not yet implemented

The following Eventor API endpoints are not yet wrapped by this library:

| Endpoint | Description | | --- | --- | | GET /authenticatePerson | Authenticate a person by username/password. | | GET /activities | List activities for an organisation in a time period. | | GET /activity | Get a single activity. | | GET /externalLoginUrl | Generate a single-use redirect URL into Eventor. | | PUT /competitor | Update a competitor's settings (card, default class). |

Additionally, some existing endpoints expose parameters not yet supported:

| Endpoint | Missing parameters | | --- | --- | | GET /entries | includeEntryFees | | GET /results/event | top | | GET /eventclasses | includeEntryFees |

CORS limitation

The Eventor API does not provide CORS headers, so direct browser requests will be blocked. This library works as intended in:

  • Server-side environments (Node.js, Deno, Bun)
  • Desktop apps (Tauri, Electron)
  • Browser via a CORS proxy you control

Development

npm install
npm run build       # one-shot compile
npm run dev         # watch mode
npm test            # runtime tests against fixtures in example-responses/
npm run test:package # verify the packed TypeScript/Node.js consumer surface
npm run format      # rescript format

npm run build generates src/Eventor.js and src/Eventor.d.ts from the committed src/Eventor.ts facade, so JavaScript behavior and TypeScript declarations stay in sync.

License

MIT — see LICENSE.