Skip to content
GitHubXDiscord

@triggery/core

The runtime that powers every Triggery binding. Framework-agnostic, zero runtime dependencies, runs anywhere JavaScript runs (browser, Node, Workers, React Native, edge).

npm bundle

pnpm add @triggery/core
ExportPurpose
createTriggerDeclare a scenario (events, conditions, required, handler).
createRuntimeInstantiate an isolated runtime.
getDefaultRuntime / setDefaultRuntimeGlobal singleton helpers.
createCheckBuild the check.is/all/any helpers for the handler context.
createInspectorCustom ring-buffer inspector.
createSchedulerBuild a custom scheduler.
All public typesTriggerSchema, TriggerCtx, Middleware, ConcurrencyStrategy, …
import { createRuntime, createTrigger } from '@triggery/core';

const runtime = createRuntime();

const trigger = createTrigger<{
  events:  { tick: number };
  actions: { log: number };
}>(
  {
    id: 'demo:tick',
    events: ['tick'],
    handler: ({ event, actions }) => actions.log?.(event.payload),
  },
  runtime,
);

runtime.registerAction('demo:tick', 'log', n => console.log('tick', n));
runtime.fireSync('tick', 42);   // → "tick 42"

That’s the runtime in isolation. In a real app you’d skip the manual registerAction — bindings do that through useAction.

The runtime is a plain JavaScript object with a Map-based registry. It does not import React. It does not import a virtual DOM. It can run:

  • In a web worker or service worker.
  • In a Node.js process — CLI, server, edge function.
  • In React Native (no DOM adapter needed for the runtime).
  • In a vanilla HTML page with no bundler.

The same createTrigger({ … }) declaration runs unchanged in all of the above. Bindings (~50 lines each) wire useEvent / useCondition / useAction to the host framework’s lifecycle.

  • Indexed dispatchMap<eventKey, Trigger[]>, no full-table scans.
  • required-gate — handler skipped (with inspector entry) until all required conditions are registered.
  • Concurrency strategies for async handlers: take-latest (default), take-every, take-first, queue, exhaust, sync.
  • Action chains: actions.debounce(ms).foo(p), actions.throttle, actions.defer, actions.queue.
  • Cascade safety — depth limit + cycle detection on action → fireEvent chains.
  • MiddlewareonFire, onBeforeMatch, onSkip, onActionStart, onActionEnd, onError, onCascade.
  • Inspector ring buffer — built-in, auto-disables in PROD by default.
  • Last-mount-wins ownership with DEV warn-once.
  • Pure ESM, side-effect-free, tree-shakable.

About 5 KB gzipped for the core runtime alone. The bindings add about 1 KB each on top.