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

@vrai-ie/heat-runtime

v0.1.0

Published

Official HEAT runtime for Node.js: build runners and applications that use HEAT as a backend. Token auth, task lifecycle, sessions, templates, nodes, and config.

Readme

heat-runtime

The official HEAT runtime for Node.js: build HEAT runners (containers that process node tasks) and build applications that use HEAT as a backend (sessions, nodes, data sources, config). Use a single library in both cases; pass a session token when calling from outside the cluster so all requests are authenticated.

Requirements: Node.js ≥ 16.

Installation

From the public npm registry:

npm install heat-runtime

From the HEAT repo (development or local link):

cd runtimes/js && npm install && npm run build
# Or from another project:
# "heat-runtime": "file:../path/to/HEAT/runtimes/js"
{
  "dependencies": {
    "heat-runtime": "file:../../runtimes/js"
  }
}

Quick start (published package)

import { HEATRuntimeOptions, HEATRuntime } from 'heat-runtime';

const coreApiUrl = process.env.CORE_API_URL || 'http://localhost:5220';
const sessionToken = process.env.HEAT_SESSION_TOKEN;

const runtime = new HEATRuntime(new HEATRuntimeOptions(coreApiUrl, sessionToken));

// List sessions
const sessions = await runtime.listSessions();
console.log(sessions);

Configuration

Create a runtime with the Core API URL and, when needed, a session token:

import { HEATRuntimeOptions, HEATRuntime } from 'heat-runtime';

const coreApiUrl = process.env.CORE_API_URL || 'http://localhost:5220';
const sessionToken = process.env.HEAT_SESSION_TOKEN || process.env.RuntimeSessionToken;

const opts = new HEATRuntimeOptions(coreApiUrl, sessionToken);
const runtime = new HEATRuntime(opts);
  • coreApiUrl (required): Base URL of the HEAT Core API (e.g. http://localhost:5220 or https://core.heat.example.com).
  • sessionToken (optional): Bearer token for authentication. Use it when:
    • Running outside the cluster (scripts, web apps, CLI tools).
    • Core API is in Strict auth mode, or in ClusterOnly mode and the request is treated as external.

If you omit sessionToken, the runtime does not send an Authorization header. That is fine when Core is in Local mode or when something else injects the header (e.g. a facade that forwards the incoming request’s token).

  • isDebug (optional): When true, init() does not poll /api/tasks/claim. Instead it builds a synthetic task for a single node instance and runs the matching processor once, then exits. Use for local iteration without the scheduler.
  • debugNodeId (required when isDebug is true): The node instance id to run locally (same as Python --node).

Example: run once against node instance 12:

const opts = new HEATRuntimeOptions(coreApiUrl, sessionToken, true, 12);
const runtime = new HEATRuntime(opts);
runtime.register(processor);
await runtime.init('my-runner-debug'); // runs once then returns

Use case 1: Building runners

Runners poll the Core API for tasks, run your logic, then report results. You can use either a manual claim loop or the register + init pattern.

Manual claim loop

Create a runtime, then in a loop: claim a task, run your processor, then complete or fail the task.

const runtime = new HEATRuntime(new HEATRuntimeOptions(coreApiUrl, process.env.HEAT_SESSION_TOKEN));
const runnerTag = 'my-runner-' + Math.random().toString(36).slice(2, 10);
const supportedTemplates = ['my-node-template'];

while (true) {
  try {
    const task = await runtime.claimTask(runnerTag, supportedTemplates);
    if (!task?.id) {
      await sleep(5000);
      continue;
    }
    try {
      await runtime.signalTaskExecution(task.id);
      // Your logic: read task.parentNodeOutputs, compute, then:
      await runtime.createNodeOutput(task.nodeInstanceId, outputDto);
      await runtime.completeNode(task.id, task.nodeInstanceId);
    } catch (err) {
      await runtime.failNode(task.id, task.nodeInstanceId, err.message);
    }
  } catch (err) {
    if (err?.response?.status === 404) {
      await sleep(5000);
      continue;
    }
    throw err;
  }
}

Register + init (recommended)

Implement the processor contract and start the built-in loop:

  1. Implement IProcessor: templateName, optional validate(task), and process(task, runtime).
  2. Call runtime.register(processor) for each processor.
  3. Call runtime.init(runnerTag) to run the claim → validate → signal → process → complete/fail loop.
import { HEATRuntime, HEATRuntimeOptions, IProcessor, RunnerTask, IProcessorRuntime } from 'heat-runtime';

const processor: IProcessor = {
  templateName: 'my-node-template',
  async validate(task) {
    if (!task.parentNodeOutputs?.length) return { success: false, message: 'No parent outputs' };
    return { success: true };
  },
  async process(task, runtime: IProcessorRuntime) {
    // Build output from task.parentNodeOutputs, then:
    await runtime.createNodeOutput(task.nodeInstanceId, {
      nodeInstanceId: task.nodeInstanceId,
      configuration: JSON.stringify(result),
      dataSourceId: 1,
      dataPath: 'out',
      outputIdentifier: 'out',
    });
  },
};

const runtime = new HEATRuntime(new HEATRuntimeOptions(coreApiUrl, process.env.HEAT_SESSION_TOKEN));
runtime.register(processor);
await runtime.init(runnerTag, { pollingIntervalMs: 2000 });

Optional: load platform config into process.env before starting:

await runtime.loadEnv({ runnerName: 'my-runner', failOnMissing: false });
runtime.register(processor);
await runtime.init(runnerTag);

Task lifecycle

  • claimTask(runnerTag, supportedNodeTemplateNames) → returns a RunnerTask or 404 when none available.
  • signalTaskExecution(taskId) → marks task as started.
  • createNodeOutput(nodeId, dto) → attach output to the node (do this inside your process logic when needed).
  • completeNode(taskId, nodeId [, statusDetails]) → set node success and complete the task.
  • failNode(taskId, nodeId [, statusDetails]) → set node failed and fail the task.

Low-level: completeTask(taskId), failTask(taskId) are also available if you manage node status yourself.

Use case 2: Building a service that depends on HEAT

Use the same runtime as a full client to create, edit, manipulate, and query HEAT resources. Always pass a session token when the app runs outside the cluster and Core requires auth. The runtime exposes the Core API surface needed for services: sessions, templates, node instances, node outputs, projects, and platform config.

Authentication

import { HEATRuntimeOptions, HEATRuntime } from 'heat-runtime';

const runtime = new HEATRuntime(
  new HEATRuntimeOptions(process.env.CORE_API_URL!, process.env.HEAT_SESSION_TOKEN!)
);

API summary (grouped by resource)

Sessions: listSessions, getSessionById, createSession, updateSession, deleteSession, getSessionUsers, addSessionUser, removeSessionUser, getSessionNodeOutputs

Session templates: listSessionTemplates, getSessionTemplateById, createSessionTemplate, updateSessionTemplate, deleteSessionTemplate, exportSessionTemplate, importSessionTemplate

Session template nodes: listSessionTemplateNodes, getSessionTemplateNodeById, createSessionTemplateNode, updateSessionTemplateNode, deleteSessionTemplateNode

Projects: listProjects, getProjectById, createProject, updateProject, deleteProject

Node instances: getNodeById, listNodes, createNodeOutput, updateNodeStatus, getNodeLatestOutput, listNodeOutputs, reprocessNode

Node outputs: getNodeOutputById (output data by id)

Scenario instances: getSessionScenarioInstances, addScenarioInstance, updateScenarioInstance, removeScenarioInstance

Dimensions: createSessionDimension, getDimensionById, updateSessionDimension, deleteSessionDimension, listDimensionsForUser

Node templates: listNodeTemplates, getNodeTemplateById, createNodeTemplate, updateNodeTemplate, deleteNodeTemplate, getNodeTemplateRunnerMappings

Runner types: listRunnerTypes, getRunnerTypeById, createRunnerType, updateRunnerType, deleteRunnerType, getRunnerTypeSupportedTemplates

Platform config: getConfig, getConfigValue, setConfigValue (object-style, like Python); getPlatformConfigurationByPrefix, getAllPlatformConfig, getPlatformConfigDetail, createPlatformConfig, updatePlatformConfig, deletePlatformConfig

Data sources: listDataSources, getDataSourceById, createDataSource, updateDataSource, deleteDataSource

Example: create project, session, then list node outputs

const runtime = new HEATRuntime(
  new HEATRuntimeOptions(process.env.CORE_API_URL!, process.env.HEAT_SESSION_TOKEN!)
);

// Create a project
const project = await runtime.createProject({
  title: 'My Project',
  description: 'Description',
  icon: 'folder',
  ownerId: 1,
  defaultSessionTemplateId: 1,
});

// Create a session from a template
const session = await runtime.createSession(project.id!, {
  name: 'New Session',
  sessionTemplateId: 1,
});

// Later: list node outputs for the session (all node instances' outputs in one call)
const nodeOutputs = await runtime.getSessionNodeOutputs(session.id!);

Example: query and update

const sessions = await runtime.listSessions();
const session = await runtime.getSessionById(sessions[0].id!);
await runtime.updateSession(session.id!, { name: 'Updated name' });

const nodes = await runtime.listNodes(session.id!);
const latestOutput = await runtime.getNodeLatestOutput(nodes[0].id);
const outputData = await runtime.getNodeOutputById(latestOutput.id!);

Configuration as object (like Python)

You can read and write platform config as an object or by dotted path, matching the Python runtime:

// Get config for a prefix as an object
const runnerConfig = await runtime.getConfig('runner_config');
const defaultStore = runnerConfig.default_store;

// Get a single value by dotted path
const store = await runtime.getConfigValue('runner_config.default_store');

// Set a single value by dotted name
await runtime.setConfigValue('runner_config.default_store', 'HEAT Managed Object Store');

Behaviour

  • 404 from claim: No task available. The manual loop and init() both treat 404 as “sleep and retry” (no throw).
  • Errors: Other HTTP errors (4xx/5xx) are thrown by axios; handle them in your loop or process.
  • Idempotency: Process each task once using only the provided task data and config; avoid external side effects that are not reported back to Core.

Documentation

  • Full API reference: docs/API.md — all HEATRuntime methods, options, and exported types.
  • Guides: HEAT docs site → Building Node TemplatesDeveloping Runners (JavaScript) (Dockerfile, manifest, local test).
  • Publishing: See PUBLISHING.md for the npm publish checklist.

The JavaScript runtime mirrors the behaviour of the Python runtime; use the same Core concepts (node templates, sessions, tasks, runner types).

Troubleshooting

  • 401 Unauthorized: Set HEAT_SESSION_TOKEN (or RuntimeSessionToken) when calling Core from outside the cluster or when Core is in Strict/ClusterOnly auth.
  • 404 on claim: No task available; the built-in loop and manual examples treat this as “sleep and retry”. Not an error.
  • CORS / network: Ensure coreApiUrl is reachable from your environment (browser apps may need a proxy if Core does not allow CORS).

License

See LICENSE in the repository root, or the license field in package.json.