@codenotch/process 0.0.0-dev
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 +51 -0
- package/dist/activity.mjs +14 -0
- package/dist/template.mjs +21 -0
- package/dist/types/activity/index.d.ts +52 -0
- package/dist/types/lib/bindings.d.ts +48 -0
- package/dist/types/lib/canonical-json.d.ts +10 -0
- package/dist/types/lib/collections.d.ts +12 -0
- package/dist/types/lib/connectors.d.ts +299 -0
- package/dist/types/lib/context.d.ts +307 -0
- package/dist/types/lib/credits.d.ts +71 -0
- package/dist/types/lib/decimal.d.ts +72 -0
- package/dist/types/lib/duration.d.ts +40 -0
- package/dist/types/lib/encoding.d.ts +27 -0
- package/dist/types/lib/errors.d.ts +57 -0
- package/dist/types/lib/hash.d.ts +18 -0
- package/dist/types/lib/index.d.ts +25 -0
- package/dist/types/lib/instant.d.ts +41 -0
- package/dist/types/lib/meters.d.ts +61 -0
- package/dist/types/lib/registry.d.ts +131 -0
- package/dist/types/lib/renderings.d.ts +75 -0
- package/dist/types/lib/subscriptions.d.ts +61 -0
- package/dist/types/lib/types.d.ts +89 -0
- package/dist/types/lib/urls.d.ts +36 -0
- package/dist/types/lib/userTasks.d.ts +119 -0
- package/dist/types/lib/validators.d.ts +22 -0
- package/dist/types/lib/webPush.d.ts +30 -0
- package/dist/types/template/index.d.ts +17 -0
- package/dist/types/testing/api.d.ts +175 -0
- package/dist/types/testing/index.d.ts +2 -0
- package/dist/types/testing/main.d.ts +1 -0
- package/dist/types/testing/stdlib.d.ts +79 -0
- package/package.json +43 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import { engine, type EngineBindings } from './bindings';
|
|
2
|
+
import { type ChatHandle, type ConnectorBindingOf, type EmailHandle, type FileTransferHandle, type LlmHandle, type ObjectStorageHandle, type PaymentHandle, type SmsHandle } from './connectors';
|
|
3
|
+
import { type CreditsHandle } from './credits';
|
|
4
|
+
import { type MeterHandle } from './meters';
|
|
5
|
+
import { type SubscriptionHandle } from './subscriptions';
|
|
6
|
+
import { type UserTaskDefinition, type UserTaskHandle, type UserTaskOptions } from './userTasks';
|
|
7
|
+
import { type RenderApi } from './renderings';
|
|
8
|
+
import { type WebPushApi } from './webPush';
|
|
9
|
+
import { Instant } from './instant';
|
|
10
|
+
import type { EventMap, Process } from './registry';
|
|
11
|
+
import type { Activity, DeliveryOptions, DurationLike, Json, JsonPatchOp, RetryPolicy, Serializable } from './types';
|
|
12
|
+
/** Armed subscription handle. Auto-disposed when run() exits (any path). */
|
|
13
|
+
export interface ArmedHandler {
|
|
14
|
+
stop(): void;
|
|
15
|
+
}
|
|
16
|
+
export interface RecordGrant {
|
|
17
|
+
user: string;
|
|
18
|
+
/** r = read, u = update, d = delete. */
|
|
19
|
+
access: 'r' | 'ru' | 'rud';
|
|
20
|
+
}
|
|
21
|
+
export interface WriteOptions {
|
|
22
|
+
/** Per-record RLS grants. */
|
|
23
|
+
grants?: RecordGrant[];
|
|
24
|
+
}
|
|
25
|
+
/** Typed handle to one of the project's tables. */
|
|
26
|
+
export interface TableHandle<T> {
|
|
27
|
+
/** Single-record lookup by id (string) or key match ({ Email: '…' }). Null when absent. */
|
|
28
|
+
read(key: string | Partial<T>): Promise<T | null>;
|
|
29
|
+
/** read() or throw NotFoundError. */
|
|
30
|
+
require(key: string | Partial<T>): Promise<T>;
|
|
31
|
+
/**
|
|
32
|
+
* Merge-upsert by record id. Only the fields present in `data` are written:
|
|
33
|
+
* `null` clears a field, `undefined`/absent means no change. Id/CreatedAt/UpdatedAt
|
|
34
|
+
* are storage-managed and ignored. A write that creates the row must carry every
|
|
35
|
+
* non-nullable field. A write the database rejects (any constraint) throws a
|
|
36
|
+
* catchable `datastore.writeRejected` error and nothing is written.
|
|
37
|
+
*/
|
|
38
|
+
write(id: string, data: Partial<T>, opts?: WriteOptions): Promise<void>;
|
|
39
|
+
/** JSON-patch ops for transformations merge can't express. */
|
|
40
|
+
patch(id: string, ops: JsonPatchOp[], opts?: WriteOptions): Promise<void>;
|
|
41
|
+
delete(id: string): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
/** Handle to one of the project's document stores. Same field rules as TableHandle. */
|
|
44
|
+
export interface DocStoreHandle<T> {
|
|
45
|
+
read(id: string): Promise<T | null>;
|
|
46
|
+
/** read() or throw NotFoundError. */
|
|
47
|
+
require(id: string): Promise<T>;
|
|
48
|
+
/** Merge-upsert; `null` stores an explicit null under the key — removing the key is a patch remove op. */
|
|
49
|
+
write(id: string, data: Partial<T>): Promise<void>;
|
|
50
|
+
patch(id: string, ops: JsonPatchOp[]): Promise<void>;
|
|
51
|
+
delete(id: string): Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The project's tables, keyed by name — augmented via declaration merging by the
|
|
55
|
+
* generated db-schema.d.ts so every table and row type autocompletes.
|
|
56
|
+
*/
|
|
57
|
+
export interface ProjectTables {
|
|
58
|
+
[name: string]: TableHandle<Json>;
|
|
59
|
+
}
|
|
60
|
+
export interface ProjectDocs {
|
|
61
|
+
[name: string]: DocStoreHandle<Json>;
|
|
62
|
+
}
|
|
63
|
+
export interface CallTarget {
|
|
64
|
+
/** Absent = own project. */
|
|
65
|
+
project?: string;
|
|
66
|
+
process: string;
|
|
67
|
+
}
|
|
68
|
+
export interface CallOptions {
|
|
69
|
+
/**
|
|
70
|
+
* detached: true — the callee outlives this instance (fire-and-forget).
|
|
71
|
+
* Default false: a non-detached, un-awaited callee still running when this
|
|
72
|
+
* instance completes is cancelled (structured concurrency).
|
|
73
|
+
*/
|
|
74
|
+
detached?: boolean;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Thenable handle to a called process instance. Await it now, hold it and await
|
|
78
|
+
* later, or never await it (see CallOptions).
|
|
79
|
+
*/
|
|
80
|
+
export interface CallHandle<Out, E extends EventMap = EventMap> extends PromiseLike<Out> {
|
|
81
|
+
/**
|
|
82
|
+
* Park until the callee sends this declared event once. Rejects with
|
|
83
|
+
* CallCompletedError if the callee completes first — for "event or done,
|
|
84
|
+
* whichever first", race it: ctx.race({ ev: call.waitEvent('x'), done: call }).
|
|
85
|
+
*/
|
|
86
|
+
waitEvent<K extends keyof E & string>(event: K): Promise<E[K]>;
|
|
87
|
+
/** Armed listener for a declared callee event. Buffered from start. */
|
|
88
|
+
onEvent<K extends keyof E & string>(event: K, handler: (payload: E[K]) => void | Promise<void>): ArmedHandler;
|
|
89
|
+
/** Send a signal targeted at this instance (not broadcast). */
|
|
90
|
+
sendSignal(ref: string, data?: Serializable): Promise<void>;
|
|
91
|
+
cancel(reason?: string): Promise<void>;
|
|
92
|
+
}
|
|
93
|
+
export interface CallerIdentity {
|
|
94
|
+
id: string;
|
|
95
|
+
email?: string;
|
|
96
|
+
name?: string;
|
|
97
|
+
roles: string[];
|
|
98
|
+
/** A logged-in user is either internal or external (public/system cannot log in). */
|
|
99
|
+
group: 'internal' | 'external';
|
|
100
|
+
language?: string;
|
|
101
|
+
}
|
|
102
|
+
export interface ProcessLogger {
|
|
103
|
+
debug(message: string, data?: Serializable): void;
|
|
104
|
+
info(message: string, data?: Serializable): void;
|
|
105
|
+
warn(message: string, data?: Serializable): void;
|
|
106
|
+
error(message: string, data?: Serializable): void;
|
|
107
|
+
}
|
|
108
|
+
export interface ActivityOptions {
|
|
109
|
+
/** Retries happen inside ONE journaled execution — a policy change never diverges an old replay. */
|
|
110
|
+
retry?: RetryPolicy;
|
|
111
|
+
timeout?: DurationLike;
|
|
112
|
+
}
|
|
113
|
+
export interface FetchOptions {
|
|
114
|
+
/** HTTP method. Default GET. */
|
|
115
|
+
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
|
|
116
|
+
headers?: Record<string, string>;
|
|
117
|
+
/** A string is sent as-is; any object is JSON-serialized (content-type json unless set). */
|
|
118
|
+
body?: string | Serializable;
|
|
119
|
+
/**
|
|
120
|
+
* Adds an 'Idempotency-Key' header carrying this execution's stable key
|
|
121
|
+
* (instance:generation:seq) — the same value on every at-least-once re-run, so
|
|
122
|
+
* providers that honor the header dedupe non-idempotent calls (POSTs).
|
|
123
|
+
*/
|
|
124
|
+
idempotencyKey?: boolean;
|
|
125
|
+
retry?: RetryPolicy;
|
|
126
|
+
timeout?: DurationLike;
|
|
127
|
+
}
|
|
128
|
+
export interface FetchResponse<T = Json> {
|
|
129
|
+
/** HTTP status code. Non-2xx is NOT thrown — check ok/status. */
|
|
130
|
+
status: number;
|
|
131
|
+
/** True for 2xx. */
|
|
132
|
+
ok: boolean;
|
|
133
|
+
/** Response headers, lowercase names; repeated headers joined with ', '. */
|
|
134
|
+
headers: Record<string, string>;
|
|
135
|
+
/** Raw response body text. */
|
|
136
|
+
body: string;
|
|
137
|
+
/** The body parsed as JSON (throws on non-JSON bodies). */
|
|
138
|
+
json(): T;
|
|
139
|
+
}
|
|
140
|
+
/** Keyed race outcome: which arm won and its value. */
|
|
141
|
+
export type RaceOutcome<T extends Record<string, PromiseLike<unknown>>> = {
|
|
142
|
+
[K in keyof T]: {
|
|
143
|
+
key: K;
|
|
144
|
+
value: Awaited<T[K]>;
|
|
145
|
+
};
|
|
146
|
+
}[keyof T];
|
|
147
|
+
/**
|
|
148
|
+
* The workflow context — the boundary between deterministic workflow code and the
|
|
149
|
+
* world. Everything on ctx is journaled; everything off ctx must be pure.
|
|
150
|
+
*/
|
|
151
|
+
export interface Context<E extends EventMap = {}> {
|
|
152
|
+
/** The authenticated starter. */
|
|
153
|
+
readonly user: CallerIdentity;
|
|
154
|
+
/** Project parameters, snapshot at start. */
|
|
155
|
+
readonly params: Readonly<Record<string, Json>>;
|
|
156
|
+
readonly instanceId: string;
|
|
157
|
+
/** Journal-fed time; advances only at awaits. Same value on every replay. */
|
|
158
|
+
now(): Instant;
|
|
159
|
+
/** Seeded, replay-stable random in [0,1). */
|
|
160
|
+
random(): number;
|
|
161
|
+
/** Replay-stable UUID. */
|
|
162
|
+
uuid(): string;
|
|
163
|
+
/** Structured instance logging (journal-adjacent telemetry, not workflow state). */
|
|
164
|
+
log: ProcessLogger;
|
|
165
|
+
/** Park for a duration — milliseconds, 'PT5M', '00:05:00' or { minutes: 5 }. Durable: survives restarts. */
|
|
166
|
+
wait(duration: DurationLike): Promise<void>;
|
|
167
|
+
/** Park until an absolute time (Instant or ISO-8601 string). */
|
|
168
|
+
waitUntil(at: Instant | string): Promise<void>;
|
|
169
|
+
/** Park until ONE occurrence of the signal. Hierarchical refs: 'ticket' receives 'ticket.done.1'. */
|
|
170
|
+
waitSignal<T = unknown>(ref: string, opts?: DeliveryOptions): Promise<T>;
|
|
171
|
+
/** Broadcast a signal (parked processes, start triggers, webhooks, clients). Durable fire-and-forget. */
|
|
172
|
+
sendSignal(ref: string, data?: Serializable): Promise<void>;
|
|
173
|
+
/** First arm wins; losing PARKS are cancelled (in-flight activities still settle). */
|
|
174
|
+
race<T extends Record<string, PromiseLike<unknown>>>(arms: T): Promise<RaceOutcome<T>>;
|
|
175
|
+
/** Parallel map over items with bounded concurrency. Results keep item order. */
|
|
176
|
+
map<T, R>(items: readonly T[], opts: {
|
|
177
|
+
concurrency: number;
|
|
178
|
+
}, fn: (item: T, index: number) => Promise<R>): Promise<R[]>;
|
|
179
|
+
/** Rejects with TimeoutError when the promise does not settle in time (v1: the losing work is not cancelled). */
|
|
180
|
+
withTimeout<T>(duration: DurationLike, promise: Promise<T>): Promise<T>;
|
|
181
|
+
/** Typed, string-free access to the project's own tables: ctx.tables.Books.write(id, …). */
|
|
182
|
+
readonly tables: ProjectTables;
|
|
183
|
+
readonly docs: ProjectDocs;
|
|
184
|
+
/** By-name table access — for dynamic names and cross-project stores. */
|
|
185
|
+
table<T = Json>(name: string, opts?: {
|
|
186
|
+
project?: string;
|
|
187
|
+
}): TableHandle<T>;
|
|
188
|
+
/** By-name document-store access. */
|
|
189
|
+
doc<T = Json>(store: string, opts?: {
|
|
190
|
+
project?: string;
|
|
191
|
+
}): DocStoreHandle<T>;
|
|
192
|
+
/**
|
|
193
|
+
* CNQL query — a file reference ('queries/x.cnql') or inline CNQL; args bound
|
|
194
|
+
* safely. The result is journaled and replayed on every wake-up, so return
|
|
195
|
+
* conclusions, not datasets: filter and aggregate in the query.
|
|
196
|
+
*/
|
|
197
|
+
query<Row = Json>(query: string, args?: Record<string, Serializable>): Promise<Row[]>;
|
|
198
|
+
/**
|
|
199
|
+
* An activity execution (at-least-once, result journaled). Retries and the
|
|
200
|
+
* timeout apply inside one journaled execution. Pass the imported activity
|
|
201
|
+
* handle for a fully typed invocation resolved against this deployment's
|
|
202
|
+
* activity artifacts — or a registered host activity by name (string form).
|
|
203
|
+
*/
|
|
204
|
+
activity<In, Out>(target: Activity<In, Out>, input: In, opts?: ActivityOptions): Promise<Out>;
|
|
205
|
+
activity<T = Json>(name: string, input?: Serializable, opts?: ActivityOptions): Promise<T>;
|
|
206
|
+
/**
|
|
207
|
+
* Outbound HTTP, executed host-side as a journaled activity (at-least-once — set
|
|
208
|
+
* idempotencyKey for non-idempotent calls). Follows redirects; private/internal
|
|
209
|
+
* targets are rejected by the server's SSRF policy. Non-2xx responses return
|
|
210
|
+
* normally — check res.ok; only transport/policy failures throw.
|
|
211
|
+
*/
|
|
212
|
+
fetch<T = Json>(url: string, opts?: FetchOptions): Promise<FetchResponse<T>>;
|
|
213
|
+
/** Call another process — a statically imported handle (fully typed) or a { project?, process } target. */
|
|
214
|
+
call<In, Out, CE extends EventMap>(target: Process<In, Out, CE>, input: In, opts?: CallOptions): CallHandle<Out, CE>;
|
|
215
|
+
call<Out = unknown, CE extends EventMap = EventMap>(target: CallTarget, input?: Serializable, opts?: CallOptions): CallHandle<Out, CE>;
|
|
216
|
+
/** The email connector — bound to the named manifest parameter, or the project's only one of kind 'email'. */
|
|
217
|
+
email(binding?: ConnectorBindingOf<'email'>): EmailHandle;
|
|
218
|
+
/** The SMS connector — the named manifest parameter, or the project's only one of kind 'sms'. */
|
|
219
|
+
sms(binding?: ConnectorBindingOf<'sms'>): SmsHandle;
|
|
220
|
+
/** The chat connector (Slack, Teams, …) — the named manifest parameter, or the project's only one of kind 'chat'. */
|
|
221
|
+
chat(binding?: ConnectorBindingOf<'chat'>): ChatHandle;
|
|
222
|
+
/** The object store (S3, Azure Blob, …) — the named manifest parameter, or the project's only one of kind 'objectStorage'. */
|
|
223
|
+
objectStorage(binding?: ConnectorBindingOf<'objectStorage'>): ObjectStorageHandle;
|
|
224
|
+
/** The file-transfer server (SFTP) — the named manifest parameter, or the project's only one of kind 'fileTransfer'. */
|
|
225
|
+
fileTransfer(binding?: ConnectorBindingOf<'fileTransfer'>): FileTransferHandle;
|
|
226
|
+
/** The payment provider — the named manifest parameter, or the project's only one of kind 'payment'. */
|
|
227
|
+
payment(binding?: ConnectorBindingOf<'payment'>): PaymentHandle;
|
|
228
|
+
/** The language model (Claude, GPT, Gemini, or a local runtime) — the named manifest parameter, or the project's only one of kind 'llm'. */
|
|
229
|
+
llm(binding?: ConnectorBindingOf<'llm'>): LlmHandle;
|
|
230
|
+
/**
|
|
231
|
+
* The credit ledger, scoped to this project and one balance name: named integer balances
|
|
232
|
+
* per user (or anonymous pools by account id), conditional spend that never goes below
|
|
233
|
+
* zero, and a mandatory idempotency reference on every movement.
|
|
234
|
+
*/
|
|
235
|
+
credits(name: string): CreditsHandle;
|
|
236
|
+
/**
|
|
237
|
+
* A usage meter, scoped to this project: per-period unit counters the framework
|
|
238
|
+
* accumulates. Framework meters (dotted names: email.sent, llm.tokens.*) count
|
|
239
|
+
* themselves and are read-only here; custom meters record the project's own business
|
|
240
|
+
* units.
|
|
241
|
+
*/
|
|
242
|
+
meter(name: string): MeterHandle;
|
|
243
|
+
/**
|
|
244
|
+
* The subscription registry, scoped to this project (or tenant-wide with
|
|
245
|
+
* { tenant: true }): the framework tracks the term and raises a signal per transition;
|
|
246
|
+
* entitlement and renewal are this project's process code.
|
|
247
|
+
*/
|
|
248
|
+
subscription(plan: string, scope?: {
|
|
249
|
+
tenant?: boolean;
|
|
250
|
+
}): SubscriptionHandle;
|
|
251
|
+
/**
|
|
252
|
+
* Web push to the devices a user subscribed for one of the project's react
|
|
253
|
+
* applications. Subscriptions, keys and delivery are platform built-ins — nothing to
|
|
254
|
+
* bind; send() is a journaled activity with the same one-attempt default as the
|
|
255
|
+
* connector sends.
|
|
256
|
+
*/
|
|
257
|
+
readonly webPush: WebPushApi;
|
|
258
|
+
/**
|
|
259
|
+
* Render a manifest-declared template into its channel payload — the imported template
|
|
260
|
+
* handle (fully typed, kind-checked) or its manifest name. One journaled activity: the
|
|
261
|
+
* template bundle executes server-side on the Node pool. Email results carry send();
|
|
262
|
+
* pdf results are stored references whose bytes never enter the process.
|
|
263
|
+
*/
|
|
264
|
+
readonly render: RenderApi;
|
|
265
|
+
/**
|
|
266
|
+
* Creates a user task — a form somebody must fill in the portal (or via a share link) —
|
|
267
|
+
* and returns its handle: await handle.outcome to park until a human completes it (the
|
|
268
|
+
* BPMN user-task shape), race it with a timer for escalation, reassign or cancel it.
|
|
269
|
+
* Unless detached, the task is cancelled with the run's compensation.
|
|
270
|
+
*/
|
|
271
|
+
userTask(definition: UserTaskDefinition, opts?: UserTaskOptions): Promise<UserTaskHandle>;
|
|
272
|
+
/**
|
|
273
|
+
* Send the HTTP response of an api-triggered process. Call it EARLY to answer the
|
|
274
|
+
* caller while the process keeps running, or just before returning to control
|
|
275
|
+
* status/headers. Once per instance.
|
|
276
|
+
*/
|
|
277
|
+
respond(status: number, body?: Serializable, headers?: Record<string, string>): Promise<void>;
|
|
278
|
+
/** Send a DECLARED event to the caller without terminating. */
|
|
279
|
+
sendEvent<K extends keyof E & string>(event: K, payload: E[K]): Promise<void>;
|
|
280
|
+
/** Register compensation AFTER the action it undoes succeeded. LIFO on failure/cancel. */
|
|
281
|
+
onCompensate(handler: () => void | Promise<void>): void;
|
|
282
|
+
/** Run the compensation chain NOW without failing. */
|
|
283
|
+
compensate(): Promise<void>;
|
|
284
|
+
/** Seal this history, restart with carried input (fresh generation). */
|
|
285
|
+
continueAsNew(input: Serializable): Promise<never>;
|
|
286
|
+
/** Execute-once escape hatch: the closure runs live only (REAL Date/random inside); its result is journaled. */
|
|
287
|
+
run<T extends Serializable>(fn: () => T | Promise<T>): Promise<T>;
|
|
288
|
+
/**
|
|
289
|
+
* In-flight hotfix marker: live executions journal the marker and return true;
|
|
290
|
+
* replays return what this instance recorded at this point. Normal deploys never
|
|
291
|
+
* need this — instances pin their bundle version.
|
|
292
|
+
*/
|
|
293
|
+
patched(marker: string): boolean;
|
|
294
|
+
}
|
|
295
|
+
/** @internal The runtime pieces createContext returns beside the ctx object. */
|
|
296
|
+
export interface ContextInternals {
|
|
297
|
+
ctx: Context<EventMap>;
|
|
298
|
+
/** The journaled start environment, set by the bootstrap before run() executes. */
|
|
299
|
+
setEnvironment(user: CallerIdentity, params: Record<string, Json>, instanceId: string | null): void;
|
|
300
|
+
/** LIFO compensation chain length (bootstrap: skip the unwind when empty). */
|
|
301
|
+
compensationCount(): number;
|
|
302
|
+
/** Runs the compensation chain to exhaustion (failures logged, chain continues). */
|
|
303
|
+
runCompensation(): Promise<void>;
|
|
304
|
+
}
|
|
305
|
+
/** @internal Builds the ctx facade over the protocol bindings. Called once per run session. */
|
|
306
|
+
export declare const createContext: (host: EngineBindings) => ContextInternals;
|
|
307
|
+
export { engine };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { ActivityOptions } from './context';
|
|
2
|
+
/** Exactly one of user (the user's account of the handle's name) and account (an account id). */
|
|
3
|
+
export type CreditTarget = {
|
|
4
|
+
user: string;
|
|
5
|
+
} | {
|
|
6
|
+
account: string;
|
|
7
|
+
};
|
|
8
|
+
export type CreditGrantKind = 'purchased' | 'promotional';
|
|
9
|
+
export interface CreditGrantOptions {
|
|
10
|
+
/** Idempotency reference (order id, …) — the same reference never grants twice. */
|
|
11
|
+
reference: string;
|
|
12
|
+
/** Purchased (paid for) or promotional (given away) — tagged distinctly in the history. */
|
|
13
|
+
kind: CreditGrantKind;
|
|
14
|
+
reason?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface CreditSpendOptions {
|
|
17
|
+
/** Idempotency reference (run id, …) — the same reference never spends twice. */
|
|
18
|
+
reference: string;
|
|
19
|
+
reason?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface CreditSpendResult {
|
|
22
|
+
/** False = refused, the balance would go below zero (or the account does not exist). Nothing moved. */
|
|
23
|
+
applied: boolean;
|
|
24
|
+
/** True when the reference was already recorded — the recorded outcome is returned. */
|
|
25
|
+
replayed: boolean;
|
|
26
|
+
/** Balance after the movement, or the current balance when refused. */
|
|
27
|
+
balance: number;
|
|
28
|
+
}
|
|
29
|
+
export interface CreditGrantResult {
|
|
30
|
+
replayed: boolean;
|
|
31
|
+
balance: number;
|
|
32
|
+
}
|
|
33
|
+
export interface CreditMovement {
|
|
34
|
+
id: string;
|
|
35
|
+
kind: 'grant.purchased' | 'grant.promotional' | 'spend';
|
|
36
|
+
/** Signed: positive grants, negative spends. */
|
|
37
|
+
amount: number;
|
|
38
|
+
balanceAfter: number;
|
|
39
|
+
reference: string;
|
|
40
|
+
reason?: string;
|
|
41
|
+
createdAt: string;
|
|
42
|
+
}
|
|
43
|
+
export interface CreditHistoryPage {
|
|
44
|
+
items: CreditMovement[];
|
|
45
|
+
totalCount: number;
|
|
46
|
+
}
|
|
47
|
+
export interface CreditsHandle {
|
|
48
|
+
/**
|
|
49
|
+
* Add credits. Creates the account when absent: a user-target creates the user's account
|
|
50
|
+
* of this name; an account-target creates an anonymous pool under the supplied id. A
|
|
51
|
+
* duplicate reference with different parameters fails with credits.referenceConflict.
|
|
52
|
+
*/
|
|
53
|
+
grant(target: CreditTarget, amount: number, opts: CreditGrantOptions & ActivityOptions): Promise<CreditGrantResult>;
|
|
54
|
+
/**
|
|
55
|
+
* Remove credits when the balance suffices — never below zero, never creating an account.
|
|
56
|
+
* A refusal is a result to branch on ({applied: false}), not an error.
|
|
57
|
+
*/
|
|
58
|
+
spend(target: CreditTarget, amount: number, opts: CreditSpendOptions & ActivityOptions): Promise<CreditSpendResult>;
|
|
59
|
+
/** The current balance; 0 when the account does not exist. */
|
|
60
|
+
get(target: CreditTarget, opts?: ActivityOptions): Promise<number>;
|
|
61
|
+
/** The account's movements, newest first. */
|
|
62
|
+
history(target: CreditTarget, opts?: {
|
|
63
|
+
limit?: number;
|
|
64
|
+
before?: string;
|
|
65
|
+
} & ActivityOptions): Promise<CreditHistoryPage>;
|
|
66
|
+
}
|
|
67
|
+
/** @internal Same call channel as the connector handles. */
|
|
68
|
+
type CreditsCall = <T>(name: string, input: Record<string, unknown>, opts: ActivityOptions | undefined) => Promise<T>;
|
|
69
|
+
/** @internal ctx.credits factory over the activity channel — bound by createContext. */
|
|
70
|
+
export declare const createCreditsFactory: (call: CreditsCall) => (name: string) => CreditsHandle;
|
|
71
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export type RoundingMode =
|
|
2
|
+
/** Away from zero. */
|
|
3
|
+
'up'
|
|
4
|
+
/** Toward zero (truncate). */
|
|
5
|
+
| 'down'
|
|
6
|
+
/** Toward +Infinity. */
|
|
7
|
+
| 'ceil'
|
|
8
|
+
/** Toward -Infinity. */
|
|
9
|
+
| 'floor'
|
|
10
|
+
/** Nearest; ties away from zero (schoolbook rounding). */
|
|
11
|
+
| 'halfUp'
|
|
12
|
+
/** Nearest; ties toward zero. */
|
|
13
|
+
| 'halfDown'
|
|
14
|
+
/** Nearest; ties to the even neighbor (banker's rounding — the money default). */
|
|
15
|
+
| 'halfEven';
|
|
16
|
+
/**
|
|
17
|
+
* Arbitrary-precision decimal for money and precision math (vanilla JS numbers are
|
|
18
|
+
* binary floats). Immutable; serializes to its plain decimal string (toJSON).
|
|
19
|
+
*/
|
|
20
|
+
export declare class Decimal {
|
|
21
|
+
private readonly coefficient;
|
|
22
|
+
private readonly scale;
|
|
23
|
+
private constructor();
|
|
24
|
+
/** Parses a decimal string ('19.99', '-1e-3') or a number (via its exact string form). */
|
|
25
|
+
static from(value: string | number | Decimal): Decimal;
|
|
26
|
+
/** Standard comparator (numeric): -1, 0 or 1. */
|
|
27
|
+
static compare(a: Decimal | number | string, b: Decimal | number | string): -1 | 0 | 1;
|
|
28
|
+
/** Exact sum. The result keeps the larger scale of the two operands. */
|
|
29
|
+
plus(other: Decimal | number | string): Decimal;
|
|
30
|
+
/** Exact difference. */
|
|
31
|
+
minus(other: Decimal | number | string): Decimal;
|
|
32
|
+
/** Exact product. Scales add ('1.25' × '0.5' → '0.625'). */
|
|
33
|
+
times(other: Decimal | number | string): Decimal;
|
|
34
|
+
/**
|
|
35
|
+
* Division at a fixed precision: `decimalPlaces` fraction digits (default 20),
|
|
36
|
+
* rounded with `rounding` (default 'halfEven'). Throws on division by zero.
|
|
37
|
+
*/
|
|
38
|
+
dividedBy(other: Decimal | number | string, options?: {
|
|
39
|
+
decimalPlaces?: number;
|
|
40
|
+
rounding?: RoundingMode;
|
|
41
|
+
}): Decimal;
|
|
42
|
+
/** This value rounded to `decimalPlaces` fraction digits (default mode 'halfEven'). */
|
|
43
|
+
round(decimalPlaces: number, rounding?: RoundingMode): Decimal;
|
|
44
|
+
/**
|
|
45
|
+
* Splits this value by the given ratios without losing a unit at the current scale
|
|
46
|
+
* (largest-remainder distribution): Decimal.from('100.00').allocate([1, 1, 1]) →
|
|
47
|
+
* ['33.34', '33.33', '33.33']. Ratios must be non-negative with a positive sum.
|
|
48
|
+
*/
|
|
49
|
+
allocate(ratios: readonly number[]): Decimal[];
|
|
50
|
+
/** Numeric comparison (scale-independent): -1, 0 or 1. */
|
|
51
|
+
compare(other: Decimal | number | string): -1 | 0 | 1;
|
|
52
|
+
/** Numeric equality ('1.5' equals '1.50'). */
|
|
53
|
+
equals(other: Decimal | number | string): boolean;
|
|
54
|
+
isZero(): boolean;
|
|
55
|
+
isNegative(): boolean;
|
|
56
|
+
/** The absolute value. */
|
|
57
|
+
abs(): Decimal;
|
|
58
|
+
/** The value with its sign flipped. */
|
|
59
|
+
negated(): Decimal;
|
|
60
|
+
/** Fixed-point text with exactly `decimalPlaces` fraction digits, rounding when narrower. */
|
|
61
|
+
toFixed(decimalPlaces: number, rounding?: RoundingMode): string;
|
|
62
|
+
/**
|
|
63
|
+
* The closest JS number. Explicitly lossy for values beyond float precision —
|
|
64
|
+
* keep money in Decimal and convert only at the edges.
|
|
65
|
+
*/
|
|
66
|
+
toNumber(): number;
|
|
67
|
+
/** Plain decimal text, no exponent, trailing zeros kept ('1.50' stays '1.50'). */
|
|
68
|
+
toString(): string;
|
|
69
|
+
toJSON(): string;
|
|
70
|
+
/** Approximate numeric value — lets relational operators (<, >) behave sanely. Use compare() for exactness. */
|
|
71
|
+
valueOf(): number;
|
|
72
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { DurationLike } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* A length of time. Fixed components (weeks/days/hours/minutes/seconds/milliseconds)
|
|
4
|
+
* collapse to exact milliseconds; calendar components (years/months) have no fixed
|
|
5
|
+
* length and are kept apart — they only gain meaning when applied to an Instant.
|
|
6
|
+
*
|
|
7
|
+
* Accepted input everywhere a DurationLike is expected: ISO-8601 ('P3D', 'PT5M'),
|
|
8
|
+
* raw milliseconds (180000), .NET TimeSpan text ('3.00:00:00') or a components
|
|
9
|
+
* object ({ days: 3 }).
|
|
10
|
+
*/
|
|
11
|
+
export declare class Duration {
|
|
12
|
+
/** @internal Calendar months (years folded in). */
|
|
13
|
+
readonly calendarMonths: number;
|
|
14
|
+
/** @internal Fixed milliseconds (weeks/days/time folded in). */
|
|
15
|
+
readonly fixedMillis: number;
|
|
16
|
+
private constructor();
|
|
17
|
+
/** Parses any DurationLike. Throws on unrecognized input. */
|
|
18
|
+
static from(value: DurationLike): Duration;
|
|
19
|
+
/** The sum of this duration and another. */
|
|
20
|
+
plus(other: DurationLike): Duration;
|
|
21
|
+
/** This duration minus another. */
|
|
22
|
+
minus(other: DurationLike): Duration;
|
|
23
|
+
/** The same duration with every component negated. */
|
|
24
|
+
negated(): Duration;
|
|
25
|
+
/** True when every component is zero. */
|
|
26
|
+
isZero(): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Total milliseconds. Throws when the duration carries calendar components
|
|
29
|
+
* (years/months have no fixed length — apply the duration to an Instant instead).
|
|
30
|
+
*/
|
|
31
|
+
toMillis(): number;
|
|
32
|
+
/** Total seconds (same calendar-component rule as toMillis). */
|
|
33
|
+
toSeconds(): number;
|
|
34
|
+
/** ISO-8601 text ('P1M2DT3H'). Zero durations render as 'PT0S'. */
|
|
35
|
+
toISOString(): string;
|
|
36
|
+
toJSON(): string;
|
|
37
|
+
toString(): string;
|
|
38
|
+
}
|
|
39
|
+
/** @internal Converts a DurationLike to exact milliseconds (rejects calendar components). */
|
|
40
|
+
export declare const durationToMillis: (value: DurationLike) => number;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** UTF-8 text ↔ bytes. */
|
|
2
|
+
export declare const utf8: {
|
|
3
|
+
/** Encodes text as UTF-8 bytes. */
|
|
4
|
+
encode(text: string): Uint8Array;
|
|
5
|
+
/** Decodes UTF-8 bytes to text. Throws on malformed sequences. */
|
|
6
|
+
decode(bytes: Uint8Array): string;
|
|
7
|
+
};
|
|
8
|
+
/** Base64 (and base64url) text ↔ bytes. Strings encode as their UTF-8 bytes. */
|
|
9
|
+
export declare const base64: {
|
|
10
|
+
/** Encodes bytes (or a string's UTF-8 bytes) as base64. { url: true } gives base64url without padding. */
|
|
11
|
+
encode(data: string | Uint8Array, options?: {
|
|
12
|
+
url?: boolean;
|
|
13
|
+
}): string;
|
|
14
|
+
/** Decodes base64 or base64url text (padding optional) to bytes. */
|
|
15
|
+
decode(text: string): Uint8Array;
|
|
16
|
+
/** Decodes base64 text straight to UTF-8 text. */
|
|
17
|
+
decodeToText(text: string): string;
|
|
18
|
+
};
|
|
19
|
+
/** Lowercase hex text ↔ bytes. Strings encode as their UTF-8 bytes. */
|
|
20
|
+
export declare const hex: {
|
|
21
|
+
/** Encodes bytes (or a string's UTF-8 bytes) as lowercase hex. */
|
|
22
|
+
encode(data: string | Uint8Array): string;
|
|
23
|
+
/** Decodes hex text (either case) to bytes. */
|
|
24
|
+
decode(text: string): Uint8Array;
|
|
25
|
+
/** Decodes hex text straight to UTF-8 text. */
|
|
26
|
+
decodeToText(text: string): string;
|
|
27
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Json } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Structured error for failures that must cross a boundary with fidelity. A callee
|
|
4
|
+
* throwing ProcessError is rehydrated as ProcessError in its caller (instanceof works
|
|
5
|
+
* there); for a failed root process the code becomes the API error code. Throwing
|
|
6
|
+
* anything else is fine too — it crosses boundaries as CallFailedError (name/message).
|
|
7
|
+
*/
|
|
8
|
+
export declare class ProcessError extends Error {
|
|
9
|
+
readonly code: string;
|
|
10
|
+
readonly details?: Json;
|
|
11
|
+
constructor(code: string, options?: {
|
|
12
|
+
details?: Json;
|
|
13
|
+
cause?: unknown;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/** A called process failed with a non-ProcessError throw; carries what serialization kept. */
|
|
17
|
+
export declare class CallFailedError extends Error {
|
|
18
|
+
/** Constructor name of the original thrown value (or 'Error'). */
|
|
19
|
+
readonly errorName: string;
|
|
20
|
+
readonly processId: string;
|
|
21
|
+
constructor(message?: string, errorName?: string, processId?: string);
|
|
22
|
+
}
|
|
23
|
+
/** Thrown by ctx.withTimeout when the wrapped promise did not settle in time. */
|
|
24
|
+
export declare class TimeoutError extends Error {
|
|
25
|
+
constructor(message?: string);
|
|
26
|
+
}
|
|
27
|
+
/** Thrown into in-flight waits when the instance is cancelled/stopped. */
|
|
28
|
+
export declare class CancelledError extends Error {
|
|
29
|
+
constructor(message?: string | null);
|
|
30
|
+
}
|
|
31
|
+
/** Rejects a pending call.waitEvent when the callee completes without sending that event. */
|
|
32
|
+
export declare class CallCompletedError extends Error {
|
|
33
|
+
constructor(message?: string);
|
|
34
|
+
}
|
|
35
|
+
/** Thrown by table/doc require() when the record does not exist. */
|
|
36
|
+
export declare class NotFoundError extends Error {
|
|
37
|
+
readonly store: string;
|
|
38
|
+
readonly key: string;
|
|
39
|
+
constructor(message?: string, store?: string, key?: string);
|
|
40
|
+
}
|
|
41
|
+
/** The serialized error value journaled for a failed run (internal). */
|
|
42
|
+
export interface SerializedError {
|
|
43
|
+
name: string;
|
|
44
|
+
message: string;
|
|
45
|
+
code?: string;
|
|
46
|
+
details?: Json | null;
|
|
47
|
+
}
|
|
48
|
+
/** @internal Serializes a thrown value the way the journal records it. */
|
|
49
|
+
export declare const serializeError: (err: unknown) => SerializedError;
|
|
50
|
+
/** @internal Rehydrates a journaled error value into the matching error class. */
|
|
51
|
+
export declare const reviveError: (value: SerializedError | null | undefined) => Error;
|
|
52
|
+
/**
|
|
53
|
+
* @internal A failed CALL crosses the boundary as ProcessError when the callee threw one
|
|
54
|
+
* (rehydrated, instanceof works); anything else becomes CallFailedError carrying the
|
|
55
|
+
* original error name.
|
|
56
|
+
*/
|
|
57
|
+
export declare const reviveChildError: (value: SerializedError | null | undefined, processId: string) => Error;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type HashOutput = 'hex' | 'base64';
|
|
2
|
+
/**
|
|
3
|
+
* Hashing and signature verification. Host-backed pure functions: same input, same
|
|
4
|
+
* output, on every replay — safe to call anywhere in workflow code, nothing journaled.
|
|
5
|
+
* Strings hash as their UTF-8 bytes.
|
|
6
|
+
*/
|
|
7
|
+
export declare const hash: {
|
|
8
|
+
/** SHA-256 digest, hex by default ('base64' on request). */
|
|
9
|
+
sha256(data: string | Uint8Array, output?: HashOutput): string;
|
|
10
|
+
/** HMAC-SHA-256 signature — the webhook-verification primitive. Hex by default. */
|
|
11
|
+
hmacSha256(key: string | Uint8Array, data: string | Uint8Array, output?: HashOutput): string;
|
|
12
|
+
/**
|
|
13
|
+
* Constant-time equality for comparing a computed signature against a received one
|
|
14
|
+
* (an early-exit === leaks match length through timing). Strings compare as UTF-8
|
|
15
|
+
* bytes; different lengths are simply unequal.
|
|
16
|
+
*/
|
|
17
|
+
timingSafeEqual(a: string | Uint8Array, b: string | Uint8Array): boolean;
|
|
18
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export { process, api, signal, timer, connectorEvent, install, manual, events } from './registry';
|
|
2
|
+
export type { AuthScope, Concurrency, ConnectorBindingName, ConnectorEventName, EventMap, EventsDecl, Process, ProcessAuth, ProcessDefinition, ProcessOptions, Trigger, } from './registry';
|
|
3
|
+
export { ProcessError, CallFailedError, TimeoutError, CancelledError, CallCompletedError, NotFoundError, } from './errors';
|
|
4
|
+
export type { Activity, Json, Serializable, DurationParts, DurationLike, RetryPolicy, DeliveryOptions, JsonPatchOp, Template, TemplateKind, } from './types';
|
|
5
|
+
export type { EmailTemplatePayload, PdfPageOptions, PdfTemplatePayload, PdfRenderOptions, RenderApi, RenderOptions, RenderSendOptions, RenderedEmail, StoredRendering, } from './renderings';
|
|
6
|
+
export type { WebPushApi, WebPushDeviceStatus, WebPushMessage, WebPushResult, } from './webPush';
|
|
7
|
+
export type { ActivityOptions, ArmedHandler, CallerIdentity, CallHandle, CallOptions, CallTarget, Context, DocStoreHandle, FetchOptions, FetchResponse, ProcessLogger, ProjectDocs, ProjectTables, RaceOutcome, RecordGrant, TableHandle, WriteOptions, } from './context';
|
|
8
|
+
export type { ChargeRequest, ChargeResult, ChatHandle, ChatMessage, CheckoutRequest, CheckoutSession, ConnectorBindingOf, ConnectorKind, ConnectorKindEvents, EmailAttachment, RenderingAttachment, EmailHandle, EmailMessage, FileTransferHandle, FileTransferItem, LlmHandle, LlmMessage, LlmRequest, LlmResult, LlmStopReason, LlmUsage, MeterAttribution, ObjectStorageHandle, ObjectStorageItem, PaymentHandle, PaymentState, PaymentStatus, ProjectConnectors, RefundResult, SmsHandle, SmsMessage, } from './connectors';
|
|
9
|
+
export type { CreditGrantKind, CreditGrantOptions, CreditGrantResult, CreditHistoryPage, CreditMovement, CreditSpendOptions, CreditSpendResult, CreditsHandle, CreditTarget, } from './credits';
|
|
10
|
+
export type { MeterAddOptions, MeterAddResult, MeterBreakdownPage, MeterBreakdownQuery, MeterBreakdownRow, MeterHandle, MeterTarget, MeterTotalQuery, } from './meters';
|
|
11
|
+
export type { SubscriptionHandle, SubscriptionPeriod, SubscriptionSnapshot, SubscriptionState, SubscriptionTarget, SubscriptionTerm, } from './subscriptions';
|
|
12
|
+
export type { UserTaskAssignment, UserTaskDefinition, UserTaskForm, UserTaskFormField, UserTaskHandle, UserTaskOptions, UserTaskOutcome, UserTaskSnapshot, } from './userTasks';
|
|
13
|
+
export { Instant } from './instant';
|
|
14
|
+
export type { InstantUnit } from './instant';
|
|
15
|
+
export { Duration } from './duration';
|
|
16
|
+
export { Decimal } from './decimal';
|
|
17
|
+
export type { RoundingMode } from './decimal';
|
|
18
|
+
export { base64, hex, utf8 } from './encoding';
|
|
19
|
+
export * as url from './urls';
|
|
20
|
+
export type { QueryValue, UrlParts } from './urls';
|
|
21
|
+
export { canonicalJson } from './canonical-json';
|
|
22
|
+
export { chunk, uniqueBy } from './collections';
|
|
23
|
+
export { is } from './validators';
|
|
24
|
+
export { hash } from './hash';
|
|
25
|
+
export type { HashOutput } from './hash';
|