@triggerlink/sdk 0.4.8 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/execx.d.ts CHANGED
@@ -11,13 +11,16 @@ export interface OpError {
11
11
  }
12
12
  /** 应用 → 平台的执行指令(serve 序列化为响应)。 */
13
13
  export interface Opcode {
14
- op: "StepComplete" | "StepError" | "RunComplete" | "RunError" | "Sleep" | "SendEvent";
14
+ op: "StepComplete" | "StepError" | "RunComplete" | "RunError" | "Sleep" | "SendEvent" | "WaitForEvent";
15
15
  id?: string;
16
16
  step_id?: string;
17
17
  output?: unknown;
18
18
  error?: OpError;
19
19
  until?: string;
20
20
  events?: OutgoingEvent[];
21
+ event?: string;
22
+ match?: string;
23
+ timeout?: string;
21
24
  }
22
25
  /** step.sendEvent 待扇出的事件(id/ts 缺省由平台补全,id 缺省为确定性派生)。 */
23
26
  export interface OutgoingEvent {
@@ -6,6 +6,15 @@ export interface EventPayload<T = unknown> {
6
6
  data: T;
7
7
  ts: string;
8
8
  }
9
+ /** step.waitForEvent 命中后返回的事件(与 EventPayload 同构)。 */
10
+ export type TriggerLinkEvent<T = unknown> = EventPayload<T>;
11
+ /** cancelOn 取消规则(FR-4.9):event 到达且 match 命中时,平台取消该函数的在途 run。 */
12
+ export interface CancelOnRule {
13
+ /** 触发取消的事件名 */
14
+ event: string;
15
+ /** 可选 expr 表达式,留空 = 该事件到达即取消;环境:data=到达事件 data,event=本 run 触发事件 {name, data} */
16
+ match?: string;
17
+ }
9
18
  /** 传给用户 handler 的上下文。 */
10
19
  export interface HandlerContext<T = unknown> {
11
20
  event: EventPayload<T>;
@@ -13,16 +22,38 @@ export interface HandlerContext<T = unknown> {
13
22
  runId: string;
14
23
  attempt: number;
15
24
  }
25
+ /** triggerlink/run.failed 内部事件的 data(FR-2.11),即 onFailure handler 的 event.data。 */
26
+ export interface RunFailedEventData {
27
+ run_id: string;
28
+ function_id: string;
29
+ error: string;
30
+ /** 触发该 run 的原始事件 */
31
+ event: EventPayload;
32
+ }
16
33
  export interface FunctionOpts {
17
34
  /** 稳定标识,改名会丢历史 memo 关联 */
18
35
  id: string;
19
- /** 订阅的事件名 */
20
- event: string;
36
+ /** 订阅的事件名;纯 cron 函数可省略(event/cron 至少其一) */
37
+ event?: string;
38
+ /** 事件触发 match 表达式(FR-3.1),expr 语法,环境只含 data(= 事件 data) */
39
+ match?: string;
40
+ /** 标准 5 字段 cron(分 时 日 月 周),UTC */
41
+ cron?: string;
21
42
  /** 重试上限;0/缺省 = 平台默认(4) */
22
43
  retries?: number;
44
+ /** 取消规则,随 manifest 上报为 cancel_on */
45
+ cancelOn?: CancelOnRule[];
46
+ /**
47
+ * run 进入 Failed 终态时的处理器(FR-2.11)。serve 时注册隐式函数 <id>/on-failure,
48
+ * 订阅内部事件 triggerlink/run.failed(match 按 function_id 过滤),handler 内可用全部 step 原语。
49
+ * onFailure 自身失败不会递归触发。
50
+ */
51
+ onFailure?: (ctx: HandlerContext<RunFailedEventData>) => Promise<unknown>;
23
52
  }
24
53
  export interface TriggerFunction<T = unknown> {
25
- readonly opts: Required<FunctionOpts>;
54
+ readonly opts: FunctionOpts & {
55
+ retries: number;
56
+ };
26
57
  readonly handler: (ctx: HandlerContext<T>) => Promise<unknown>;
27
58
  }
28
59
  /** 定义一个 durable 函数。副作用必须放进 step.run(协议第 6 节约束)。 */
package/dist/function.js CHANGED
@@ -2,7 +2,8 @@
2
2
  export function createFunction(opts, handler) {
3
3
  if (!opts.id)
4
4
  throw new Error("createFunction: id is required");
5
- if (!opts.event)
6
- throw new Error("createFunction: event is required");
5
+ if (!opts.event && !opts.cron) {
6
+ throw new Error("createFunction: event or cron is required"); // 纯 cron 函数无事件订阅
7
+ }
7
8
  return { opts: { retries: 0, ...opts }, handler };
8
9
  }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { createClient, type Client, type ClientOptions, type SendEventInput, type SendResult, type RegisterOptions, } from "./client.js";
2
- export { createFunction, type TriggerFunction, type FunctionOpts, type HandlerContext, type EventPayload, } from "./function.js";
2
+ export { createFunction, type TriggerFunction, type FunctionOpts, type HandlerContext, type EventPayload, type TriggerLinkEvent, type CancelOnRule, type RunFailedEventData, } from "./function.js";
3
3
  export { serve, sdkVersion, type ServeOptions } from "./serve.js";
4
4
  export { StepInterrupt, type Opcode, type StepState, type OutgoingEvent } from "./execx.js";
5
- export type { StepTool } from "./step.js";
5
+ export type { StepTool, WaitForEventOpts } from "./step.js";
package/dist/serve.js CHANGED
@@ -9,8 +9,21 @@ function json(data, status = 200) {
9
9
  }
10
10
  export function serve(opts) {
11
11
  const byID = new Map();
12
- for (const fn of opts.functions)
12
+ for (const fn of opts.functions) {
13
13
  byID.set(fn.opts.id, fn);
14
+ if (fn.opts.onFailure) {
15
+ // FR-2.11:注册隐式函数,订阅 run 失败内部事件并按 function_id 过滤
16
+ byID.set(`${fn.opts.id}/on-failure`, {
17
+ opts: {
18
+ id: `${fn.opts.id}/on-failure`,
19
+ event: "triggerlink/run.failed",
20
+ match: `data.function_id == '${fn.opts.id}'`,
21
+ retries: 0,
22
+ },
23
+ handler: fn.opts.onFailure,
24
+ });
25
+ }
26
+ }
14
27
  async function GET(req) {
15
28
  if (!verifySignature(opts.client.signingKey, req.headers.get(SIGNATURE_HEADER), new Uint8Array(0))) {
16
29
  return json({ error: "unauthorized" }, 401);
@@ -21,7 +34,12 @@ export function serve(opts) {
21
34
  functions: [...byID.values()].map((f) => ({
22
35
  id: f.opts.id,
23
36
  event: f.opts.event,
37
+ ...(f.opts.match ? { match: f.opts.match } : {}),
38
+ ...(f.opts.cron ? { cron: f.opts.cron } : {}),
24
39
  retries: f.opts.retries,
40
+ ...(f.opts.cancelOn?.length
41
+ ? { cancel_on: f.opts.cancelOn.map((c) => ({ event: c.event, match: c.match })) }
42
+ : {}),
25
43
  })),
26
44
  });
27
45
  }
package/dist/step.d.ts CHANGED
@@ -1,4 +1,14 @@
1
1
  import { ExecCtx, type OutgoingEvent } from "./execx.js";
2
+ import type { TriggerLinkEvent } from "./function.js";
3
+ /** step.waitForEvent 的配置。 */
4
+ export interface WaitForEventOpts {
5
+ /** 等待的事件名(必填) */
6
+ event: string;
7
+ /** 可选 expr 表达式;求值环境:data=到达事件 data,event=本 run 触发事件 {name, data} */
8
+ match?: string;
9
+ /** 可选超时:Go duration 字符串(如 "168h")或毫秒数(1500 → "1.5s");超时后返回 null */
10
+ timeout?: string | number;
11
+ }
2
12
  /** handler 内可用的 step 工具。 */
3
13
  export interface StepTool {
4
14
  /**
@@ -19,6 +29,13 @@ export interface StepTool {
19
29
  * memo 语义同 run——恢复重入时直接返回已发事件 ID 列表,不会重复发送。
20
30
  */
21
31
  sendEvent(id: string, events: OutgoingEvent | OutgoingEvent[]): Promise<string[]>;
32
+ /**
33
+ * 挂起当前 run 直至匹配事件到达或超时(协议 5.7 / FR-2.6):
34
+ * 事件命中 → 返回该事件;超时 → 返回 null(超时分支)。
35
+ * 与 sleep 同为挂起原语(恢复重入时 memo 命中直接返回),但唤醒由平台在
36
+ * 事件路由命中/超时扫描时驱动,挂起期间零占用。
37
+ */
38
+ waitForEvent(id: string, opts: WaitForEventOpts): Promise<TriggerLinkEvent | null>;
22
39
  }
23
40
  /** 为一次函数调用构造 step 工具。 */
24
41
  export declare function createStepTool(ec: ExecCtx): StepTool;
package/dist/step.js CHANGED
@@ -45,8 +45,34 @@ export function createStepTool(ec) {
45
45
  throw new Error(`step.sendEvent "${id}": no events`);
46
46
  throw new StepInterrupt({ op: "SendEvent", id: h, step_id: id, events: list });
47
47
  },
48
+ async waitForEvent(id, opts) {
49
+ const h = ec.nextHash(id);
50
+ const memo = ec.steps[h];
51
+ if (memo && memo.status === "completed") {
52
+ if (memo.output == null)
53
+ return null; // 超时分支:平台以 output=JSON null 完成
54
+ return memo.output;
55
+ }
56
+ if (!opts.event)
57
+ throw new Error(`step.waitForEvent "${id}": event is required`);
58
+ throw new StepInterrupt({
59
+ op: "WaitForEvent",
60
+ id: h,
61
+ step_id: id,
62
+ event: opts.event,
63
+ match: opts.match,
64
+ timeout: typeof opts.timeout === "number" ? msToGoDuration(opts.timeout) : opts.timeout,
65
+ });
66
+ },
48
67
  };
49
68
  }
69
+ /** 毫秒 → Go duration 字符串(协议要求 timeout 为 Go duration,如 1500 → "1.5s")。 */
70
+ function msToGoDuration(ms) {
71
+ if (!Number.isFinite(ms) || ms <= 0) {
72
+ throw new Error(`step.waitForEvent: invalid timeout ${ms}`);
73
+ }
74
+ return `${ms / 1000}s`;
75
+ }
50
76
  export function errMessage(err) {
51
77
  return err instanceof Error ? err.message : String(err);
52
78
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@triggerlink/sdk",
3
- "version": "0.4.8",
3
+ "version": "0.5.0",
4
4
  "description": "TriggerLink TypeScript SDK: durable, crash-recoverable functions for Next.js / Node.js",
5
5
  "keywords": [
6
6
  "triggerlink",