TriggerCtx
Единственный аргумент, который получает каждый обработчик триггера. В нём упакованы матчившееся событие, снепшот условий, прокси действий, DSL check, метаданные рантайма и AbortSignal. Форма полностью выводится из TriggerSchema триггера — деструктурируй только нужные поля.
import type { TriggerCtx } from '@triggery/core';
Определение
Заголовок раздела «Определение»type TriggerCtx<S extends TriggerSchema, R extends ConditionKey<S> = never> = {
readonly event: EventOf<S>;
readonly conditions: ConditionsCtx<ConditionMap<S>, R>;
readonly actions: ActionsCtx<ActionMap<S>>;
readonly check: CheckCtx<ConditionMap<S>>;
readonly meta: MetaCtx;
readonly signal: AbortSignal;
};S — схема триггера; R — union ключей обязательных условий (required: [...] в конфиге).
event — EventOf<S>
Заголовок раздела «event — EventOf<S>»Дискриминированный union по S['events']. У каждого варианта { readonly name: K; readonly payload: EventMap<S>[K] }. Сужай через event.name.
type EventOf<S> = { name: 'open'; payload: { id: string } }
| { name: 'close'; payload: { id: string; reason: 'ok' | 'cancel' } };conditions — ConditionsCtx<ConditionMap<S>, R>
Заголовок раздела «conditions — ConditionsCtx<ConditionMap<S>, R>»Снепшот всех условий, снимается один раз в момент срабатывания. Ключи, перечисленные в required, видны как необязательные нет — без undefined; остальные — T | undefined.
Ограничение V1: required не сужает в системе типов — conditions.user остаётся User | undefined, даже если required: ['user']. Используй check.is/all/any или ранний guard if (!conditions.user) return;.
actions — ActionsCtx<ActionMap<S>>
Заголовок раздела «actions — ActionsCtx<ActionMap<S>>»Мапа { [name]?: (payload) => void } плюс три цепочечных таймера:
| Метод | Возвращает | Описание |
|---|---|---|
actions.<name>?.(payload) | void | Вызвать действие, если оно зарегистрировано. Optional chain, потому что реактор мог быть не смонтирован. |
actions.debounce(ms) | та же форма | Ждать ms тишины перед срабатыванием. |
actions.throttle(ms) | та же форма | Не более одного срабатывания за окно ms. |
actions.defer(ms) | та же форма | Ждать ms перед срабатыванием — без coalescing. |
check — CheckCtx<ConditionMap<S>>
Заголовок раздела «check — CheckCtx<ConditionMap<S>>»DSL предикатов. См. createCheck. is, all и any сужают значение через NonNullable внутри предиката.
meta — MetaCtx
Заголовок раздела «meta — MetaCtx»Метаданные рантайма о текущем запуске:
| Поле | Тип | Описание |
|---|---|---|
runId | string | Уникальный id запуска. |
triggerId | string | Триггер, который сейчас запущен. |
scheduledAt | number | performance.now() в момент постановки запуска в очередь. |
cascadeDepth | number | 0 для срабатываний верхнего уровня; n для n-го потомка каскада. |
parentRunId? | string | Установлен, если запуск — часть каскада. |
parentTriggerId? | string | То же — id upstream-триггера. |
signal — AbortSignal
Заголовок раздела «signal — AbortSignal»Прерывается, когда рантайм отменяет текущий запуск — например, стратегия concurrency take-latest его вытесняет, триггер отключён или утилизирован, либо разрушается сам рантайм. Передавай его в fetch(url, { signal }), addEventListener('…', fn, { signal }) или проверяй signal.aborted после любых async-ожиданий.
Примеры
Заголовок раздела «Примеры»Деструктурируй только нужное
Заголовок раздела «Деструктурируй только нужное»import { createTrigger function createTrigger<S extends TriggerSchema>(config: CreateTriggerConfig<S>, runtime?: Runtime): Trigger<S>Create a trigger and register it in a runtime (the default runtime if none is passed). } from '@triggery/core';
createTrigger createTrigger<{
events: {
ping: void;
};
conditions: {
user: {
id: string;
} | null;
};
actions: {
log: string;
};
}>(config: CreateTriggerConfig<{
events: {
ping: void;
};
conditions: {
user: {
id: string;
} | null;
};
actions: {
log: string;
};
}>, runtime?: Runtime): Trigger<{
events: {
ping: void;
};
conditions: {
user: {
id: string;
} | null;
};
actions: {
log: string;
};
}>
Create a trigger and register it in a runtime (the default runtime if none is passed). <{
events events: {
ping: void;
}
: { ping ping: void : void };
conditions conditions: {
user: {
id: string;
} | null;
}
: { user user: {
id: string;
} | null
: { id id: string : string } | null };
actions actions: {
log: string;
}
: { log log: string : string };
}>({
id id: string : 'demo',
events events: readonly "ping"[] : ['ping'],
required required?: readonly "user"[] | undefinedRequired condition keys. The trigger will not run unless all of them are registered. : ['user'],
handler handler: TriggerHandler<{
events: {
ping: void;
};
conditions: {
user: {
id: string;
} | null;
};
actions: {
log: string;
};
}, never>
({ event event: {
readonly name: "ping";
readonly payload: void;
}
, conditions conditions: ConditionsCtx<{
user: {
id: string;
} | null;
}, never>
, actions actions: ActionsCtx<{
log: string;
}>
, check check: CheckCtx<{
user: {
id: string;
} | null;
}>
, meta meta: MetaCtx , signal signal: AbortSignal }) {
if (signal signal: AbortSignal .aborted AbortSignal.aborted: booleanThe **`aborted`** read-only property returns a value that indicates whether the asynchronous operations the signal is communicating with are aborted (`true`) or not (`false`).
[MDN Reference](https://developer.mozilla.org/docs/Web/API/AbortSignal/aborted) ) return;
if (!check check: CheckCtx<{
user: {
id: string;
} | null;
}>
.is is<"user">(key: "user", predicate: (value: {
id: string;
}) => boolean): boolean
('user', u u: {
id: string;
}
=> u u: {
id: string;
}
.id id: string .length String.length: numberReturns the length of a String object. > 0)) return;
actions actions: ActionsCtx<{
log: string;
}>
.log log?: ((payload: string) => void) | undefined ?.(`[run ${meta meta: MetaCtx .runId runId: string }] ${event event: {
readonly name: "ping";
readonly payload: void;
}
.name name: "ping" }`);
},
});Сужение по event.name
Заголовок раздела «Сужение по event.name»import { createTrigger function createTrigger<S extends TriggerSchema>(config: CreateTriggerConfig<S>, runtime?: Runtime): Trigger<S>Create a trigger and register it in a runtime (the default runtime if none is passed). } from '@triggery/core';
createTrigger createTrigger<{
events: {
open: {
id: string;
};
close: {
id: string;
reason: "ok" | "cancel";
};
};
}>(config: CreateTriggerConfig<{
events: {
open: {
id: string;
};
close: {
id: string;
reason: "ok" | "cancel";
};
};
}>, runtime?: Runtime): Trigger<{
events: {
open: {
id: string;
};
close: {
id: string;
reason: "ok" | "cancel";
};
};
}>
Create a trigger and register it in a runtime (the default runtime if none is passed). <{
events events: {
open: {
id: string;
};
close: {
id: string;
reason: "ok" | "cancel";
};
}
: { open open: {
id: string;
}
: { id id: string : string }; close close: {
id: string;
reason: "ok" | "cancel";
}
: { id id: string : string; reason reason: "ok" | "cancel" : 'ok' | 'cancel' } };
}>({
id id: string : 'modal',
events events: readonly ("open" | "close")[] : ['open', 'close'],
handler handler: TriggerHandler<{
events: {
open: {
id: string;
};
close: {
id: string;
reason: "ok" | "cancel";
};
};
}, never>
({ event event: EventOf<{
events: {
open: {
id: string;
};
close: {
id: string;
reason: "ok" | "cancel";
};
};
}>
}) {
if (event event: EventOf<{
events: {
open: {
id: string;
};
close: {
id: string;
reason: "ok" | "cancel";
};
};
}>
.name name: "open" | "close" === 'open') {
console var console: Console .log Console.log(...data: any[]): voidThe **`console.log()`** static method outputs a message to the console.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static) ('opening', event event: {
readonly name: "open";
readonly payload: {
id: string;
};
}
.payload payload: {
id: string;
}
.id id: string );
} else {
console var console: Console .log Console.log(...data: any[]): voidThe **`console.log()`** static method outputs a message to the console.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static) ('closing', event event: {
readonly name: "close";
readonly payload: {
id: string;
reason: "ok" | "cancel";
};
}
.payload payload: {
id: string;
reason: "ok" | "cancel";
}
.reason reason: "ok" | "cancel" );
}
},
});Async-работа с поддержкой abort
Заголовок раздела «Async-работа с поддержкой abort»import { createTrigger function createTrigger<S extends TriggerSchema>(config: CreateTriggerConfig<S>, runtime?: Runtime): Trigger<S>Create a trigger and register it in a runtime (the default runtime if none is passed). } from '@triggery/core';
createTrigger createTrigger<{
events: {
fetch: string;
};
actions: {
setData: unknown;
};
}>(config: CreateTriggerConfig<{
events: {
fetch: string;
};
actions: {
setData: unknown;
};
}>, runtime?: Runtime): Trigger<{
events: {
fetch: string;
};
actions: {
setData: unknown;
};
}>
Create a trigger and register it in a runtime (the default runtime if none is passed). <{
events events: {
fetch: string;
}
: { fetch fetch: string : string };
actions actions: {
setData: unknown;
}
: { setData setData: unknown : unknown };
}>({
id id: string : 'fetcher',
events events: readonly "fetch"[] : ['fetch'],
concurrency concurrency?: ConcurrencyStrategy | undefinedConcurrency strategy applied across handler runs (default: `'take-latest'`).
- `take-latest` — new run aborts the previous (`signal.aborted` becomes true).
- `take-every` — every run proceeds independently, no aborts.
- `take-first` / `exhaust` — new runs are skipped while one is still in flight.
- `queue` — new runs wait for the previous to finish (serialized).
- `sync` — like `take-every`; provided as a documentation marker. : 'take-latest',
async handler handler: TriggerHandler<{
events: {
fetch: string;
};
actions: {
setData: unknown;
};
}, never>
({ event event: {
readonly name: "fetch";
readonly payload: string;
}
, actions actions: ActionsCtx<{
setData: unknown;
}>
, signal signal: AbortSignal }) {
const res const res: Response = await fetch function fetch(input: string | URL | Request, init?: RequestInit): Promise<Response> (+1 overload)[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/fetch) (`/api/${event event: {
readonly name: "fetch";
readonly payload: string;
}
.payload payload: string }`, { signal RequestInit.signal?: AbortSignal | null | undefinedAn AbortSignal to set request's signal. });
if (signal signal: AbortSignal .aborted AbortSignal.aborted: booleanThe **`aborted`** read-only property returns a value that indicates whether the asynchronous operations the signal is communicating with are aborted (`true`) or not (`false`).
[MDN Reference](https://developer.mozilla.org/docs/Web/API/AbortSignal/aborted) ) return;
const data const data: any = await res const res: Response .json Body.json(): Promise<any>[MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/json) ();
actions actions: ActionsCtx<{
setData: unknown;
}>
.setData setData?: ((payload: unknown) => void) | undefined ?.(data const data: any );
},
});Цепочка действий с debounce
Заголовок раздела «Цепочка действий с debounce»import { createTrigger function createTrigger<S extends TriggerSchema>(config: CreateTriggerConfig<S>, runtime?: Runtime): Trigger<S>Create a trigger and register it in a runtime (the default runtime if none is passed). } from '@triggery/core';
createTrigger createTrigger<{
events: {
keystroke: string;
};
actions: {
search: string;
};
}>(config: CreateTriggerConfig<{
events: {
keystroke: string;
};
actions: {
search: string;
};
}>, runtime?: Runtime): Trigger<{
events: {
keystroke: string;
};
actions: {
search: string;
};
}>
Create a trigger and register it in a runtime (the default runtime if none is passed). <{
events events: {
keystroke: string;
}
: { keystroke keystroke: string : string };
actions actions: {
search: string;
}
: { search search: string : string };
}>({
id id: string : 'autocomplete',
events events: readonly "keystroke"[] : ['keystroke'],
handler handler: TriggerHandler<{
events: {
keystroke: string;
};
actions: {
search: string;
};
}, never>
({ event event: {
readonly name: "keystroke";
readonly payload: string;
}
, actions actions: ActionsCtx<{
search: string;
}>
}) {
actions actions: ActionsCtx<{
search: string;
}>
.debounce function debounce(ms: number): ActionsCtx<{
search: string;
}>
(300).search search?: ((payload: string) => void) | undefined ?.(event event: {
readonly name: "keystroke";
readonly payload: string;
}
.payload payload: string );
},
});Логирование с учётом каскада
Заголовок раздела «Логирование с учётом каскада»import { createTrigger function createTrigger<S extends TriggerSchema>(config: CreateTriggerConfig<S>, runtime?: Runtime): Trigger<S>Create a trigger and register it in a runtime (the default runtime if none is passed). } from '@triggery/core';
createTrigger createTrigger<{
events: {
"order-placed": {
id: string;
};
};
}>(config: CreateTriggerConfig<{
events: {
"order-placed": {
id: string;
};
};
}>, runtime?: Runtime): Trigger<{
events: {
"order-placed": {
id: string;
};
};
}>
Create a trigger and register it in a runtime (the default runtime if none is passed). <{ events events: {
'order-placed': {
id: string;
};
}
: { 'order-placed': { id id: string : string } } }>({
id id: string : 'order',
events events: readonly "order-placed"[] : ['order-placed'],
handler handler: TriggerHandler<{
events: {
"order-placed": {
id: string;
};
};
}, never>
({ event event: {
readonly name: "order-placed";
readonly payload: {
id: string;
};
}
, meta meta: MetaCtx }) {
if (meta meta: MetaCtx .cascadeDepth cascadeDepth: number > 0) {
console var console: Console .log Console.log(...data: any[]): voidThe **`console.log()`** static method outputs a message to the console.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static) (`order ${event event: {
readonly name: "order-placed";
readonly payload: {
id: string;
};
}
.payload payload: {
id: string;
}
.id id: string } via cascade from ${meta meta: MetaCtx .parentTriggerId parentTriggerId?: string | undefined }`);
}
},
});