@foir/sdk 0.1.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 +110 -0
- package/dist/auth.d.ts +305 -0
- package/dist/auth.js +309 -0
- package/dist/chunk-ADO5FJNM.js +30 -0
- package/dist/client.d.ts +83 -0
- package/dist/client.js +81 -0
- package/dist/codegen/block-registry.d.ts +27 -0
- package/dist/codegen/block-registry.js +35 -0
- package/dist/codegen/block-scaffold.d.ts +28 -0
- package/dist/codegen/block-scaffold.js +45 -0
- package/dist/codegen/index.d.ts +65 -0
- package/dist/codegen/index.js +80 -0
- package/dist/content.d.ts +96 -0
- package/dist/content.js +161 -0
- package/dist/index.d.ts +394 -0
- package/dist/index.js +476 -0
- package/dist/media.d.ts +234 -0
- package/dist/media.js +399 -0
- package/dist/realtime.d.ts +111 -0
- package/dist/realtime.js +168 -0
- package/dist/server.d.ts +457 -0
- package/dist/server.js +296 -0
- package/dist/shared-DkWlEd2Z.d.ts +18 -0
- package/package.json +136 -0
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side types for Foir Editor SDK.
|
|
3
|
+
*
|
|
4
|
+
* Used by Hono API backends that communicate with the platform.
|
|
5
|
+
*/
|
|
6
|
+
/** Options for creating a ServerClient. */
|
|
7
|
+
interface ServerClientOptions {
|
|
8
|
+
/** Base URL for the platform API (e.g., 'https://api.example.com'). */
|
|
9
|
+
baseUrl: string;
|
|
10
|
+
/** Project-scoped API key (sk_* format). */
|
|
11
|
+
apiKey: string;
|
|
12
|
+
/**
|
|
13
|
+
* Optional config key. Retained for backwards compatibility with older
|
|
14
|
+
* extension scaffolds that pass it; the current client does not use it.
|
|
15
|
+
*/
|
|
16
|
+
configKey?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Where an editor iframe should appear in the admin record editor.
|
|
20
|
+
*/
|
|
21
|
+
interface EditorPlacement {
|
|
22
|
+
/** 'main-editor' replaces / augments the content tab; 'sidebar' renders in the sidebar. */
|
|
23
|
+
type: 'main-editor' | 'sidebar';
|
|
24
|
+
/** Full URL of the editor iframe. */
|
|
25
|
+
url: string;
|
|
26
|
+
/** Allowed postMessage origin (defaults to url origin). */
|
|
27
|
+
allowedOrigin?: string;
|
|
28
|
+
/** Iframe height: 'auto' (resize via postMessage), 'fill' (100%), or fixed px. */
|
|
29
|
+
height?: 'auto' | 'fill' | number;
|
|
30
|
+
/** Tab label for main-editor placements (defaults to config name). */
|
|
31
|
+
tabName?: string;
|
|
32
|
+
/** When true, hides the standard Content tab (main-editor only). */
|
|
33
|
+
hideContentTab?: boolean;
|
|
34
|
+
/** Which model keys this placement applies to; omit for all models. */
|
|
35
|
+
modelKeys?: string[];
|
|
36
|
+
}
|
|
37
|
+
/** GraphQL response shape. */
|
|
38
|
+
interface GraphQLResponse<T = Record<string, unknown>> {
|
|
39
|
+
data: T | null;
|
|
40
|
+
errors?: Array<{
|
|
41
|
+
message: string;
|
|
42
|
+
locations?: Array<{
|
|
43
|
+
line: number;
|
|
44
|
+
column: number;
|
|
45
|
+
}>;
|
|
46
|
+
path?: Array<string | number>;
|
|
47
|
+
extensions?: Record<string, unknown>;
|
|
48
|
+
}>;
|
|
49
|
+
}
|
|
50
|
+
/** The ServerClient interface — runtime communication with the platform. */
|
|
51
|
+
interface ServerClient {
|
|
52
|
+
/** Execute a GraphQL query against the platform public API. */
|
|
53
|
+
query<T = Record<string, unknown>>(query: string, variables?: Record<string, unknown>): Promise<GraphQLResponse<T>>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Server-side client for runtime communication with the Foir platform.
|
|
58
|
+
*
|
|
59
|
+
* Used by config API backends (e.g., Hono servers) to query the platform
|
|
60
|
+
* GraphQL API at runtime. Provisioning (models, operations, schedules) is
|
|
61
|
+
* handled by `foir push`. Record writes from upstream sources go through
|
|
62
|
+
* the scoped-token `upsertRecord` GraphQL mutation served by the
|
|
63
|
+
* integrations gateway, not through this client.
|
|
64
|
+
*
|
|
65
|
+
* Auth: All requests use an API key (x-api-key header).
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
/** Error thrown when a platform API request fails. */
|
|
69
|
+
declare class ServerClientError extends Error {
|
|
70
|
+
status?: number | undefined;
|
|
71
|
+
response?: unknown | undefined;
|
|
72
|
+
constructor(message: string, status?: number | undefined, response?: unknown | undefined);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Create a ServerClient for runtime platform communication.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* import { createServerClient } from '@foir/sdk/server';
|
|
80
|
+
*
|
|
81
|
+
* const client = createServerClient({
|
|
82
|
+
* baseUrl: 'https://api.example.com',
|
|
83
|
+
* apiKey: 'sk_project_xxx',
|
|
84
|
+
* });
|
|
85
|
+
*
|
|
86
|
+
* const { data } = await client.query('query { models { items { key } } }');
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
declare function createServerClient(options: ServerClientOptions): ServerClient;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Webhook verification helpers for extension API backends.
|
|
93
|
+
*
|
|
94
|
+
* Verifies HMAC-SHA256 signatures on incoming webhook requests
|
|
95
|
+
* from the EIDE platform.
|
|
96
|
+
*
|
|
97
|
+
* The platform sends two security headers:
|
|
98
|
+
* - `x-foir-signature`: HMAC-SHA256 hex signature of the request body
|
|
99
|
+
* - `x-foir-token`: Short-lived JWT (5min) containing extension context + API key
|
|
100
|
+
*
|
|
101
|
+
* Extensions should verify the signature and extract the API key from the token.
|
|
102
|
+
*/
|
|
103
|
+
/**
|
|
104
|
+
* Verify a webhook signature from the platform.
|
|
105
|
+
*
|
|
106
|
+
* The platform signs webhook payloads with HMAC-SHA256 using the
|
|
107
|
+
* extension's webhook secret. The signature is sent in the
|
|
108
|
+
* `x-foir-signature` header as a hex-encoded string.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```ts
|
|
112
|
+
* import { verifyWebhookSignature } from '@foir/sdk/server';
|
|
113
|
+
*
|
|
114
|
+
* app.post('/webhooks/entity-published', async (c) => {
|
|
115
|
+
* const body = await c.req.text();
|
|
116
|
+
* const signature = c.req.header('x-foir-signature') ?? '';
|
|
117
|
+
*
|
|
118
|
+
* const valid = await verifyWebhookSignature(body, signature, WEBHOOK_SECRET);
|
|
119
|
+
* if (!valid) return c.text('Invalid signature', 401);
|
|
120
|
+
*
|
|
121
|
+
* const payload = JSON.parse(body);
|
|
122
|
+
* // process webhook...
|
|
123
|
+
* });
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
declare function verifyWebhookSignature(payload: string, signature: string, secret: string): Promise<boolean>;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Verify a Foir scoped-token JWT (Ed25519, EdDSA) using Web Crypto.
|
|
130
|
+
*
|
|
131
|
+
* Operation handlers receive this token in the `X-Foir-Token` header (the
|
|
132
|
+
* dispatch token authenticating the inbound request) or embedded in the
|
|
133
|
+
* dispatch envelope's `callback.token` field (the callback token used as
|
|
134
|
+
* Bearer for mid-execution GraphQL calls back to api-public). Replaces the
|
|
135
|
+
* legacy HMAC + shared-secret verification for operation dispatches — the
|
|
136
|
+
* handler no longer needs `FOIR_SIGNING_SECRET` for the inbound path, only
|
|
137
|
+
* the URL of the platform's JWKS endpoint
|
|
138
|
+
* (`https://api.foir.dev/.well-known/jwks.json`).
|
|
139
|
+
*
|
|
140
|
+
* Lifted verbatim from the inline implementations in
|
|
141
|
+
* belstaff-translation-portal/src/lib/verify-scoped-token.ts and
|
|
142
|
+
* hydrogen-storefront/app/lib/foir/verify-scoped-token.ts so consumers can
|
|
143
|
+
* drop their copies in favor of the shared export. JWKS keys are cached
|
|
144
|
+
* per-isolate via `globalThis`; TTL matches the endpoint's
|
|
145
|
+
* Cache-Control max-age (5 minutes).
|
|
146
|
+
*/
|
|
147
|
+
interface ScopedTokenClaims {
|
|
148
|
+
iss: string;
|
|
149
|
+
/**
|
|
150
|
+
* Pipe-delimited `<tenantId>|<projectId>|<appName>` triple. Use
|
|
151
|
+
* {@link parseSubject} to split into a typed object.
|
|
152
|
+
*/
|
|
153
|
+
sub: string;
|
|
154
|
+
cap: Array<string>;
|
|
155
|
+
jti: string;
|
|
156
|
+
exp: number;
|
|
157
|
+
nbf: number;
|
|
158
|
+
iat: number;
|
|
159
|
+
ctx?: Record<string, string>;
|
|
160
|
+
/**
|
|
161
|
+
* Records-read model allow-list. Present when the operation declared one
|
|
162
|
+
* or more `records:read:<model>` capabilities. Pair with the
|
|
163
|
+
* `records:read` marker in {@link ScopedTokenClaims.cap} to authorize a
|
|
164
|
+
* record read for a specific model.
|
|
165
|
+
*/
|
|
166
|
+
rrm?: Array<string>;
|
|
167
|
+
/**
|
|
168
|
+
* Records-write model allow-list. Present when the operation declared
|
|
169
|
+
* one or more `records:write:<model>` capabilities. Pair with the
|
|
170
|
+
* `records:write` marker in {@link ScopedTokenClaims.cap} to authorize
|
|
171
|
+
* a record write for a specific model.
|
|
172
|
+
*/
|
|
173
|
+
rwm?: Array<string>;
|
|
174
|
+
}
|
|
175
|
+
interface ScopedTokenSubject {
|
|
176
|
+
tenantId: string;
|
|
177
|
+
projectId: string;
|
|
178
|
+
appName: string;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Parse the pipe-delimited `sub` claim emitted by the platform's
|
|
182
|
+
* scoped-token minter into its three components. Throws on a missing or
|
|
183
|
+
* empty segment — the platform never emits a partially-populated subject,
|
|
184
|
+
* so a malformed sub indicates a forged or corrupt token.
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* ```ts
|
|
188
|
+
* const { tenantId, projectId, appName } = parseSubject(claims.sub);
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
declare function parseSubject(sub: string): ScopedTokenSubject;
|
|
192
|
+
/**
|
|
193
|
+
* Extract the `records:read:<model>` allow-list from a verified claim
|
|
194
|
+
* set. Returns an empty array when the token grants no per-model read
|
|
195
|
+
* capabilities. Convenience over reading {@link ScopedTokenClaims.rrm}
|
|
196
|
+
* directly, mirroring the platform's
|
|
197
|
+
* `scopedtoken.Claims.RecordsReadModels` field.
|
|
198
|
+
*/
|
|
199
|
+
declare function recordsReadModels(claims: ScopedTokenClaims): Array<string>;
|
|
200
|
+
/**
|
|
201
|
+
* Extract the `records:write:<model>` allow-list from a verified claim
|
|
202
|
+
* set. Returns an empty array when the token grants no per-model write
|
|
203
|
+
* capabilities. Mirror of {@link recordsReadModels} for the write side.
|
|
204
|
+
*/
|
|
205
|
+
declare function recordsWriteModels(claims: ScopedTokenClaims): Array<string>;
|
|
206
|
+
interface VerifyScopedTokenOptions {
|
|
207
|
+
/**
|
|
208
|
+
* Expected `iss` claim. Defaults to `'foir-platform'`, the issuer the
|
|
209
|
+
* platform's scoped-token minter uses. Override only when verifying
|
|
210
|
+
* tokens from a non-default issuer (test harnesses, alternate deploys).
|
|
211
|
+
*/
|
|
212
|
+
expectedIssuer?: string;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Verify a scoped-token JWT against the platform's JWKS.
|
|
216
|
+
*
|
|
217
|
+
* Throws on malformed header, unknown kid, bad signature, missing/expired
|
|
218
|
+
* exp, future nbf (with 30s skew tolerance), or mismatched iss. Returns
|
|
219
|
+
* the decoded claim set on success.
|
|
220
|
+
*/
|
|
221
|
+
declare function verifyScopedToken(token: string, jwksUrl: string, options?: VerifyScopedTokenOptions): Promise<ScopedTokenClaims>;
|
|
222
|
+
/**
|
|
223
|
+
* Parse the semicolon-delimited `X-Foir-Context` header the platform
|
|
224
|
+
* attaches to dispatched operation requests. Shape:
|
|
225
|
+
* `project=P;app=A;operation=O;triggered_by=T;execution_id=E;causation_chain=a,b,c`.
|
|
226
|
+
*/
|
|
227
|
+
declare function parseContextHeader(raw: string | null): Record<string, string>;
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Type definitions for platform operations.
|
|
231
|
+
*
|
|
232
|
+
* These types match the platform's operation execution payload structure.
|
|
233
|
+
*/
|
|
234
|
+
/**
|
|
235
|
+
* Operation payload sent by the platform to extension endpoints.
|
|
236
|
+
*
|
|
237
|
+
* All operations receive this standardized payload structure regardless
|
|
238
|
+
* of how they're triggered (UI, API, lifecycle hook, schedule).
|
|
239
|
+
*/
|
|
240
|
+
interface OperationPayload {
|
|
241
|
+
/** Execution id — present so the extension can include it in callbacks. */
|
|
242
|
+
executionId?: string;
|
|
243
|
+
/** Unique key identifying this operation (e.g., 'tilly-process-note') */
|
|
244
|
+
operationKey: string;
|
|
245
|
+
/** How this operation was triggered */
|
|
246
|
+
trigger: OperationTrigger;
|
|
247
|
+
/** Input data provided by the caller */
|
|
248
|
+
input: Record<string, unknown>;
|
|
249
|
+
/** Content/field value (for field-triggered operations) */
|
|
250
|
+
content: unknown;
|
|
251
|
+
/** Record context (if operation was triggered by a record event) */
|
|
252
|
+
record: OperationRecordContext | null;
|
|
253
|
+
/** Platform context (tenant, project, user, locale) */
|
|
254
|
+
context: OperationContext;
|
|
255
|
+
/** Extension credentials (auto-injected by platform) */
|
|
256
|
+
credentials?: Record<string, unknown>;
|
|
257
|
+
/** Extension config (auto-injected by platform) */
|
|
258
|
+
config?: Record<string, unknown>;
|
|
259
|
+
/**
|
|
260
|
+
* Async-callback dispatch metadata. Present iff the operation was
|
|
261
|
+
* dispatched in `async-callback` mode. Contains the scoped token, the
|
|
262
|
+
* api-public GraphQL endpoint, and the per-op typed mutation names the
|
|
263
|
+
* extension should call back to.
|
|
264
|
+
*
|
|
265
|
+
* Absent for SYNC operations — the extension returns its result in the
|
|
266
|
+
* HTTP response body and there's nothing to call back to.
|
|
267
|
+
*/
|
|
268
|
+
callback?: OperationCallback;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Callback context the platform hands the extension when it dispatches an
|
|
272
|
+
* async-callback operation. Everything the extension needs to call back is
|
|
273
|
+
* here — endpoint, auth token, signing secret reference (the secret itself
|
|
274
|
+
* lives on the extension, set out of band; the platform only sends the
|
|
275
|
+
* token), and the per-op mutation names so the extension doesn't need to
|
|
276
|
+
* derive them from the operation key.
|
|
277
|
+
*/
|
|
278
|
+
interface OperationCallback {
|
|
279
|
+
/** api-public GraphQL endpoint, e.g. https://api.foir.dev/graphql */
|
|
280
|
+
gqlEndpoint: string;
|
|
281
|
+
/** Bearer token for the Authorization header (Ed25519, single execution scope) */
|
|
282
|
+
token: string;
|
|
283
|
+
/** RFC3339 expiry — extensions can short-circuit work past this. */
|
|
284
|
+
expiresAt: string;
|
|
285
|
+
/** Per-op typed mutation names the extension should call back with. */
|
|
286
|
+
mutations: {
|
|
287
|
+
complete: string;
|
|
288
|
+
fail: string;
|
|
289
|
+
progress: string;
|
|
290
|
+
cancel: string;
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Trigger information describing how the operation was invoked.
|
|
295
|
+
*/
|
|
296
|
+
interface OperationTrigger {
|
|
297
|
+
/** Trigger type */
|
|
298
|
+
type: 'ui' | 'api' | 'lifecycle' | 'field';
|
|
299
|
+
/** Field key (for field-triggered operations) */
|
|
300
|
+
fieldKey?: string;
|
|
301
|
+
/** Field type (for field-triggered operations) */
|
|
302
|
+
fieldType?: string;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Record context provided when operation is triggered by a record event.
|
|
306
|
+
*/
|
|
307
|
+
interface OperationRecordContext {
|
|
308
|
+
/** Record ID */
|
|
309
|
+
id: string;
|
|
310
|
+
/** Model key (e.g., 'tilly_note') */
|
|
311
|
+
modelKey: string;
|
|
312
|
+
/** Version ID (if versioned record) */
|
|
313
|
+
versionId?: string;
|
|
314
|
+
/** Record content/data */
|
|
315
|
+
data: Record<string, unknown>;
|
|
316
|
+
/** Record metadata */
|
|
317
|
+
metadata: {
|
|
318
|
+
/** Natural key (slug, handle, etc.) */
|
|
319
|
+
naturalKey?: string;
|
|
320
|
+
/** Additional metadata fields */
|
|
321
|
+
[key: string]: unknown;
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Platform context provided to all operations.
|
|
326
|
+
*/
|
|
327
|
+
interface OperationContext {
|
|
328
|
+
/** Tenant ID */
|
|
329
|
+
tenantId: string;
|
|
330
|
+
/** Project ID */
|
|
331
|
+
projectId: string;
|
|
332
|
+
/** User ID (if user-triggered) */
|
|
333
|
+
userId?: string;
|
|
334
|
+
/** Customer ID (if customer-scoped operation) */
|
|
335
|
+
customerId?: string;
|
|
336
|
+
/** Locale code (if locale-specific) */
|
|
337
|
+
locale?: string;
|
|
338
|
+
/** Timestamp when operation was triggered */
|
|
339
|
+
timestamp: string;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Standard operation result shape.
|
|
343
|
+
*
|
|
344
|
+
* All operations should return this structure.
|
|
345
|
+
*/
|
|
346
|
+
interface OperationResult {
|
|
347
|
+
/** Whether the operation succeeded */
|
|
348
|
+
success: boolean;
|
|
349
|
+
/** Operation result data (if successful) */
|
|
350
|
+
result?: unknown;
|
|
351
|
+
/** Error information (if failed) */
|
|
352
|
+
error?: {
|
|
353
|
+
/** Error code (e.g., 'MISSING_INPUT', 'PROCESSING_FAILED') */
|
|
354
|
+
code: string;
|
|
355
|
+
/** Human-readable error message */
|
|
356
|
+
message: string;
|
|
357
|
+
/** Additional error details */
|
|
358
|
+
details?: Record<string, unknown>;
|
|
359
|
+
};
|
|
360
|
+
/** Optional metadata (timing, cost, etc.) */
|
|
361
|
+
metadata?: Record<string, unknown>;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Callback client for extensions running async operations.
|
|
366
|
+
*
|
|
367
|
+
* The platform dispatches with `mode='async'` and includes a `callback`
|
|
368
|
+
* block in the operation payload. The extension acks 202, kicks the work
|
|
369
|
+
* off in its own durable runtime (CF Queue, BullMQ, etc.), and later
|
|
370
|
+
* calls back with one of:
|
|
371
|
+
*
|
|
372
|
+
* - `complete(result)` — operation succeeded; result conforms to the
|
|
373
|
+
* operation's `output_schema` (per-op typed via codegen).
|
|
374
|
+
* - `fail(code, message, opts?)` — operation failed; `retryable=true`
|
|
375
|
+
* pushes a DLQ entry.
|
|
376
|
+
* - `progress({pct, message, metadata})` — non-terminal update; the
|
|
377
|
+
* monotonic guard at the platform DB layer drops out-of-order packets.
|
|
378
|
+
* - `cancel()` — extension self-cancels (rare; admins normally drive
|
|
379
|
+
* cancel via the admin app's ConnectRPC path).
|
|
380
|
+
*
|
|
381
|
+
* Each call carries:
|
|
382
|
+
* - `Authorization: Bearer <callback.token>` — Ed25519 scoped token.
|
|
383
|
+
* - `X-Foir-Signature: sha256=<hex>` — HMAC of the raw request body
|
|
384
|
+
* keyed on the project's `operations.signing_secret`. The secret is
|
|
385
|
+
* out-of-band (CLI publishes it to the extension on push); the SDK
|
|
386
|
+
* only handles the HMAC computation.
|
|
387
|
+
*
|
|
388
|
+
* Both response body shape and content-type follow the GraphQL spec —
|
|
389
|
+
* extensions importing this client receive typed result data.
|
|
390
|
+
*/
|
|
391
|
+
|
|
392
|
+
/** Shape of a successful response from any callback mutation. */
|
|
393
|
+
interface CallbackResult {
|
|
394
|
+
/**
|
|
395
|
+
* Status as seen by the platform AFTER the call. One of:
|
|
396
|
+
* pending|dispatched|running|completed|failed|cancelled|timed_out|progress_stale.
|
|
397
|
+
* Always set even on idempotent / cancelled calls.
|
|
398
|
+
*/
|
|
399
|
+
status: string;
|
|
400
|
+
/**
|
|
401
|
+
* True when the admin cancelled the execution while the extension was
|
|
402
|
+
* processing — the platform refused to overwrite the cancelled state.
|
|
403
|
+
* Extensions should stop work and (optionally) call `fail('CANCELLED')`.
|
|
404
|
+
*/
|
|
405
|
+
cancelled: boolean;
|
|
406
|
+
/**
|
|
407
|
+
* Progress mutations only: false when the monotonic guard rejected an
|
|
408
|
+
* out-of-order update. Extensions can use this to detect packet
|
|
409
|
+
* reordering without erroring; missing on complete/fail/cancel.
|
|
410
|
+
*/
|
|
411
|
+
applied?: boolean;
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Per-operation callback client. `TResult` is the operation's typed result
|
|
415
|
+
* shape — supply the type generated by graphql-codegen against the
|
|
416
|
+
* api-public schema (`Complete{Op}ExecutionMutationVariables['result']`).
|
|
417
|
+
*/
|
|
418
|
+
interface CallbackClient<TResult = unknown> {
|
|
419
|
+
complete(result: TResult): Promise<CallbackResult>;
|
|
420
|
+
fail(code: string, message: string, opts?: {
|
|
421
|
+
retryable?: boolean;
|
|
422
|
+
details?: Record<string, unknown>;
|
|
423
|
+
}): Promise<CallbackResult>;
|
|
424
|
+
/**
|
|
425
|
+
* Returns `{cancelled: true}` when the admin has cancelled — extension
|
|
426
|
+
* must stop work. `applied: false` means the monotonic guard dropped
|
|
427
|
+
* the update because pct was lower than the persisted value.
|
|
428
|
+
*/
|
|
429
|
+
progress(update: {
|
|
430
|
+
pct?: number;
|
|
431
|
+
message?: string;
|
|
432
|
+
metadata?: Record<string, unknown>;
|
|
433
|
+
}): Promise<CallbackResult>;
|
|
434
|
+
cancel(): Promise<CallbackResult>;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Construct a callback client from the dispatch payload's callback block
|
|
438
|
+
* plus the runtime-provided execution id and signing secret.
|
|
439
|
+
*
|
|
440
|
+
* `executionId` comes from the same operation payload that delivered
|
|
441
|
+
* `callback`; pass them together so the SDK doesn't have to re-parse the
|
|
442
|
+
* payload structure on every call.
|
|
443
|
+
*
|
|
444
|
+
* `signingSecret` lives on the extension (set as `FOIR_SIGNING_SECRET` or
|
|
445
|
+
* equivalent env var). The CLI publishes it during `foir push` so it's
|
|
446
|
+
* available before any callback runs — see foir-cli writeConfigCredential.
|
|
447
|
+
*
|
|
448
|
+
* `fetch` is overridable for testability and to support runtimes (CF
|
|
449
|
+
* Workers, Node) where `fetch` may not be the global.
|
|
450
|
+
*/
|
|
451
|
+
declare function createCallbackClient<TResult = unknown>(callback: OperationCallback, opts: {
|
|
452
|
+
executionId: string;
|
|
453
|
+
signingSecret: string;
|
|
454
|
+
fetch?: typeof fetch;
|
|
455
|
+
}): CallbackClient<TResult>;
|
|
456
|
+
|
|
457
|
+
export { type CallbackClient, type CallbackResult, type EditorPlacement, type GraphQLResponse, type OperationCallback, type OperationContext, type OperationPayload, type OperationRecordContext, type OperationResult, type OperationTrigger, type ScopedTokenClaims, type ScopedTokenSubject, type ServerClient, ServerClientError, type ServerClientOptions, type VerifyScopedTokenOptions, createCallbackClient, createServerClient, parseContextHeader, parseSubject, recordsReadModels, recordsWriteModels, verifyScopedToken, verifyWebhookSignature };
|