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

@epicurrents/core

v2.0.0

Published

Epicurrents core library

Readme

@epicurrents/core

The core library of the Epicurrents neurophysiological signal viewer. It defines the application entry point (Epicurrents), the runtime state manager, the asset / resource / module / service abstractions, the biosignal montage and trend machinery, the worker commission protocol, and the shared TypeScript types that every other @epicurrents/* package builds on. It contains no UI — the viewer interface, file-format readers, modality modules and computation services are separate packages that register themselves onto the application at setup time.

Documentation map

| Document | Audience | Contents | |---|---|---| | README.md (this file) | Developers consuming or embedding the package | Structure, usage, build and test workflow | | AGENTS.md | AI coding assistants (useful to humans too) | In-depth internals: signal data flow, SAB cache lifecycle, rolling-cache protocol, worker commissions, network resilience, gotchas | | ROADMAP.md | Contributors | General design directions and deferred work — explicitly not an issue tracker |

The README / AGENTS split is deliberate: much of the intended audience is clinicians rather than career developers, and the deep technical material lives in AGENTS.md so that an AI coding agent can carry those concepts for them. A reader should get a working mental model of the package from this file alone, and point an agent at AGENTS.md for anything beyond it.

Role in the package family

@epicurrents/core is the dependency root. Sibling packages fall into three patterns, each documented in its own repository:

  • Readers (edf-reader, csv-reader, wav-reader, nic-reader, dicom-reader, …) — parse a file format into studies and signals, usually with their own web worker.
  • Modality modules (eeg-module, emg-module, ncs-module, …) — the domain logic and settings for one recording modality.
  • Services (pyodide-service, onnx-service) — optional off-thread computation backends.

Editions of the full viewer are assembled from these packages by the separate builder repository.

Install and build

npm install
npm run build        # build:workers (worker bundles) + build:tsc (dist/)
npm test             # vitest unit suite
npm run lint         # eslint on src/

The two build outputs serve different consumers and must be regenerated together after any source change: dist/ is the ESM output imported by the main thread, and umd/ holds the standalone worker bundles. Rebuilding only one leaves the worker and main thread disagreeing about shared code — a mismatch the type system cannot see.

The package resolves its own workers, so dist/ carries each one inlined and a consumer needs no worker registration and no asset base. See AGENTS.md → Worker resolution for the escape hatch when a content security policy forbids blob: workers.

tsconfig.base.json is exported and extended by every sibling package; the TypeScript version is pinned family-wide (see AGENTS.md → Version compliance).

The package also ships the epicurrents-build-types bin, which emits a package's declarations and rewrites its # path aliases into specifiers a consumer can resolve. Core's build:types runs it, and sibling packages call it from theirs (see AGENTS.md → Path aliases and the declaration build).

Package structure

src/
  index.ts             # Epicurrents application class + public exports
  assets/
    biosignal/         # biosignal resource, montage, trend, mutex + montage/trend services
    connector/         # REST API and WebDAV data-source connectors
    dataset/           # dataset containers for resources opened together
    document/          # document (non-signal) resource base
    error/             # placeholder resource for a study that failed to load
    media/             # biosignal audio playback and synthesis methods
    reader/            # signal reader/writer/processor bases, rolling-cache op queue
    service/           # web-worker service base, memory manager, worker substitutes
    study/             # study loaders, importers and exporters
    annotation/        # annotations and resource labels
  config/              # Settings singleton
  events/              # EventBus and application events
  runtime/             # RuntimeStateManager
  types/               # all shared TypeScript interfaces
  util/                # constants, conversions, signal maths, filters and FFT (dsp),
                       # network/ (resilientFetch)
  workers/             # base, montage, trend, signal-reader and memory-manager workers

Subpath exports mirror this layout: @epicurrents/core/assets, /config, /events, /runtime, /types, /util and /workers. Only these barrels are published; a file inside one, such as dist/types/event, is not reachable. The standalone worker bundles are exposed as @epicurrents/core/workers/<name>.worker.js (from umd/).

Usage

import { Epicurrents } from '@epicurrents/core'

const app = new Epicurrents()
// Sets window.__EPICURRENTS__ = { APP, EVENT_BUS, RUNTIME, SETUP }.
// SETUP is the host's static bootstrap configuration, written before launch and read, never
// mutated, by the viewer; the runtime state manager holds the live configuration.

// Optionally override default settings before launching.
app.configure({ 'app.useMemoryManager': false })

// Register the modality modules, services, study importers and the UI.
app.registerModule('eeg', eegModule)
app.registerService('pyodide', pyodideService)
app.registerStudyImporter('edf', 'EDF', 'file', edfLoader)
app.registerInterface(MyInterfaceModule)

// Launch: sets up the memory manager when app.useMemoryManager is on and SharedArrayBuffer is
// available in a cross-origin-isolated page, then instantiates the interface.
await app.launch()

// Open a recording through a registered importer.
const dataset = app.createDataset('Session 1', true)
const resource = await app.loadStudy('edf', 'https://example.com/recording.edf', { dataset })
if (resource) {
    app.selectActiveResource(resource)
}

Key Epicurrents methods beyond the flow above:

  • addResource(resource, modality?) — add an already-constructed resource to the active dataset.
  • setActiveDataset(dataset) — make a dataset the active one, or clear it with null.
  • registerStudyExporter(name, label, mode, loader) — the export-side counterpart of registerStudyImporter.
  • setWorkerOverride(name, getWorker) — inject a deployment-specific or test-double worker factory; getWorkerOverride(name) returns an instance from the registered factory, or null when none is registered.
  • notifySessionRestored() — host applications call this after a re-login; it resets the network circuit breakers on the main thread and in every registered service's worker so latched fetch paths resume.
  • setSettingsValue(field, value) / SETTINGS — runtime settings access. Persisted user overrides are read at startup: init() picks up a settings entry from localStorage and applies the values whose fields a module declares user-definable. Writing that entry is the host application's job; nothing in this package stores it.

The event bus (app.eventBus, also window.__EPICURRENTS__.EVENT_BUS) carries scoped property-change:* and payload events for reactive consumers; see AGENTS.md → Event bus dispatch semantics for the contract.

Testing

Vitest suites live in tests/, mirroring src/. Four of them run against real SharedArrayBuffer instances: BiosignalMutex.test.ts, memory-rearrange.test.ts, window-epoch.test.ts, and montage-validated-read.test.ts, which covers the optimistic epoch-validated read the montage derives from live window views with, taking no lock. Run a single file with npx vitest run tests/<path>.

Contributing

Work on a feature branch, keep npm test and npm run lint green, and regenerate both build outputs before verifying in a consuming application. Planned and deferred design work is listed in ROADMAP.md; bug reports and feature requests belong in the GitHub issue tracker.

License

Copyright 2017-2022, 2023-2026 Sampsa Lohi. Licensed under the Apache-2.0 license.