@trigora/sdk 0.9.0 → 1.0.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/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @trigora/sdk
2
2
 
3
- Flow authoring for Trigora.
3
+ TypeScript authoring SDK for Trigora durable programs.
4
4
 
5
- `@trigora/sdk` is the package most Trigora users write against directly. It provides `defineFlow` plus the shared runtime types needed to author flows with good TypeScript ergonomics.
5
+ Build long-running programs that can call external systems, wait for events, sleep durably, invoke child executions, and recover from committed continuation state.
6
6
 
7
7
  ## Install
8
8
 
@@ -10,314 +10,105 @@ Flow authoring for Trigora.
10
10
  npm install @trigora/sdk
11
11
  ```
12
12
 
13
- Most projects will install the CLI alongside it:
14
-
15
- ```bash
16
- npm install trigora @trigora/sdk
17
- ```
18
-
19
- ## Basic Usage
13
+ ## Quick example
20
14
 
21
15
  ```ts
22
- import { defineFlow } from '@trigora/sdk';
23
-
24
- export default defineFlow({
25
- id: 'hello',
26
- trigger: { type: 'manual' },
27
- async run(event, ctx) {
28
- await ctx.log.info('Hello from Trigora', event.payload);
29
- },
30
- });
31
- ```
32
-
33
- ## What `defineFlow` Gives You
34
-
35
- `defineFlow` helps with:
36
-
37
- - typed flow definitions
38
- - typed trigger variants
39
- - typed event payload access
40
- - typed runtime context
41
- - trigger-aware return types
42
- - compile-time validation of trigger shape
16
+ import { effect, waitForEvent } from '@trigora/sdk';
43
17
 
44
- The trigger typing is strict. If you mix properties from different trigger kinds, TypeScript will flag it.
18
+ export default async function approval(input) {
19
+ const result = await effect('generate', () => 42);
20
+ const review = await waitForEvent('approved');
45
21
 
46
- For example, this is invalid:
47
-
48
- ```ts
49
- import { defineFlow } from '@trigora/sdk';
50
-
51
- export default defineFlow({
52
- id: 'broken',
53
- trigger: {
54
- type: 'webhook',
55
- cron: '* * * * *',
56
- },
57
- async run() {
58
- return 'nope';
59
- },
60
- });
22
+ return { result, review };
23
+ }
61
24
  ```
62
25
 
63
- ## Trigger Types
64
-
65
- ### Manual
66
-
67
- Use manual triggers for local invocation and testing.
26
+ Run it locally with:
68
27
 
69
- ```ts
70
- import { defineFlow } from '@trigora/sdk';
71
-
72
- export default defineFlow({
73
- id: 'hello',
74
- trigger: { type: 'manual' },
75
- async run(event, ctx) {
76
- await ctx.log.info('Triggered manually', event.payload);
77
- },
78
- });
28
+ ```bash
29
+ trigora dev
30
+ trigora start approval --input '{"request":"example"}'
79
31
  ```
80
32
 
81
- ### Webhook
33
+ ## Program entry
82
34
 
83
- Use webhook triggers for hosted HTTP entrypoints.
35
+ Trigora discovers programs from the paths configured in `trigora.toml`:
84
36
 
85
- ```ts
86
- import { defineFlow } from '@trigora/sdk';
87
-
88
- export default defineFlow({
89
- id: 'stripe-webhook',
90
- trigger: { type: 'webhook', route: '/hooks/stripe' },
91
- async run() {
92
- return 'pong';
93
- },
94
- });
37
+ ```toml
38
+ [project]
39
+ name = "my-project"
40
+ programs = ["src/**/*.ts"]
95
41
  ```
96
42
 
97
- `id` is the internal flow identifier used by the CLI. `route` is the optional public hosted webhook path.
98
- When `route` is omitted, hosted ingress defaults to `/${id}`.
99
-
100
- You can also include an optional event name:
43
+ Each matching file default-exports one async program entry.
101
44
 
102
45
  ```ts
103
- trigger: { type: 'webhook', event: 'orders.created', route: '/hooks/orders' }
46
+ export default async function research(topic, depth = topic) {
47
+ // ...
48
+ }
104
49
  ```
105
50
 
106
- ### Cron
107
-
108
- Use cron triggers for scheduled work.
109
-
110
- ```ts
111
- import { defineFlow } from '@trigora/sdk';
112
-
113
- export default defineFlow({
114
- id: 'nightly-sync',
115
- trigger: { type: 'cron', cron: '0 2 * * *' },
116
- async run(event, ctx) {
117
- await ctx.log.info('Nightly sync started', event.payload);
118
- },
119
- });
120
- ```
51
+ The TypeScript frontend implements `ts.subset.v1`.
121
52
 
122
- ### Queue
53
+ Program parameters may be plain identifiers. Defaults may reference earlier parameters only. Missing arguments remain `undefined` unless a supported default applies, and extra arguments are ignored.
123
54
 
124
- Use queue triggers to consume workspace-scoped queue messages. Deploy auto-provisions and binds the named queue to the flow.
55
+ Rest parameters and optional `?` parameters are not supported.
125
56
 
126
- Optional `retry` configures how many times a failed message may be redelivered. Omitted `retry` means a single attempt. `attempts > 1` is supported for queue flows only.
57
+ An anonymous default export is also valid:
127
58
 
128
59
  ```ts
129
- import { defineFlow } from '@trigora/sdk';
130
-
131
- export default defineFlow({
132
- id: 'process-image',
133
- trigger: { type: 'queue', queue: 'image-processing' },
134
- retry: { attempts: 5, backoff: 'exponential' },
135
- async run(event, ctx) {
136
- await ctx.log.info('Processing message', {
137
- queue: event.queue,
138
- messageId: event.messageId,
139
- attempt: event.attempt,
140
- maxAttempts: event.maxAttempts,
141
- payload: event.payload,
142
- });
143
- },
144
- });
60
+ export default async function () {
61
+ // ...
62
+ }
145
63
  ```
146
64
 
147
- Locally, `trigora trigger` and `trigora dev` invoke queue flows with a synthetic `QueueFlowEvent` (`messageId` starts with `local_`, `attempt` is `1`, and `maxAttempts` comes from `retry.attempts` or `1`). Local runs do not actually retry. Hosted runs use the real message id and attempt count.
148
-
149
- ## Return Types
150
-
151
- Return values are trigger-aware.
152
-
153
- ### Webhook flows
154
-
155
- Webhook flows can return HTTP-friendly values directly from `run`.
156
-
157
- Supported return values:
158
-
159
- - `Response`
160
- - plain objects, arrays, numbers, and booleans
161
- - `string`
162
- - `null`
163
- - `undefined`
164
-
165
- Example:
166
-
167
- ```ts
168
- import { defineFlow } from '@trigora/sdk';
169
-
170
- export default defineFlow({
171
- id: 'status',
172
- trigger: { type: 'webhook', route: '/status' },
173
- async run() {
174
- return {
175
- ok: true,
176
- service: 'trigora',
177
- };
178
- },
179
- });
180
- ```
65
+ Its artifact entry name is `"default"`.
181
66
 
182
- ### Manual, cron, and queue flows
67
+ ## Durable primitives
183
68
 
184
- Manual, cron, and queue flows do not use return values. Their `run` functions are typed as `void`.
69
+ - `effect(name, fn)` — run a durable external effect
70
+ - `sleep(ms)` — suspend on a durable timer
71
+ - `waitForEvent(name)` — wait for an external event
72
+ - `invoke(program, input)` — invoke a durable child execution
73
+ - `execution.id` — current execution id
74
+ - `execution.attempt` — current attempt
75
+ - `execution.signal` — execution cancellation signal
185
76
 
186
- This matches how Trigora uses them:
77
+ Effect keys and event names are string literals in the current TypeScript subset.
187
78
 
188
- - manual flows are invoked locally for testing and development
189
- - cron flows are background-style scheduled jobs
190
- - queue flows consume workspace queue messages
191
- - webhook flows are request-response flows
79
+ ## Local development
192
80
 
193
- ## Event Shape
194
-
195
- Flows receive an event object:
196
-
197
- ```ts
198
- type FlowEvent<TPayload = JsonValue> = {
199
- id: string;
200
- type: string;
201
- timestamp: string;
202
- payload: TPayload;
203
- request?: {
204
- headers: Record<string, string>;
205
- method: string;
206
- url: string;
207
- rawBody: string;
208
- };
209
- };
210
- ```
211
-
212
- Queue events also include:
213
-
214
- ```ts
215
- queue: string;
216
- messageId: string;
217
- attempt: number; // 1-based delivery count
218
- maxAttempts: number; // from retry.attempts, or 1 when omitted
219
- ```
220
-
221
- In local manual runs, the payload comes from your JSON payload file when one is provided. In local webhook dev and deployed webhook flows, the payload is the parsed JSON request body.
222
-
223
- If you do not provide your own payload type, `event.payload` defaults to `JsonValue`.
224
-
225
- For webhook flows, request metadata may also be available on `event.request`, including headers, method, URL, and the raw request body. `event.request.rawBody` is useful when you want to verify webhook signatures yourself.
226
-
227
- ## Stripe Webhooks
228
-
229
- Trigora includes a small helper for verifying Stripe webhook signatures:
230
-
231
- ```ts
232
- import { defineFlow } from '@trigora/sdk';
233
- import { verifyStripeWebhook } from '@trigora/sdk/stripe';
234
-
235
- export default defineFlow({
236
- id: 'stripe-webhook',
237
- trigger: { type: 'webhook', route: '/hooks/stripe' },
238
- async run(event, ctx) {
239
- await verifyStripeWebhook(event, {
240
- secret: ctx.env.STRIPE_WEBHOOK_SECRET,
241
- });
242
-
243
- return { ok: true };
244
- },
245
- });
81
+ ```bash
82
+ trigora init
83
+ trigora dev
84
+ trigora start approval
85
+ trigora send <execution> approved --payload '"ok"'
86
+ trigora result <execution>
246
87
  ```
247
88
 
248
- This verifies against `event.request.rawBody` and the `Stripe-Signature` header.
249
-
250
- Production Stripe webhooks should verify signatures before trusting payloads.
89
+ Programs execute through the Trigora runtime rather than by running the source file directly.
251
90
 
252
- ## GitHub Webhooks
91
+ ## Typed events
253
92
 
254
- Trigora includes a small helper for verifying GitHub webhook signatures:
93
+ `event()` can be used to define typed events shared between program and client code.
255
94
 
256
- ```ts
257
- import { defineFlow } from '@trigora/sdk';
258
- import { verifyGitHubWebhook } from '@trigora/sdk/github';
259
-
260
- export default defineFlow({
261
- id: 'github-webhook',
262
- trigger: { type: 'webhook', route: '/hooks/github' },
263
- async run(event, ctx) {
264
- await verifyGitHubWebhook(event, {
265
- secret: ctx.env.GITHUB_WEBHOOK_SECRET,
266
- });
267
-
268
- return { ok: true };
269
- },
270
- });
271
- ```
95
+ ## Integrations
272
96
 
273
- This verifies against `event.request.rawBody` and the `X-Hub-Signature-256` header.
274
-
275
- ## Context
276
-
277
- Flows receive a context object with logging and environment access:
97
+ Webhook signature helpers are available at:
278
98
 
279
99
  ```ts
280
- ctx.log.info('message')
281
- ctx.log.warn('message')
282
- ctx.log.error('message')
283
-
284
- ctx.env
100
+ @trigora/sdk/stripe
101
+ @trigora/sdk/github
285
102
  ```
286
103
 
287
- In local CLI runs, `ctx.env` includes the process environment after loading `.env` and `.env.local`, with existing shell variables taking precedence.
288
-
289
- The exact exported type is `FlowContext<TEnv>`.
290
-
291
- ## Exported Types
292
-
293
- `@trigora/sdk` re-exports the main flow authoring types from `@trigora/contracts`:
294
-
295
- - `FlowContext`
296
- - `FlowDefinition`
297
- - `FlowEvent`
298
- - `FlowRunFn`
299
- - `JsonValue`
300
- - `RetryPolicy`
301
- - `Trigger`
302
- - `WebhookFlowResult`
303
-
304
- That means most flow authors can stay entirely within `@trigora/sdk`.
305
-
306
- ## Typical Workflow
307
-
308
- 1. Define a flow with `defineFlow`
309
- 2. Run it locally with:
310
- - `trigora trigger hello --payload payload.json` for one-off runs
311
- - `trigora dev hello --payload payload.json` for manual or payload watch mode
312
- - `trigora dev stripe-checkout` for a local webhook server
313
- 3. Deploy webhook flows with `trigora deploy`
314
- 4. Manage hosted flows with `trigora flows`
104
+ These are optional TypeScript convenience utilities.
315
105
 
316
- ## Related Packages
106
+ ## Learn more
317
107
 
318
- - `trigora` - CLI for local development and hosted deploys
319
- - `@trigora/contracts` - shared public types used by the SDK, CLI, and API consumers
108
+ - [Quickstart](https://trigora.dev/docs/quickstart)
109
+ - [Trigora documentation](https://trigora.dev/docs)
110
+ - [TCC TypeScript semantics](https://github.com/trigora-dev/tcc-engine/blob/main/spec/typescript-subset.md)
320
111
 
321
112
  ## License
322
113
 
323
- MIT
114
+ MIT © 2026 Trigora, Inc.
@@ -0,0 +1,70 @@
1
+ // src/webhookSignature.ts
2
+ function encodeUtf8(value) {
3
+ return new TextEncoder().encode(value);
4
+ }
5
+ function toArrayBuffer(bytes) {
6
+ return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
7
+ }
8
+ function bytesToHex(bytes) {
9
+ return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
10
+ }
11
+ function getHeaderCaseInsensitive(headers, headerName) {
12
+ const normalizedName = headerName.toLowerCase();
13
+ for (const [key, value] of Object.entries(headers)) {
14
+ if (key.toLowerCase() === normalizedName) {
15
+ return value;
16
+ }
17
+ }
18
+ return void 0;
19
+ }
20
+ function isHexString(value) {
21
+ return value.length > 0 && value.length % 2 === 0 && /^[0-9a-f]+$/i.test(value);
22
+ }
23
+ function timingSafeEqualStrings(left, right) {
24
+ const leftBytes = encodeUtf8(left);
25
+ const rightBytes = encodeUtf8(right);
26
+ const length = Math.max(leftBytes.length, rightBytes.length);
27
+ let difference = leftBytes.length === rightBytes.length ? 0 : 1;
28
+ for (let index = 0; index < length; index += 1) {
29
+ difference |= (leftBytes[index] ?? 0) ^ (rightBytes[index] ?? 0);
30
+ }
31
+ return difference === 0;
32
+ }
33
+ async function computeHmacSha256Hex(secret, signedPayload) {
34
+ const subtle = globalThis.crypto?.subtle;
35
+ if (!subtle) {
36
+ throw new Error("Web Crypto API is unavailable in this runtime.");
37
+ }
38
+ const key = await subtle.importKey(
39
+ "raw",
40
+ toArrayBuffer(encodeUtf8(secret)),
41
+ {
42
+ name: "HMAC",
43
+ hash: "SHA-256"
44
+ },
45
+ false,
46
+ ["sign"]
47
+ );
48
+ const signature = await subtle.sign("HMAC", key, toArrayBuffer(encodeUtf8(signedPayload)));
49
+ return bytesToHex(new Uint8Array(signature));
50
+ }
51
+ function requireWebhookRequestParts(event, providerName) {
52
+ if (!event.request || typeof event.request.headers !== "object" || event.request.headers === null) {
53
+ throw new Error(`${providerName} webhook request metadata is required.`);
54
+ }
55
+ if (typeof event.request.rawBody !== "string") {
56
+ throw new Error(`${providerName} webhook raw body is required.`);
57
+ }
58
+ return {
59
+ headers: event.request.headers,
60
+ rawBody: event.request.rawBody
61
+ };
62
+ }
63
+
64
+ export {
65
+ getHeaderCaseInsensitive,
66
+ isHexString,
67
+ timingSafeEqualStrings,
68
+ computeHmacSha256Hex,
69
+ requireWebhookRequestParts
70
+ };
@@ -0,0 +1,20 @@
1
+ // src/runtimeHost.ts
2
+ import { AsyncLocalStorage } from "async_hooks";
3
+ var runtimeStorage = new AsyncLocalStorage();
4
+ function runWithDurableRuntime(host, fn) {
5
+ return runtimeStorage.run(host, fn);
6
+ }
7
+ function getDurableRuntimeHost() {
8
+ const host = runtimeStorage.getStore();
9
+ if (!host) {
10
+ throw new Error(
11
+ "Durable primitives can only run inside a Trigora execution. Start the program with `@trigora/client` while `trigora dev` is running."
12
+ );
13
+ }
14
+ return host;
15
+ }
16
+
17
+ export {
18
+ runWithDurableRuntime,
19
+ getDurableRuntimeHost
20
+ };
@@ -0,0 +1 @@
1
+ export declare function effect<T>(name: string, run: () => T | Promise<T>): Promise<T>;
@@ -0,0 +1,4 @@
1
+ import { resolveEventName, type EventDefinition } from '@trigora/contracts';
2
+ export type { EventDefinition };
3
+ export { resolveEventName };
4
+ export declare function event<TPayload = unknown>(name: string): EventDefinition<TPayload>;
@@ -0,0 +1,3 @@
1
+ import { type ExecutionInfo } from './runtimeHost';
2
+ export type { ExecutionInfo };
3
+ export declare const execution: ExecutionInfo;
package/dist/github.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import type { WebhookFlowEvent } from '@trigora/contracts';
1
+ import type { WebhookRequest } from './webhookSignature';
2
2
  export type VerifyGitHubWebhookOptions = {
3
3
  secret: string | undefined;
4
4
  };
5
5
  export declare class GitHubWebhookVerificationError extends Error {
6
6
  name: string;
7
7
  }
8
- export declare function verifyGitHubWebhook<T = unknown>(event: WebhookFlowEvent, options: VerifyGitHubWebhookOptions): Promise<T>;
8
+ export declare function verifyGitHubWebhook<T = unknown>(event: WebhookRequest, options: VerifyGitHubWebhookOptions): Promise<T>;
package/dist/github.js CHANGED
@@ -1,65 +1,10 @@
1
- // src/webhookSignature.ts
2
- function encodeUtf8(value) {
3
- return new TextEncoder().encode(value);
4
- }
5
- function toArrayBuffer(bytes) {
6
- return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
7
- }
8
- function bytesToHex(bytes) {
9
- return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
10
- }
11
- function getHeaderCaseInsensitive(headers, headerName) {
12
- const normalizedName = headerName.toLowerCase();
13
- for (const [key, value] of Object.entries(headers)) {
14
- if (key.toLowerCase() === normalizedName) {
15
- return value;
16
- }
17
- }
18
- return void 0;
19
- }
20
- function isHexString(value) {
21
- return value.length > 0 && value.length % 2 === 0 && /^[0-9a-f]+$/i.test(value);
22
- }
23
- function timingSafeEqualStrings(left, right) {
24
- const leftBytes = encodeUtf8(left);
25
- const rightBytes = encodeUtf8(right);
26
- const length = Math.max(leftBytes.length, rightBytes.length);
27
- let difference = leftBytes.length === rightBytes.length ? 0 : 1;
28
- for (let index = 0; index < length; index += 1) {
29
- difference |= (leftBytes[index] ?? 0) ^ (rightBytes[index] ?? 0);
30
- }
31
- return difference === 0;
32
- }
33
- async function computeHmacSha256Hex(secret, signedPayload) {
34
- const subtle = globalThis.crypto?.subtle;
35
- if (!subtle) {
36
- throw new Error("Web Crypto API is unavailable in this runtime.");
37
- }
38
- const key = await subtle.importKey(
39
- "raw",
40
- toArrayBuffer(encodeUtf8(secret)),
41
- {
42
- name: "HMAC",
43
- hash: "SHA-256"
44
- },
45
- false,
46
- ["sign"]
47
- );
48
- const signature = await subtle.sign("HMAC", key, toArrayBuffer(encodeUtf8(signedPayload)));
49
- return bytesToHex(new Uint8Array(signature));
50
- }
51
- function requireWebhookRequestParts(event, providerName) {
52
- if (!event.request || typeof event.request.headers !== "object" || event.request.headers === null) {
53
- throw new Error(`${providerName} webhook request metadata is required.`);
54
- }
55
- if (typeof event.request.rawBody !== "string") {
56
- throw new Error(`${providerName} webhook raw body is required.`);
57
- }
58
- return {
59
- headers: event.request.headers,
60
- rawBody: event.request.rawBody
61
- };
62
- }
1
+ import {
2
+ computeHmacSha256Hex,
3
+ getHeaderCaseInsensitive,
4
+ isHexString,
5
+ requireWebhookRequestParts,
6
+ timingSafeEqualStrings
7
+ } from "./chunk-6GNCTPSN.js";
63
8
 
64
9
  // src/github.ts
65
10
  var GITHUB_SIGNATURE_HEADER = "x-hub-signature-256";
package/dist/index.d.ts CHANGED
@@ -1,2 +1,13 @@
1
- export { defineFlow } from './defineFlow';
2
- export type { CronEventPayload, CronFlowEvent, FlowContext, FlowDefinition, FlowEvent, FlowRunFn, JsonValue, ManualFlowEvent, QueueFlowEvent, RetryBackoff, RetryPolicy, Trigger, WebhookFlowEvent, WebhookFlowResult, } from '@trigora/contracts';
1
+ export { effect } from './effect';
2
+ export { event, resolveEventName } from './event';
3
+ export { execution } from './execution';
4
+ export { invoke } from './invoke';
5
+ export { resolveProgramId } from './program';
6
+ export { sleep } from './sleep';
7
+ export { waitForEvent } from './waitForEvent';
8
+ export type { EventDefinition } from './event';
9
+ export type { ExecutionInfo } from './execution';
10
+ export type { DurableProgram } from './program';
11
+ export type { DurableRuntimeHost } from './runtimeHost';
12
+ export type { WaitForEventOptions } from './waitForEvent';
13
+ export type { ArtifactIdentity, Execution, ExecutionStatus, ExecutionWait, JsonValue, ProgramIdentity, } from '@trigora/contracts';
package/dist/index.js CHANGED
@@ -1,7 +1,68 @@
1
- // src/defineFlow.ts
2
- function defineFlow(flow) {
3
- return flow;
1
+ import {
2
+ getDurableRuntimeHost
3
+ } from "./chunk-JYNY75DO.js";
4
+
5
+ // src/effect.ts
6
+ function effect(name, run) {
7
+ if (typeof name !== "string" || name.trim() === "") {
8
+ throw new Error("effect(name, fn) requires a non-empty string key.");
9
+ }
10
+ if (typeof run !== "function") {
11
+ throw new Error("effect(name, fn) requires a function.");
12
+ }
13
+ return getDurableRuntimeHost().effect(name, run);
14
+ }
15
+
16
+ // src/event.ts
17
+ import { resolveEventName } from "@trigora/contracts";
18
+ function event(name) {
19
+ const trimmed = name.trim();
20
+ if (!trimmed) {
21
+ throw new Error("Event name must be a non-empty string.");
22
+ }
23
+ return { name: trimmed };
24
+ }
25
+
26
+ // src/execution.ts
27
+ var execution = {
28
+ get id() {
29
+ return getDurableRuntimeHost().getExecution().id;
30
+ },
31
+ get attempt() {
32
+ return getDurableRuntimeHost().getExecution().attempt;
33
+ },
34
+ get programId() {
35
+ return getDurableRuntimeHost().getExecution().programId;
36
+ },
37
+ get signal() {
38
+ return getDurableRuntimeHost().getExecution().signal;
39
+ }
40
+ };
41
+
42
+ // src/program.ts
43
+ import { resolveProgramId } from "@trigora/contracts";
44
+
45
+ // src/invoke.ts
46
+ function invoke(program, input) {
47
+ return getDurableRuntimeHost().invoke(resolveProgramId(program), input);
48
+ }
49
+
50
+ // src/sleep.ts
51
+ function sleep(duration) {
52
+ return getDurableRuntimeHost().sleep(duration);
53
+ }
54
+
55
+ // src/waitForEvent.ts
56
+ function waitForEvent(eventOrName, options) {
57
+ return getDurableRuntimeHost().waitForEvent(resolveEventName(eventOrName), options);
4
58
  }
5
59
  export {
6
- defineFlow
60
+ effect,
61
+ event,
62
+ execution,
63
+ invoke,
64
+ resolveEventName,
65
+ resolveProgramId,
66
+ sleep,
67
+ waitForEvent
7
68
  };
@@ -0,0 +1,2 @@
1
+ import type { DurableProgram } from './program';
2
+ export declare function invoke<TInput, TResult>(program: DurableProgram<TInput, TResult> | string, input: TInput): Promise<TResult>;
@@ -0,0 +1 @@
1
+ export { resolveProgramId, type DurableProgram } from '@trigora/contracts';
@@ -0,0 +1 @@
1
+ export { getDurableRuntimeHost, runWithDurableRuntime, type DurableRuntimeHost, type ExecutionInfo, } from './runtimeHost';
@@ -0,0 +1,8 @@
1
+ import {
2
+ getDurableRuntimeHost,
3
+ runWithDurableRuntime
4
+ } from "./chunk-JYNY75DO.js";
5
+ export {
6
+ getDurableRuntimeHost,
7
+ runWithDurableRuntime
8
+ };
@@ -0,0 +1,17 @@
1
+ import type { JsonValue, WaitForEventOptions } from '@trigora/contracts';
2
+ export type ExecutionInfo = {
3
+ id: string;
4
+ attempt: number;
5
+ programId: string;
6
+ signal: AbortSignal;
7
+ };
8
+ export type DurableRuntimeHost = {
9
+ effect<T>(name: string, run: () => T | Promise<T>): Promise<T>;
10
+ sleep(duration: string | number): Promise<void>;
11
+ waitForEvent<T>(name: string, options?: WaitForEventOptions): Promise<T>;
12
+ invoke<TInput, TResult>(programId: string, input: TInput): Promise<TResult>;
13
+ getExecution(): ExecutionInfo;
14
+ };
15
+ export declare function runWithDurableRuntime<T>(host: DurableRuntimeHost, fn: () => Promise<T>): Promise<T>;
16
+ export declare function getDurableRuntimeHost(): DurableRuntimeHost;
17
+ export type { JsonValue, WaitForEventOptions };
@@ -0,0 +1 @@
1
+ export declare function sleep(duration: string | number): Promise<void>;
package/dist/stripe.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { WebhookFlowEvent } from '@trigora/contracts';
1
+ import type { WebhookRequest } from './webhookSignature';
2
2
  export type VerifyStripeWebhookOptions = {
3
3
  secret: string | undefined;
4
4
  toleranceSeconds?: number;
@@ -6,4 +6,4 @@ export type VerifyStripeWebhookOptions = {
6
6
  export declare class StripeWebhookVerificationError extends Error {
7
7
  name: string;
8
8
  }
9
- export declare function verifyStripeWebhook<T = unknown>(event: WebhookFlowEvent, options: VerifyStripeWebhookOptions): Promise<T>;
9
+ export declare function verifyStripeWebhook<T = unknown>(event: WebhookRequest, options: VerifyStripeWebhookOptions): Promise<T>;
package/dist/stripe.js CHANGED
@@ -1,65 +1,10 @@
1
- // src/webhookSignature.ts
2
- function encodeUtf8(value) {
3
- return new TextEncoder().encode(value);
4
- }
5
- function toArrayBuffer(bytes) {
6
- return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
7
- }
8
- function bytesToHex(bytes) {
9
- return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
10
- }
11
- function getHeaderCaseInsensitive(headers, headerName) {
12
- const normalizedName = headerName.toLowerCase();
13
- for (const [key, value] of Object.entries(headers)) {
14
- if (key.toLowerCase() === normalizedName) {
15
- return value;
16
- }
17
- }
18
- return void 0;
19
- }
20
- function isHexString(value) {
21
- return value.length > 0 && value.length % 2 === 0 && /^[0-9a-f]+$/i.test(value);
22
- }
23
- function timingSafeEqualStrings(left, right) {
24
- const leftBytes = encodeUtf8(left);
25
- const rightBytes = encodeUtf8(right);
26
- const length = Math.max(leftBytes.length, rightBytes.length);
27
- let difference = leftBytes.length === rightBytes.length ? 0 : 1;
28
- for (let index = 0; index < length; index += 1) {
29
- difference |= (leftBytes[index] ?? 0) ^ (rightBytes[index] ?? 0);
30
- }
31
- return difference === 0;
32
- }
33
- async function computeHmacSha256Hex(secret, signedPayload) {
34
- const subtle = globalThis.crypto?.subtle;
35
- if (!subtle) {
36
- throw new Error("Web Crypto API is unavailable in this runtime.");
37
- }
38
- const key = await subtle.importKey(
39
- "raw",
40
- toArrayBuffer(encodeUtf8(secret)),
41
- {
42
- name: "HMAC",
43
- hash: "SHA-256"
44
- },
45
- false,
46
- ["sign"]
47
- );
48
- const signature = await subtle.sign("HMAC", key, toArrayBuffer(encodeUtf8(signedPayload)));
49
- return bytesToHex(new Uint8Array(signature));
50
- }
51
- function requireWebhookRequestParts(event, providerName) {
52
- if (!event.request || typeof event.request.headers !== "object" || event.request.headers === null) {
53
- throw new Error(`${providerName} webhook request metadata is required.`);
54
- }
55
- if (typeof event.request.rawBody !== "string") {
56
- throw new Error(`${providerName} webhook raw body is required.`);
57
- }
58
- return {
59
- headers: event.request.headers,
60
- rawBody: event.request.rawBody
61
- };
62
- }
1
+ import {
2
+ computeHmacSha256Hex,
3
+ getHeaderCaseInsensitive,
4
+ isHexString,
5
+ requireWebhookRequestParts,
6
+ timingSafeEqualStrings
7
+ } from "./chunk-6GNCTPSN.js";
63
8
 
64
9
  // src/stripe.ts
65
10
  var DEFAULT_TOLERANCE_SECONDS = 300;
@@ -0,0 +1,3 @@
1
+ import type { EventDefinition, WaitForEventOptions } from '@trigora/contracts';
2
+ export type { WaitForEventOptions };
3
+ export declare function waitForEvent<TPayload>(eventOrName: EventDefinition<TPayload> | string, options?: WaitForEventOptions): Promise<TPayload>;
@@ -1,4 +1,12 @@
1
- import type { WebhookFlowEvent } from '@trigora/contracts';
1
+ export type WebhookRequest = {
2
+ request: {
3
+ headers: Record<string, string>;
4
+ rawBody: string;
5
+ method?: string;
6
+ url?: string;
7
+ };
8
+ payload?: unknown;
9
+ };
2
10
  export declare function encodeUtf8(value: string): Uint8Array;
3
11
  export declare function toArrayBuffer(bytes: Uint8Array): ArrayBuffer;
4
12
  export declare function bytesToHex(bytes: Uint8Array): string;
@@ -6,7 +14,7 @@ export declare function getHeaderCaseInsensitive(headers: Record<string, string>
6
14
  export declare function isHexString(value: string): boolean;
7
15
  export declare function timingSafeEqualStrings(left: string, right: string): boolean;
8
16
  export declare function computeHmacSha256Hex(secret: string, signedPayload: string): Promise<string>;
9
- export declare function requireWebhookRequestParts(event: WebhookFlowEvent, providerName: string): {
17
+ export declare function requireWebhookRequestParts(event: WebhookRequest, providerName: string): {
10
18
  headers: Record<string, string>;
11
19
  rawBody: string;
12
20
  };
package/package.json CHANGED
@@ -1,25 +1,21 @@
1
1
  {
2
2
  "name": "@trigora/sdk",
3
- "version": "0.9.0",
3
+ "version": "1.0.0",
4
+ "description": "TypeScript authoring SDK for Trigora durable programs.",
4
5
  "repository": {
5
6
  "type": "git",
6
- "url": "https://github.com/trigora-dev/trigora"
7
+ "url": "https://github.com/trigora-dev/trigora-typescript"
7
8
  },
8
9
  "homepage": "https://trigora.dev/",
9
10
  "bugs": {
10
- "url": "https://github.com/trigora-dev/trigora/issues"
11
+ "url": "https://github.com/trigora-dev/trigora-typescript/issues"
11
12
  },
12
13
  "keywords": [
13
- "automation",
14
- "workflow",
15
- "event-driven",
16
- "developer-tools",
14
+ "durable-execution",
17
15
  "typescript",
18
- "cli",
19
- "triggers",
20
- "cron",
21
- "queues",
22
- "webhooks"
16
+ "workflows",
17
+ "agents",
18
+ "developer-tools"
23
19
  ],
24
20
  "license": "MIT",
25
21
  "type": "module",
@@ -37,6 +33,10 @@
37
33
  "./stripe": {
38
34
  "types": "./dist/stripe.d.ts",
39
35
  "default": "./dist/stripe.js"
36
+ },
37
+ "./runtime": {
38
+ "types": "./dist/runtime.d.ts",
39
+ "default": "./dist/runtime.js"
40
40
  }
41
41
  },
42
42
  "files": [
@@ -45,12 +45,6 @@
45
45
  "publishConfig": {
46
46
  "access": "public"
47
47
  },
48
- "dependencies": {
49
- "@trigora/contracts": "^0.9.0"
50
- },
51
- "devDependencies": {
52
- "tsup": "^8.5.1"
53
- },
54
48
  "scripts": {
55
49
  "build": "pnpm run build:js && pnpm run build:types",
56
50
  "build:js": "tsup",
@@ -59,5 +53,11 @@
59
53
  "test": "vitest run",
60
54
  "test:coverage": "vitest run --coverage",
61
55
  "typecheck": "tsc --noEmit"
56
+ },
57
+ "dependencies": {
58
+ "@trigora/contracts": "1.0.0"
59
+ },
60
+ "devDependencies": {
61
+ "tsup": "^8.5.1"
62
62
  }
63
- }
63
+ }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Trigora
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1,53 +0,0 @@
1
- import type { CronEventPayload, CronFlowDefinition, FlowDefinition, FlowRunFn, JsonValue, ManualFlowDefinition, ManualTrigger, QueueFlowDefinition, QueueTrigger, RetryPolicy, Trigger, WebhookTrigger, WebhookFlowDefinition, CronTrigger } from '@trigora/contracts';
2
- type DefineFlowInput<TPayload, TEnv extends Record<string, string>, TTrigger extends Trigger> = {
3
- id: string;
4
- trigger: TTrigger;
5
- /**
6
- * Optional retry policy. Omitted means a single attempt.
7
- * `attempts > 1` is supported for queue flows only (enforced at deploy time).
8
- */
9
- retry?: RetryPolicy;
10
- run: TTrigger extends ManualTrigger ? FlowRunFn<TPayload, TEnv, ManualTrigger> : TTrigger extends WebhookTrigger ? FlowRunFn<TPayload, TEnv, WebhookTrigger> : TTrigger extends CronTrigger ? FlowRunFn<CronEventPayload, TEnv, CronTrigger> : TTrigger extends QueueTrigger ? FlowRunFn<TPayload, TEnv, QueueTrigger> : never;
11
- };
12
- type DefineFlowOutput<TPayload, TEnv extends Record<string, string>, TTrigger extends Trigger> = TTrigger extends ManualTrigger ? ManualFlowDefinition<TPayload, TEnv> : TTrigger extends WebhookTrigger ? WebhookFlowDefinition<TPayload, TEnv> : TTrigger extends CronTrigger ? CronFlowDefinition<TEnv> : TTrigger extends QueueTrigger ? QueueFlowDefinition<TPayload, TEnv> : FlowDefinition<TPayload, TEnv, TTrigger>;
13
- /**
14
- * Define a Trigora flow.
15
- *
16
- * Flows are plain TypeScript modules with three core parts:
17
- * - `id`: the internal identifier for the flow in your project
18
- * - `trigger`: how the flow is invoked
19
- * - `run`: the function that executes when the flow is triggered
20
- * - `retry`: optional retry policy (queue flows may use `attempts > 1`)
21
- *
22
- * `run` receives the incoming `event` and a `ctx` object with logging and environment access.
23
- *
24
- * For webhook flows, `trigger.route` controls the public hosted path and defaults to `/${id}`.
25
- * This is separate from the flow `id`, which is still what the CLI uses for commands like
26
- * `trigora deploy hello` or `trigora flows inspect hello`.
27
- *
28
- * Webhook flows can return HTTP-friendly values:
29
- * - `Response`
30
- * - plain objects / arrays / numbers / booleans
31
- * - `string`
32
- * - `null` or `undefined`
33
- *
34
- * Other trigger types generally do not need to return anything meaningful.
35
- *
36
- * @example
37
- * ```ts
38
- * export default defineFlow({
39
- * id: 'stripe-webhook',
40
- * trigger: { type: 'webhook', route: '/hooks/stripe' },
41
- * async run(event, ctx) {
42
- * await ctx.log.info('Received event', event.payload);
43
- * return { ok: true };
44
- * },
45
- * });
46
- * ```
47
- */
48
- export declare function defineFlow<TTrigger extends Trigger, TPayload = JsonValue, TEnv extends Record<string, string> = Record<string, string>>(flow: DefineFlowInput<TPayload, TEnv, TTrigger>): DefineFlowOutput<TPayload, TEnv, TTrigger>;
49
- export declare function defineFlow<TPayload = JsonValue, TEnv extends Record<string, string> = Record<string, string>>(flow: ManualFlowDefinition<TPayload, TEnv>): ManualFlowDefinition<TPayload, TEnv>;
50
- export declare function defineFlow<TPayload = JsonValue, TEnv extends Record<string, string> = Record<string, string>>(flow: WebhookFlowDefinition<TPayload, TEnv>): WebhookFlowDefinition<TPayload, TEnv>;
51
- export declare function defineFlow<TEnv extends Record<string, string> = Record<string, string>>(flow: CronFlowDefinition<TEnv>): CronFlowDefinition<TEnv>;
52
- export declare function defineFlow<TPayload = JsonValue, TEnv extends Record<string, string> = Record<string, string>>(flow: QueueFlowDefinition<TPayload, TEnv>): QueueFlowDefinition<TPayload, TEnv>;
53
- export {};