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

@semiont/core

v0.5.13

Published

Core types and domain logic for Semiont - Resource, Annotation, and Graph models

Downloads

2,685

Readme

@semiont/core

Tests codecov npm version npm downloads License

Core types and domain logic for the Semiont semantic knowledge platform. This package is the source of truth for OpenAPI types and provides the shared domain layer: event-sourcing types, the EventBus, the transport contract, W3C Web Annotation utilities, anchoring, DIDs, and configuration loading.

Architecture Note: This package generates TypeScript types from the OpenAPI specification. Every other package in the monorepo imports them from here.

Who Should Use This

  • Backend (apps/backend) - Server implementation, imports types from core
  • Packages - Other monorepo packages that need OpenAPI types, the EventBus, or the transport contract
  • Frontend / Browser - Types and pure utilities (the main barrel is browser-safe)

Who Should Use @semiont/core/node Instead

Node.js-specific exports live in the /node subpath:

import { SemiontProject, loadEnvironmentConfig } from '@semiont/core/node';
  • SemiontProject — represents a project on the filesystem; resolves XDG directories, reads/writes files. Not usable in a browser.
  • loadEnvironmentConfig — loads ~/.semiontconfig + .semiont/config using fs/os/path. Not usable in a browser.

Rule: If your code runs in a browser or edge runtime, use @semiont/core. If it runs in Node.js and needs filesystem access, use @semiont/core/node.

Who Should Use @semiont/sdk Instead

Application code talking to a Semiont backend should use @semiont/sdk, which provides SemiontClient, the verb-oriented namespaces, and the session layer. The SDK consumes the ITransport / IContentTransport contracts defined here; the HTTP implementations of those contracts live in @semiont/http-transport and are re-exported by the SDK for convenience.

Rule of thumb: If you are making API calls, use @semiont/sdk. If you only need types and domain logic, use @semiont/core. Import from @semiont/http-transport directly only when constructing a transport stack by hand.

Installation

Install the latest stable release from npm:

npm install @semiont/core

Or install the latest development build:

npm install @semiont/core@dev

What's Included

OpenAPI Types (Generated)

TypeScript types generated from the OpenAPI specification - the source of truth for all API schemas:

import type { components, paths, operations } from '@semiont/core';

type Annotation = components['schemas']['Annotation'];
type Resource = components['schemas']['Resource'];
type CreateResourceRequest = components['schemas']['CreateResourceRequest'];

These types are generated during the build process:

npm run generate:openapi  # Bundles spec → generates types.ts

Branded Types

Compile-time type safety for URIs, tokens, and identifiers:

import { resourceUri, annotationUri, accessToken, entityType } from '@semiont/core';

const rUri = resourceUri('http://localhost:4000/resources/doc-123');
const token = accessToken('eyJhbGc...');
const eType = entityType('Person');

Branded ID types (ResourceId, AnnotationId, UserId) with factories and guards (resourceId, annotationId, userId, isResourceId, isAnnotationId) live alongside the URI brands.

Event Sourcing Types

The persisted event catalog — every event type written to the JSONL event log, discriminated on type and namespaced by concern (yield:* resource lifecycle, mark:* annotations and tags, frame:* schema registration, job:* job lifecycle):

import type {
  PersistedEvent,
  PersistedEventType,
  EventOfType,
  EventInput,
  StoredEvent,
  EventMetadata,
  BodyOperation,
  ResourceAnnotations,
} from '@semiont/core';
import { PERSISTED_EVENT_TYPES } from '@semiont/core';

function handle(event: PersistedEvent) {
  if (event.type === 'mark:added') {
    // payload is narrowed to the AnnotationAdded payload
  }
}

PERSISTED_EVENT_TYPES is the runtime list of every persisted event type, with a compile-time exhaustiveness check against the catalog.

EventBus

The RxJS-based event bus shared by backend and clients, with a typed channel protocol:

import { EventBus, ScopedEventBus, burstBuffer, serializePerKey } from '@semiont/core';
import type { EventMap, EventName } from '@semiont/core';
  • EventBus / ScopedEventBus — framework-agnostic pub/sub over the unified EventMap
  • CHANNEL_SCHEMAS — maps each channel to its OpenAPI payload schema
  • burstBuffer — RxJS operator for coalescing event bursts
  • serializePerKey — per-key serialization for RPC-style callers
  • busLog / setBusLogTraceIdProvider — cross-wire bus observability

Transport Contract

The interfaces every concrete transport must satisfy, plus the channel set transports bridge into a client's bus:

import type { ITransport, IContentTransport, IBackendOperations, ConnectionState } from '@semiont/core';
import { BRIDGED_CHANNELS } from '@semiont/core';

@semiont/http-transport implements these over HTTP + SSE; LocalTransport in @semiont/make-meaning implements them in-process.

W3C Web Annotation Utilities

Pure functions for building and reading W3C Annotations:

import {
  assembleAnnotation,
  applyBodyOperations,
  getBodySource,
  getTargetSelector,
  getExactText,
  isHighlight,
  isReference,
  isComment,
} from '@semiont/core';

Selector helpers cover text position, text quote, SVG, and PDF-viewrect fragment selectors (getTextPositionSelector, getSvgSelector, createFragmentSelector, parseSvgSelector, …).

Annotation body matcher

findBodyItem locates a body item in an annotation body by identity (type + source for SpecificResource, type + value for TextualBody). Used by the mark:body-updated event replay path to apply add / remove / replace operations.

import { findBodyItem, type BodyItemIdentity } from '@semiont/core';

// Loose match: any body item with this source, regardless of purpose.
// This is the common case for Semiont's bind/unbind flow.
const index = findBodyItem(annotation.body, {
  type: 'SpecificResource',
  source: 'https://example.com/target',
});

// Strict match: disambiguate among same-source bodies under different
// purposes. Needed when an annotation has multiple SpecificResource bodies
// pointing at the same target under different W3C purposes.
const linkingIdx = findBodyItem(annotation.body, {
  type: 'SpecificResource',
  source: 'https://example.com/target',
  purpose: 'linking',
});

purpose is optional in the identity. Omit it to match on identity alone; provide it when the caller knows which purpose to target.

Anchoring

Re-anchor annotations after content edits — fuzzy text matching plus a render-time strategy that combines position and quote selectors with confidence scoring:

import {
  anchorAnnotation,
  normalizeText,
  buildContentCache,
  findBestTextMatch,
} from '@semiont/core';

DID Utilities

Generate and parse W3C Decentralized Identifiers for humans and software peers:

import { userToDid, userToAgent, agentToDid, softwareToAgent, didToAgent } from '@semiont/core';

userToDid({ email: '[email protected]', domain: 'example.com' });
// => 'did:web:example.com:users:alice%40example.com'

userToAgent({ id: 'u1', domain: 'example.com', name: 'Alice', email: '[email protected]' });
// => { '@type': 'Person', '@id': 'did:web:example.com:users:alice%40example.com', name: 'Alice' }

didToAgent('did:web:example.com:agents:ollama:gemma2%3A27b');
// => { '@type': 'Software', '@id': ..., name: 'ollama gemma2:27b', provider: 'ollama', model: 'gemma2:27b' }

Error Classes

In-process error types, sharing the TransportErrorCode vocabulary with the transport-specific classes (APIError lives in @semiont/http-transport):

import {
  SemiontError,
  ValidationError,
  ScriptError,
  NotFoundError,
  UnauthorizedError,
  ConflictError,
} from '@semiont/core';

throw new NotFoundError('Resource not found');

Type Guards & Validation

import { isString, isObject, isArray, isDefined, validateData, isValidEmail } from '@semiont/core';

if (isDefined(value)) {
  // TypeScript knows value is T, not T | null | undefined
}

Resource & Misc Utilities

  • ResourceDescriptor accessorsgetResourceId, getPrimaryRepresentation, getChecksum, isArchived, decodeRepresentation, …
  • LocalesLOCALES, getLocaleInfo, formatLocaleDisplay, …
  • Media typesMEDIA_TYPES capability registry keyed by the spec's SupportedMediaType enum (render / anchoring / text-extraction / authorable per type), with capabilitiesOf, textExtractionOf, mediaTypeForExtension, baseMediaType, …
  • Text encodingextractCharset, decodeWithCharset
  • Text contextextractContext, reconcileSelector
  • SVGcreateRectangleSvg, parseSvgSelector, scaleSvgToNative, …
  • IDsgenerateUuid

Configuration

Schema-generated configuration types plus loaders:

import { loadTomlConfig, parseEnvironment, ConfigurationError } from '@semiont/core';
import type { SemiontConfig, EnvironmentConfig, ServicesConfig } from '@semiont/core';

Filesystem-backed loading (SemiontProject, loadEnvironmentConfig) is in @semiont/core/node — see above.

Backend Internal Types

Types not in the OpenAPI spec:

import type {
  UpdateResourceInput,
  ResourceFilter,
  CreateAnnotationInternal,
  AnnotationCategory,
  GoogleAuthRequest,
  GraphConnection,
  GraphPath,
  EntityTypeStats,
} from '@semiont/core';

Architecture: Spec-First

Semiont follows a spec-first architecture:

  1. OpenAPI Specification (specs/src/) is the source of truth
  2. @semiont/core generates types from OpenAPI and provides domain utilities
  3. Every other package imports types from @semiont/core; application code talks to the backend through @semiont/sdk, whose transports implement core's ITransport contract

Type Yield Flow: OpenAPI spec → @semiont/core/src/types.ts (via openapi-typescript) → imported across the monorepo. This ensures no circular dependencies and clear build order.

Development

# Build the package
npm run build

# Type check
npm run typecheck

# Clean build artifacts
npm run clean

License

Apache-2.0

Related Packages

Learn More