@triggery/core
The runtime that powers every Triggery binding. Framework-agnostic, zero runtime dependencies, runs anywhere JavaScript runs (browser, Node, Workers, React Native, edge).
Install
Section titled “Install”pnpm add @triggery/core npm install @triggery/core yarn add @triggery/core bun add @triggery/core What’s inside
Section titled “What’s inside”| Export | Purpose |
|---|---|
createTrigger | Declare a scenario (events, conditions, required, handler). |
createRuntime | Instantiate an isolated runtime. |
getDefaultRuntime / setDefaultRuntime | Global singleton helpers. |
createCheck | Build the check.is/all/any helpers for the handler context. |
createInspector | Custom ring-buffer inspector. |
createScheduler | Build a custom scheduler. |
| All public types | TriggerSchema, TriggerCtx, Middleware, ConcurrencyStrategy, … |
Quick example
Section titled “Quick example”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.
Why “framework-agnostic”?
Section titled “Why “framework-agnostic”?”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.
Features
Section titled “Features”- Indexed dispatch —
Map<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 → fireEventchains. - Middleware —
onFire,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.
Bundle size
Section titled “Bundle size”About 5 KB gzipped for the core runtime alone. The bindings add about 1 KB each on top.
Related packages
Section titled “Related packages” @triggery/react React 18+ bindings.
@triggery/solid SolidJS bindings.
@triggery/vue Vue 3 Composition API bindings.
@triggery/testing Test runtime + fakeScheduler.
@triggery/vite Auto-discovery via virtual:triggery-registry.
@triggery/eslint-plugin 8 lint rules: no-event-cascade, hook-rules, …