@trigora/sdk 0.8.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,299 +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:
16
+ import { effect, waitForEvent } from '@trigora/sdk';
36
17
 
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
18
+ export default async function approval(input) {
19
+ const result = await effect('generate', () => 42);
20
+ const review = await waitForEvent('approved');
43
21
 
44
- The trigger typing is strict. If you mix properties from different trigger kinds, TypeScript will flag it.
45
-
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.
68
-
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
- });
79
- ```
80
-
81
- ### Webhook
82
-
83
- Use webhook triggers for hosted HTTP entrypoints.
84
-
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
- });
95
- ```
96
-
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:
101
-
102
- ```ts
103
- trigger: { type: 'webhook', event: 'orders.created', route: '/hooks/orders' }
104
- ```
105
-
106
- ### Cron
107
-
108
- Use cron triggers for scheduled work.
26
+ Run it locally with:
109
27
 
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
- });
28
+ ```bash
29
+ trigora dev
30
+ trigora start approval --input '{"request":"example"}'
120
31
  ```
121
32
 
122
- ### Queue
33
+ ## Program entry
123
34
 
124
- Use queue triggers to consume workspace-scoped queue messages. Deploy auto-provisions and binds the named queue to the flow.
35
+ Trigora discovers programs from the paths configured in `trigora.toml`:
125
36
 
126
- ```ts
127
- import { defineFlow } from '@trigora/sdk';
128
-
129
- export default defineFlow({
130
- id: 'process-image',
131
- trigger: { type: 'queue', queue: 'image-processing' },
132
- async run(event, ctx) {
133
- await ctx.log.info('Processing message', {
134
- queue: event.queue,
135
- messageId: event.messageId,
136
- payload: event.payload,
137
- });
138
- },
139
- });
37
+ ```toml
38
+ [project]
39
+ name = "my-project"
40
+ programs = ["src/**/*.ts"]
140
41
  ```
141
42
 
142
- Locally, `trigora trigger` and `trigora dev` invoke queue flows with a synthetic `QueueFlowEvent` (`messageId` starts with `local_`). Hosted runs use the real message id.
143
-
144
- ## Return Types
145
-
146
- Return values are trigger-aware.
147
-
148
- ### Webhook flows
149
-
150
- Webhook flows can return HTTP-friendly values directly from `run`.
151
-
152
- Supported return values:
153
-
154
- - `Response`
155
- - plain objects, arrays, numbers, and booleans
156
- - `string`
157
- - `null`
158
- - `undefined`
159
-
160
- Example:
43
+ Each matching file default-exports one async program entry.
161
44
 
162
45
  ```ts
163
- import { defineFlow } from '@trigora/sdk';
164
-
165
- export default defineFlow({
166
- id: 'status',
167
- trigger: { type: 'webhook', route: '/status' },
168
- async run() {
169
- return {
170
- ok: true,
171
- service: 'trigora',
172
- };
173
- },
174
- });
46
+ export default async function research(topic, depth = topic) {
47
+ // ...
48
+ }
175
49
  ```
176
50
 
177
- ### Manual, cron, and queue flows
178
-
179
- Manual, cron, and queue flows do not use return values. Their `run` functions are typed as `void`.
51
+ The TypeScript frontend implements `ts.subset.v1`.
180
52
 
181
- This matches how Trigora uses them:
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.
182
54
 
183
- - manual flows are invoked locally for testing and development
184
- - cron flows are background-style scheduled jobs
185
- - queue flows consume workspace queue messages
186
- - webhook flows are request-response flows
55
+ Rest parameters and optional `?` parameters are not supported.
187
56
 
188
- ## Event Shape
189
-
190
- Flows receive an event object:
57
+ An anonymous default export is also valid:
191
58
 
192
59
  ```ts
193
- type FlowEvent<TPayload = JsonValue> = {
194
- id: string;
195
- type: string;
196
- timestamp: string;
197
- payload: TPayload;
198
- request?: {
199
- headers: Record<string, string>;
200
- method: string;
201
- url: string;
202
- rawBody: string;
203
- };
204
- };
60
+ export default async function () {
61
+ // ...
62
+ }
205
63
  ```
206
64
 
207
- 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.
65
+ Its artifact entry name is `"default"`.
208
66
 
209
- If you do not provide your own payload type, `event.payload` defaults to `JsonValue`.
67
+ ## Durable primitives
210
68
 
211
- 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.
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
212
76
 
213
- ## Stripe Webhooks
77
+ Effect keys and event names are string literals in the current TypeScript subset.
214
78
 
215
- Trigora includes a small helper for verifying Stripe webhook signatures:
79
+ ## Local development
216
80
 
217
- ```ts
218
- import { defineFlow } from '@trigora/sdk';
219
- import { verifyStripeWebhook } from '@trigora/sdk/stripe';
220
-
221
- export default defineFlow({
222
- id: 'stripe-webhook',
223
- trigger: { type: 'webhook', route: '/hooks/stripe' },
224
- async run(event, ctx) {
225
- await verifyStripeWebhook(event, {
226
- secret: ctx.env.STRIPE_WEBHOOK_SECRET,
227
- });
228
-
229
- return { ok: true };
230
- },
231
- });
81
+ ```bash
82
+ trigora init
83
+ trigora dev
84
+ trigora start approval
85
+ trigora send <execution> approved --payload '"ok"'
86
+ trigora result <execution>
232
87
  ```
233
88
 
234
- This verifies against `event.request.rawBody` and the `Stripe-Signature` header.
89
+ Programs execute through the Trigora runtime rather than by running the source file directly.
235
90
 
236
- Production Stripe webhooks should verify signatures before trusting payloads.
91
+ ## Typed events
237
92
 
238
- ## GitHub Webhooks
93
+ `event()` can be used to define typed events shared between program and client code.
239
94
 
240
- Trigora includes a small helper for verifying GitHub webhook signatures:
95
+ ## Integrations
241
96
 
242
- ```ts
243
- import { defineFlow } from '@trigora/sdk';
244
- import { verifyGitHubWebhook } from '@trigora/sdk/github';
245
-
246
- export default defineFlow({
247
- id: 'github-webhook',
248
- trigger: { type: 'webhook', route: '/hooks/github' },
249
- async run(event, ctx) {
250
- await verifyGitHubWebhook(event, {
251
- secret: ctx.env.GITHUB_WEBHOOK_SECRET,
252
- });
253
-
254
- return { ok: true };
255
- },
256
- });
257
- ```
258
-
259
- This verifies against `event.request.rawBody` and the `X-Hub-Signature-256` header.
260
-
261
- ## Context
262
-
263
- Flows receive a context object with logging and environment access:
97
+ Webhook signature helpers are available at:
264
98
 
265
99
  ```ts
266
- ctx.log.info('message')
267
- ctx.log.warn('message')
268
- ctx.log.error('message')
269
-
270
- ctx.env
100
+ @trigora/sdk/stripe
101
+ @trigora/sdk/github
271
102
  ```
272
103
 
273
- In local CLI runs, `ctx.env` includes the process environment after loading `.env` and `.env.local`, with existing shell variables taking precedence.
274
-
275
- The exact exported type is `FlowContext<TEnv>`.
276
-
277
- ## Exported Types
278
-
279
- `@trigora/sdk` re-exports the main flow authoring types from `@trigora/contracts`:
280
-
281
- - `FlowContext`
282
- - `FlowDefinition`
283
- - `FlowEvent`
284
- - `FlowRunFn`
285
- - `JsonValue`
286
- - `Trigger`
287
- - `WebhookFlowResult`
288
-
289
- That means most flow authors can stay entirely within `@trigora/sdk`.
290
-
291
- ## Typical Workflow
292
-
293
- 1. Define a flow with `defineFlow`
294
- 2. Run it locally with:
295
- - `trigora trigger hello --payload payload.json` for one-off runs
296
- - `trigora dev hello --payload payload.json` for manual or payload watch mode
297
- - `trigora dev stripe-checkout` for a local webhook server
298
- 3. Deploy webhook flows with `trigora deploy`
299
- 4. Manage hosted flows with `trigora flows`
104
+ These are optional TypeScript convenience utilities.
300
105
 
301
- ## Related Packages
106
+ ## Learn more
302
107
 
303
- - `trigora` - CLI for local development and hosted deploys
304
- - `@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)
305
111
 
306
112
  ## License
307
113
 
308
- 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, 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.8.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.8.1"
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,47 +0,0 @@
1
- import type { CronEventPayload, CronFlowDefinition, FlowDefinition, FlowRunFn, JsonValue, ManualFlowDefinition, ManualTrigger, QueueFlowDefinition, QueueTrigger, 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
- 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;
6
- };
7
- 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>;
8
- /**
9
- * Define a Trigora flow.
10
- *
11
- * Flows are plain TypeScript modules with three core parts:
12
- * - `id`: the internal identifier for the flow in your project
13
- * - `trigger`: how the flow is invoked
14
- * - `run`: the function that executes when the flow is triggered
15
- *
16
- * `run` receives the incoming `event` and a `ctx` object with logging and environment access.
17
- *
18
- * For webhook flows, `trigger.route` controls the public hosted path and defaults to `/${id}`.
19
- * This is separate from the flow `id`, which is still what the CLI uses for commands like
20
- * `trigora deploy hello` or `trigora flows inspect hello`.
21
- *
22
- * Webhook flows can return HTTP-friendly values:
23
- * - `Response`
24
- * - plain objects / arrays / numbers / booleans
25
- * - `string`
26
- * - `null` or `undefined`
27
- *
28
- * Other trigger types generally do not need to return anything meaningful.
29
- *
30
- * @example
31
- * ```ts
32
- * export default defineFlow({
33
- * id: 'stripe-webhook',
34
- * trigger: { type: 'webhook', route: '/hooks/stripe' },
35
- * async run(event, ctx) {
36
- * await ctx.log.info('Received event', event.payload);
37
- * return { ok: true };
38
- * },
39
- * });
40
- * ```
41
- */
42
- 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>;
43
- export declare function defineFlow<TPayload = JsonValue, TEnv extends Record<string, string> = Record<string, string>>(flow: ManualFlowDefinition<TPayload, TEnv>): ManualFlowDefinition<TPayload, TEnv>;
44
- export declare function defineFlow<TPayload = JsonValue, TEnv extends Record<string, string> = Record<string, string>>(flow: WebhookFlowDefinition<TPayload, TEnv>): WebhookFlowDefinition<TPayload, TEnv>;
45
- export declare function defineFlow<TEnv extends Record<string, string> = Record<string, string>>(flow: CronFlowDefinition<TEnv>): CronFlowDefinition<TEnv>;
46
- export declare function defineFlow<TPayload = JsonValue, TEnv extends Record<string, string> = Record<string, string>>(flow: QueueFlowDefinition<TPayload, TEnv>): QueueFlowDefinition<TPayload, TEnv>;
47
- export {};