Skip to content

API reference

Everything is exported from the package root. Types are exported alongside every schema.

import { assembleBundle, validateBundle, type OursBundle } from "@openhi/ours";
const WELL_KNOWN_ONTOLOGY_PATH: "/.well-known/ours.json";
function wellKnownOntologyUrl(origin: string): string;

Where to look for an ontology, given only a domain. Accepts a bare host, an origin, or any URL on the right host. A host with no scheme is assumed to be https, because a discovery request that silently downgrades is worse than one that fails. Throws on input it cannot make a URL from.

wellKnownOntologyUrl("example.org");
// "https://example.org/.well-known/ours.json"
function assembleBundle(input: BundleInput): OursBundle;

Assembles a bundle from documents already fetched or read. Throws on a duplicate model or vocabulary url, on a JSON Schema with no $id, on a duplicate $id, and on a schema whose $id collides with one derived from a vocabulary. Every vocabulary’s derived schema is added to schemas automatically.

interface BundleInput {
readonly ontology: OursDocument;
readonly models?: ReadonlyArray<OursDocument>;
readonly vocabularies?: ReadonlyArray<OursDocument>;
/** JSON Schema documents, each carrying its own `$id`. */
readonly schemas?: ReadonlyArray<JsonSchema>;
}
interface OursBundle {
readonly ontology: Ontology;
readonly models: ReadonlyMap<string, Model>;
readonly vocabularies: ReadonlyMap<string, Vocabulary>;
readonly schemas: ReadonlyMap<string, JsonSchema>;
}
/** A document as it arrives, before anyone knows what is in it. */
type OursDocument = unknown;
function resourcesIn(document: OursDocument): OursResource[];

Unwraps a document that may be a single resource or a collection Bundle.

function parseResource(document: OursDocument): OursResource;

Parses one OURS resource, whatever kind it is. Throws if resourceType is not one of the three.

function emptyBundle(): Bundle;

An empty collection, for a publisher who has none of something.

function toPublishedBundles(bundle: OursBundle): { models: Bundle; vocabularies: Bundle };

Renders a bundle back into the collection Bundles a publisher serves.

function vocabularySchemaUrl(vocabulary: Pick<Vocabulary, "url">): string;

Where a vocabulary’s JSON Schema lives: beside it, with .schema.json in place of .json.

function vocabularySchemaFor(vocabulary: Vocabulary): JsonSchema;

A vocabulary as a JSON Schema: a string that is one of its codes, each carrying its display text as a title. A vocabulary with no codes yields a bare type: "string".

function validateBundle(bundle: OursBundle, options?: ValidateOptions): ValidationIssue[];
function hasErrors(issues: ReadonlyArray<ValidationIssue>): boolean;

See Validating a bundle for what is checked.

interface ValidationIssue {
readonly level: "error" | "warning";
readonly resource: string;
readonly message: string;
}
interface ValidateOptions {
readonly warnOnMissingMapsTo?: boolean;
}
function walkSchema(schema: JsonSchema, visit: (node: JsonSchema) => void): void;

Visits every subschema, including those inside allOf, anyOf, oneOf, items, additionalProperties and $defs.

function refsIn(schema: JsonSchema): string[];

Every $ref in a schema, at any depth.

function resolveRef(baseId: string, target: string): string;

Resolves a $ref target against the $id of the schema that made it, per RFC 3986. A relative base resolves as an absolute one would. A network-path reference (//host/path) is returned unchanged against a base with no scheme, because there is none to lend it.

A $ref resolves against the $id in scope where it was written, not against the document it sits in, so resolving one correctly means knowing its scope. These three produce what resolveRef needs.

function walkSchemaInScope(
schema: JsonSchema,
base: string,
visit: (node: JsonSchema, base: string) => void,
): void;

Like walkSchema, but each node arrives with the base URI it resolves against. A nested $id opens a new scope for everything beneath it, resolved against the scope it was found in. base is the URI the schema is already known by, so the root’s own $id is not applied to itself.

function scopedRefsIn(
schema: JsonSchema,
baseId: string,
): Array<{ ref: string; base: string }>;

Every $ref, paired with the base URI in scope where it appeared. Feed each pair to resolveRef.

function declaredIds(schema: JsonSchema, baseId: string): string[];

Every $id the schema declares, resolved, embedded ones included. This is the set of addresses a validator loading the document registers, which is what a resolved reference has to land on.

const refs = scopedRefsIn(schema, schema.$id).map(({ ref, base }) =>
resolveRef(base, ref),
);
const targets = new Set(declaredIds(schema, schema.$id));

See Schemas for the rules these follow and why resolving against the document instead is wrong in both directions.

Each is a zod schema with a type of the same name, minus the Schema suffix. ontologySchema has type Ontology, and so on.

Export Type
ontologySchema Ontology The root resource.
modelSchema Model A model.
vocabularySchema Vocabulary A vocabulary.
bundleSchema Bundle A collection bundle.
oursResourceSchema OursResource The three resources, discriminated on resourceType.
oursResourceBaseSchema The fields every resource carries.
mapsToSchema MapsTo An alignment.
mapsToTypeSchema MapsToType one-to-one, one-to-many, many-to-one or partial.
relationshipSchema Relationship A named link between models.
validTimeFieldsSchema ValidTimeFields Which properties carry valid time.
codeSchema Code One code in a vocabulary.

JsonSchema and JsonSchemaType are exported as types only. They describe the permitted subset as an interface rather than a zod schema, because a model’s schema is validated by an ordinary JSON Schema validator rather than by this package.