@docmana/sdk 0.28.1 → 0.36.0-hitl.2
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/CHANGELOG.md +300 -209
- package/LICENSE +21 -21
- package/README.md +264 -0
- package/dist/authoring.d.ts +317 -0
- package/dist/cli.mjs +387 -2
- package/dist/cli.mjs.map +1 -1
- package/dist/client.d.ts +6 -0
- package/dist/errors.d.ts +7 -0
- package/dist/execution-events.d.ts +47 -0
- package/dist/http/http-client.d.ts +2 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +451 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +440 -3
- package/dist/index.mjs.map +1 -1
- package/dist/models/execution-status.enum.d.ts +1 -1
- package/dist/review-events.d.ts +36 -0
- package/dist/reviews.d.ts +180 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -28,11 +28,419 @@ function normalizeApiBaseUrl(value) {
|
|
|
28
28
|
return /\/v\d+$/i.test(trimmed) ? trimmed : `${trimmed}/v1`;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
// src/sdk/authoring.ts
|
|
32
|
+
function identity(id) {
|
|
33
|
+
if (!/^[A-Za-z0-9_-]{1,200}$/.test(id)) throw new Error("Invalid formula identifier");
|
|
34
|
+
return encodeURIComponent(id);
|
|
35
|
+
}
|
|
36
|
+
var FormulaAuthoring = class {
|
|
37
|
+
constructor(http) {
|
|
38
|
+
this.http = http;
|
|
39
|
+
}
|
|
40
|
+
http;
|
|
41
|
+
/** Read-only, revision-pinned definitions. Assisted execution belongs to the server-side Flows POC. */
|
|
42
|
+
documentTrialDefinitions(spec, options) {
|
|
43
|
+
identity(spec.flowId);
|
|
44
|
+
if (Boolean(spec.node) === (spec.allNodes === true))
|
|
45
|
+
throw new Error("Select one node or all nodes");
|
|
46
|
+
if (spec.node) identity(spec.node);
|
|
47
|
+
return this.request("POST", "document-trial/definitions", options, spec);
|
|
48
|
+
}
|
|
49
|
+
/** Native manual execution through Consumer Edge; assisted trials use definitions plus server-side Flows. */
|
|
50
|
+
async trialDocument(file, filename, spec, options) {
|
|
51
|
+
if (!options.organization.trim()) throw new Error("Organization is required");
|
|
52
|
+
if (!file.size || file.size > 20 * 1024 * 1024 || !/\.(pdf|jpeg|jpg|png|bmp|tiff|tif|heic)$/i.test(filename))
|
|
53
|
+
throw new Error("Invalid trial document");
|
|
54
|
+
if ("flowId" in spec) {
|
|
55
|
+
identity(spec.flowId);
|
|
56
|
+
if (Boolean(spec.node) === (spec.allNodes === true))
|
|
57
|
+
throw new Error("Select one node or all nodes");
|
|
58
|
+
if (spec.node) identity(spec.node);
|
|
59
|
+
} else if (!Array.isArray(spec.nodes) || !spec.nodes.length || spec.nodes.length > 100)
|
|
60
|
+
throw new Error("Invalid trial nodes");
|
|
61
|
+
const body = new FormData();
|
|
62
|
+
body.set("file", file, filename);
|
|
63
|
+
body.set("spec", JSON.stringify(spec));
|
|
64
|
+
return this.http.requestJson("POST", "/authoring/document-trial", {
|
|
65
|
+
query: { organization: options.organization },
|
|
66
|
+
signal: options.signal,
|
|
67
|
+
body
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
editorCatalog(options) {
|
|
71
|
+
return this.request("GET", "editor-catalog", options);
|
|
72
|
+
}
|
|
73
|
+
generateMapping(body, options) {
|
|
74
|
+
return this.request("POST", "generate-mapping", options, body);
|
|
75
|
+
}
|
|
76
|
+
openConversation(body, options) {
|
|
77
|
+
identity(body.flow_id);
|
|
78
|
+
if (body.node_id) identity(body.node_id);
|
|
79
|
+
return this.request("POST", "conversations", options, body);
|
|
80
|
+
}
|
|
81
|
+
sendConversationMessage(id, content, options) {
|
|
82
|
+
return this.request("POST", `conversations/${identity(id)}/messages`, options, { content });
|
|
83
|
+
}
|
|
84
|
+
confirmConversation(id, body, options) {
|
|
85
|
+
return this.request("POST", `conversations/${identity(id)}/confirm`, options, body);
|
|
86
|
+
}
|
|
87
|
+
request(method, path, options, body) {
|
|
88
|
+
if (!options.organization.trim()) throw new Error("Organization is required");
|
|
89
|
+
return this.http.requestJson(method, `/authoring/${path}`, {
|
|
90
|
+
query: { organization: options.organization },
|
|
91
|
+
signal: options.signal,
|
|
92
|
+
...body === void 0 ? {} : {
|
|
93
|
+
body: JSON.stringify(body),
|
|
94
|
+
headers: { "content-type": "application/json" }
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
list(options) {
|
|
99
|
+
const offset = options.offset ?? 0, limit = options.limit ?? 50;
|
|
100
|
+
if (!Number.isInteger(offset) || offset < 0 || !Number.isInteger(limit) || limit < 1 || limit > 200)
|
|
101
|
+
throw new Error("Invalid authoring pagination");
|
|
102
|
+
return this.request(
|
|
103
|
+
"GET",
|
|
104
|
+
`flows?offset=${offset}&limit=${limit}&sort=${encodeURIComponent(options.sort ?? "id")}`,
|
|
105
|
+
options
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
remove(id, options) {
|
|
109
|
+
return this.request("DELETE", `flows/${identity(id)}`, options);
|
|
110
|
+
}
|
|
111
|
+
async exportArchive(id, options) {
|
|
112
|
+
if (!options.organization.trim()) throw new Error("Organization is required");
|
|
113
|
+
return (await this.http.requestBytes("GET", `/authoring/flows/${identity(id)}/export`, {
|
|
114
|
+
query: { organization: options.organization },
|
|
115
|
+
signal: options.signal
|
|
116
|
+
})).bytes;
|
|
117
|
+
}
|
|
118
|
+
importArchive(file, filename, options) {
|
|
119
|
+
if (!options.organization.trim()) throw new Error("Organization is required");
|
|
120
|
+
if (!/\.(zip|docmana)$/i.test(filename) || file.size > 10 * 1024 * 1024)
|
|
121
|
+
throw new Error("Invalid formula archive");
|
|
122
|
+
const body = new FormData();
|
|
123
|
+
body.append("file", file, filename);
|
|
124
|
+
return this.http.requestJson("POST", "/authoring/flows/import", {
|
|
125
|
+
query: {
|
|
126
|
+
organization: options.organization,
|
|
127
|
+
confirmOverwrite: String(options.confirmOverwrite === true)
|
|
128
|
+
},
|
|
129
|
+
body,
|
|
130
|
+
signal: options.signal
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
get(id, options) {
|
|
134
|
+
return this.request("GET", `flows/${identity(id)}`, options);
|
|
135
|
+
}
|
|
136
|
+
create(body, options) {
|
|
137
|
+
return this.request("POST", "flows", options, body);
|
|
138
|
+
}
|
|
139
|
+
save(id, body, options) {
|
|
140
|
+
return this.request("PATCH", `flows/${identity(id)}/draft`, options, body);
|
|
141
|
+
}
|
|
142
|
+
validate(id, revisions, options) {
|
|
143
|
+
return this.request("POST", `flows/${identity(id)}/validate`, options, {
|
|
144
|
+
expectedRevisions: revisions
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
publish(id, body, options) {
|
|
148
|
+
return this.request("POST", `flows/${identity(id)}/publish`, options, body);
|
|
149
|
+
}
|
|
150
|
+
history(id, kind, options) {
|
|
151
|
+
if (kind !== "snapshots" && kind !== "published") throw new Error("Invalid history kind");
|
|
152
|
+
const offset = options.offset ?? 0, limit = options.limit ?? 20;
|
|
153
|
+
if (!Number.isInteger(offset) || offset < 0 || !Number.isInteger(limit) || limit < 1 || limit > 100)
|
|
154
|
+
throw new Error("Invalid history pagination");
|
|
155
|
+
return this.request(
|
|
156
|
+
"GET",
|
|
157
|
+
`flows/${identity(id)}/history/${kind}?offset=${offset}&limit=${limit}`,
|
|
158
|
+
options
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
flags(options) {
|
|
162
|
+
return this.request("GET", "feature-flags", options);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// src/sdk/reviews.ts
|
|
167
|
+
function segment(value) {
|
|
168
|
+
if (!value || value === "." || value === ".." || /[\\/]/.test(value) || [...value].some((char) => char.charCodeAt(0) < 32))
|
|
169
|
+
throw new Error("Invalid review identifier");
|
|
170
|
+
return encodeURIComponent(value);
|
|
171
|
+
}
|
|
172
|
+
var Reviews = class {
|
|
173
|
+
constructor(http) {
|
|
174
|
+
this.http = http;
|
|
175
|
+
}
|
|
176
|
+
http;
|
|
177
|
+
/** Repeatable metadata read: never consumes the final execution result. */
|
|
178
|
+
calculation(executionId, options) {
|
|
179
|
+
return this.http.requestJson("GET", `/executions/${segment(executionId)}/review/calculation`, {
|
|
180
|
+
signal: options.signal,
|
|
181
|
+
query: { organization: options.organization }
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
/** Published formula structure only. Compare its version with the review's flowVersion. */
|
|
185
|
+
outline(flowId, options) {
|
|
186
|
+
return this.http.requestJson("GET", `/flows/${segment(flowId)}/outline`, {
|
|
187
|
+
signal: options.signal,
|
|
188
|
+
query: { organization: options.organization }
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
list(options) {
|
|
192
|
+
return this.http.requestJson("GET", "/reviews", {
|
|
193
|
+
signal: options.signal,
|
|
194
|
+
query: {
|
|
195
|
+
organization: options.organization,
|
|
196
|
+
...options.status ? { status: options.status } : {},
|
|
197
|
+
...options.cursor ? { cursor: options.cursor } : {},
|
|
198
|
+
...options.limit ? { limit: String(options.limit) } : {}
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
get(executionId, options) {
|
|
203
|
+
return this.http.requestJson("GET", `/executions/${segment(executionId)}/review`, {
|
|
204
|
+
signal: options.signal,
|
|
205
|
+
query: { organization: options.organization }
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
decide(executionId, decision, options) {
|
|
209
|
+
return this.http.requestJson("POST", `/executions/${segment(executionId)}/review`, {
|
|
210
|
+
signal: options.signal,
|
|
211
|
+
query: { organization: options.organization },
|
|
212
|
+
headers: { "content-type": "application/json" },
|
|
213
|
+
body: JSON.stringify(decision)
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
/** Streaming Response: callers own consumption/cancellation. Never buffers the PDF. */
|
|
217
|
+
document(executionId, docKey, resource, options) {
|
|
218
|
+
if (typeof resource === "object" && (!Number.isSafeInteger(resource.page) || resource.page < 1 || resource.page > 999999))
|
|
219
|
+
throw new Error("Invalid page number");
|
|
220
|
+
const path = typeof resource === "object" ? `pages/${resource.page}` : resource;
|
|
221
|
+
const headers = Object.fromEntries(
|
|
222
|
+
Object.entries({
|
|
223
|
+
range: options.range,
|
|
224
|
+
"if-range": options.ifRange,
|
|
225
|
+
"if-none-match": options.ifNoneMatch,
|
|
226
|
+
"if-modified-since": options.ifModifiedSince
|
|
227
|
+
}).filter((entry) => typeof entry[1] === "string")
|
|
228
|
+
);
|
|
229
|
+
return this.http.requestRaw(
|
|
230
|
+
"GET",
|
|
231
|
+
`/executions/${segment(executionId)}/review/documents/${segment(docKey)}/${path}`,
|
|
232
|
+
{
|
|
233
|
+
signal: options.signal,
|
|
234
|
+
headers,
|
|
235
|
+
acceptStatuses: [304, 416],
|
|
236
|
+
query: {
|
|
237
|
+
organization: options.organization,
|
|
238
|
+
...options.version ? { v: options.version } : {},
|
|
239
|
+
...options.size ? { size: options.size } : {}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
// src/sdk/execution-events.ts
|
|
247
|
+
import { createHmac as createHmac2, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
248
|
+
|
|
249
|
+
// src/sdk/review-events.ts
|
|
250
|
+
import { createHmac, timingSafeEqual } from "crypto";
|
|
251
|
+
var REVIEW_EVENT_TYPES = [
|
|
252
|
+
"execution.awaiting_review",
|
|
253
|
+
"execution.review_done",
|
|
254
|
+
"execution.review_closed",
|
|
255
|
+
"execution.review_expired"
|
|
256
|
+
];
|
|
257
|
+
var ReviewEventVerificationError = class extends Error {
|
|
258
|
+
constructor(reason) {
|
|
259
|
+
super(`Invalid review event ${reason}`);
|
|
260
|
+
this.reason = reason;
|
|
261
|
+
this.name = "ReviewEventVerificationError";
|
|
262
|
+
}
|
|
263
|
+
reason;
|
|
264
|
+
};
|
|
265
|
+
function parseReviewEventCallback(value) {
|
|
266
|
+
const fail = () => {
|
|
267
|
+
throw new ReviewEventVerificationError("payload");
|
|
268
|
+
};
|
|
269
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return fail();
|
|
270
|
+
const raw = value;
|
|
271
|
+
const text = (key) => {
|
|
272
|
+
const v = raw[key];
|
|
273
|
+
if (typeof v !== "string" || !v.trim() || v.length > 512 || [...v].some((char) => char.charCodeAt(0) < 32))
|
|
274
|
+
return fail();
|
|
275
|
+
return v;
|
|
276
|
+
};
|
|
277
|
+
if (raw.schemaVersion !== 1 || !REVIEW_EVENT_TYPES.includes(raw.type))
|
|
278
|
+
return fail();
|
|
279
|
+
const event = {
|
|
280
|
+
schemaVersion: 1,
|
|
281
|
+
eventId: text("eventId"),
|
|
282
|
+
type: raw.type,
|
|
283
|
+
organization: text("organization"),
|
|
284
|
+
executionResultId: text("executionResultId"),
|
|
285
|
+
reviewId: text("reviewId"),
|
|
286
|
+
publishedAt: text("publishedAt")
|
|
287
|
+
};
|
|
288
|
+
if (!Number.isFinite(Date.parse(event.publishedAt))) return fail();
|
|
289
|
+
for (const key of ["flowId", "nodeId"])
|
|
290
|
+
if (raw[key] !== void 0) event[key] = text(key);
|
|
291
|
+
for (const key of ["flowVersion", "reviewVersion"]) {
|
|
292
|
+
if (raw[key] === void 0) continue;
|
|
293
|
+
if (!Number.isSafeInteger(raw[key]) || Number(raw[key]) < 1) return fail();
|
|
294
|
+
event[key] = Number(raw[key]);
|
|
295
|
+
}
|
|
296
|
+
if (raw.documentKeys !== void 0) {
|
|
297
|
+
if (!Array.isArray(raw.documentKeys) || raw.documentKeys.length > 1e3 || raw.documentKeys.some((v) => typeof v !== "string" || !v || v.length > 512))
|
|
298
|
+
return fail();
|
|
299
|
+
event.documentKeys = raw.documentKeys;
|
|
300
|
+
}
|
|
301
|
+
if (raw.decision !== void 0) {
|
|
302
|
+
if (!["continue", "exclude", "rerun", "reject"].includes(String(raw.decision))) return fail();
|
|
303
|
+
event.decision = raw.decision;
|
|
304
|
+
}
|
|
305
|
+
if (raw.reviewStatus !== void 0) {
|
|
306
|
+
if (!["completed", "rejected", "failed"].includes(String(raw.reviewStatus))) return fail();
|
|
307
|
+
event.reviewStatus = raw.reviewStatus;
|
|
308
|
+
}
|
|
309
|
+
if (event.type === "execution.review_done" && (!event.decision || !event.reviewVersion))
|
|
310
|
+
return fail();
|
|
311
|
+
if (event.type === "execution.review_closed" && !event.reviewStatus) return fail();
|
|
312
|
+
return event;
|
|
313
|
+
}
|
|
314
|
+
function verifyReviewEventCallback(options) {
|
|
315
|
+
const { body, signature, timestamp, secret } = options;
|
|
316
|
+
if (!timestamp || !/^\d{10,13}$/.test(timestamp))
|
|
317
|
+
throw new ReviewEventVerificationError("timestamp");
|
|
318
|
+
const age = Math.abs((options.nowMs ?? Date.now()) / 1e3 - Number(timestamp));
|
|
319
|
+
if (age > (options.toleranceSeconds ?? 300)) throw new ReviewEventVerificationError("timestamp");
|
|
320
|
+
if (secret.length < 32 || !signature || !/^v1=[a-f0-9]{64}$/.test(signature))
|
|
321
|
+
throw new ReviewEventVerificationError("signature");
|
|
322
|
+
const expected = createHmac("sha256", secret).update(`${timestamp}.${body}`).digest();
|
|
323
|
+
if (!timingSafeEqual(expected, Buffer.from(signature.slice(3), "hex")))
|
|
324
|
+
throw new ReviewEventVerificationError("signature");
|
|
325
|
+
let value;
|
|
326
|
+
try {
|
|
327
|
+
value = JSON.parse(body);
|
|
328
|
+
} catch {
|
|
329
|
+
throw new ReviewEventVerificationError("payload");
|
|
330
|
+
}
|
|
331
|
+
const event = parseReviewEventCallback(value);
|
|
332
|
+
if (options.organization !== void 0 && event.organization !== options.organization)
|
|
333
|
+
throw new ReviewEventVerificationError("organization");
|
|
334
|
+
return event;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// src/sdk/execution-events.ts
|
|
338
|
+
var EXECUTION_NODE_EVENT_TYPES = [
|
|
339
|
+
"execution.node.started",
|
|
340
|
+
"execution.node.completed",
|
|
341
|
+
"execution.node.failed",
|
|
342
|
+
"execution.node.reused"
|
|
343
|
+
];
|
|
344
|
+
function parseExecutionEventCallback(value) {
|
|
345
|
+
const raw = value;
|
|
346
|
+
if (!raw || !EXECUTION_NODE_EVENT_TYPES.includes(raw.type))
|
|
347
|
+
return parseReviewEventCallback(value);
|
|
348
|
+
const fail = () => {
|
|
349
|
+
throw new ReviewEventVerificationError("payload");
|
|
350
|
+
};
|
|
351
|
+
const text = (key) => {
|
|
352
|
+
const v = raw[key];
|
|
353
|
+
return typeof v === "string" && v.length > 0 && v.length <= 512 && [...v].every((c) => c.charCodeAt(0) >= 32) ? v : fail();
|
|
354
|
+
};
|
|
355
|
+
const integer = (key) => Number.isSafeInteger(raw[key]) && Number(raw[key]) >= 1 ? Number(raw[key]) : fail();
|
|
356
|
+
if (raw.schemaVersion !== 1) return fail();
|
|
357
|
+
const event = {
|
|
358
|
+
schemaVersion: 1,
|
|
359
|
+
eventId: text("eventId"),
|
|
360
|
+
type: raw.type,
|
|
361
|
+
organization: text("organization"),
|
|
362
|
+
executionResultId: text("executionResultId"),
|
|
363
|
+
sequence: integer("sequence"),
|
|
364
|
+
occurredAt: text("occurredAt"),
|
|
365
|
+
nodeId: text("nodeId"),
|
|
366
|
+
nodeType: text("nodeType"),
|
|
367
|
+
revision: integer("revision"),
|
|
368
|
+
attemptId: text("attemptId"),
|
|
369
|
+
documentKeys: []
|
|
370
|
+
};
|
|
371
|
+
if (!Number.isFinite(Date.parse(event.occurredAt))) return fail();
|
|
372
|
+
if (!Array.isArray(raw.documentKeys) || !raw.documentKeys.length || raw.documentKeys.length > 1e3 || raw.documentKeys.some(
|
|
373
|
+
(v) => typeof v !== "string" || !v || v.length > 512 || [...v].some((c) => c.charCodeAt(0) < 32)
|
|
374
|
+
))
|
|
375
|
+
return fail();
|
|
376
|
+
event.documentKeys = raw.documentKeys;
|
|
377
|
+
if (raw.flowId !== void 0) event.flowId = text("flowId");
|
|
378
|
+
if (raw.flowVersion !== void 0) event.flowVersion = integer("flowVersion");
|
|
379
|
+
if (raw.publishedAt !== void 0) {
|
|
380
|
+
event.publishedAt = text("publishedAt");
|
|
381
|
+
if (!Number.isFinite(Date.parse(event.publishedAt))) return fail();
|
|
382
|
+
}
|
|
383
|
+
return event;
|
|
384
|
+
}
|
|
385
|
+
function verifyExecutionEventCallback(options) {
|
|
386
|
+
const { body, signature, timestamp, secret } = options;
|
|
387
|
+
if (!timestamp || !/^\d{10,13}$/.test(timestamp) || Math.abs((options.nowMs ?? Date.now()) / 1e3 - Number(timestamp)) > (options.toleranceSeconds ?? 300))
|
|
388
|
+
throw new ReviewEventVerificationError("timestamp");
|
|
389
|
+
if (secret.length < 32 || !signature || !/^v1=[a-f0-9]{64}$/.test(signature))
|
|
390
|
+
throw new ReviewEventVerificationError("signature");
|
|
391
|
+
const expected = createHmac2("sha256", secret).update(`${timestamp}.${body}`).digest();
|
|
392
|
+
if (!timingSafeEqual2(expected, Buffer.from(signature.slice(3), "hex")))
|
|
393
|
+
throw new ReviewEventVerificationError("signature");
|
|
394
|
+
let value;
|
|
395
|
+
try {
|
|
396
|
+
value = JSON.parse(body);
|
|
397
|
+
} catch {
|
|
398
|
+
throw new ReviewEventVerificationError("payload");
|
|
399
|
+
}
|
|
400
|
+
const event = parseExecutionEventCallback(value);
|
|
401
|
+
if (options.organization !== void 0 && event.organization !== options.organization)
|
|
402
|
+
throw new ReviewEventVerificationError("organization");
|
|
403
|
+
return event;
|
|
404
|
+
}
|
|
405
|
+
var ExecutionEvents = class {
|
|
406
|
+
constructor(http) {
|
|
407
|
+
this.http = http;
|
|
408
|
+
}
|
|
409
|
+
http;
|
|
410
|
+
/** One bounded page; never polls for completion or consumes a final result. */
|
|
411
|
+
async list(id, options) {
|
|
412
|
+
const after = options.after ?? 0, limit = options.limit ?? 100;
|
|
413
|
+
if (!id || id.length > 512 || id === "." || id === ".." || /[\\/]/.test(id) || [...id].some((c) => c.charCodeAt(0) < 32) || !options.organization?.trim() || !Number.isSafeInteger(after) || after < 0 || !Number.isSafeInteger(limit) || limit < 1 || limit > 100)
|
|
414
|
+
throw new Error("Invalid execution event query");
|
|
415
|
+
const page = await this.http.requestJson(
|
|
416
|
+
"GET",
|
|
417
|
+
`/executions/${encodeURIComponent(id)}/events`,
|
|
418
|
+
{
|
|
419
|
+
signal: options.signal,
|
|
420
|
+
query: { organization: options.organization, after: String(after), limit: String(limit) }
|
|
421
|
+
}
|
|
422
|
+
);
|
|
423
|
+
if (page.executionResultId !== id || !Array.isArray(page.events) || page.events.length > limit || !Number.isSafeInteger(page.lastSequence) || page.lastSequence < 0 || typeof page.truncated !== "boolean")
|
|
424
|
+
throw new ReviewEventVerificationError("payload");
|
|
425
|
+
const events = page.events.map((value) => parseExecutionEventCallback(value));
|
|
426
|
+
if (events.some(
|
|
427
|
+
(event, i) => !("sequence" in event) || event.executionResultId !== id || event.organization !== options.organization || event.sequence <= (i ? events[i - 1].sequence : after) || event.sequence > page.lastSequence
|
|
428
|
+
))
|
|
429
|
+
throw new ReviewEventVerificationError("payload");
|
|
430
|
+
if (page.nextAfter !== null && (!Number.isSafeInteger(page.nextAfter) || page.nextAfter <= after || page.nextAfter !== events.at(-1)?.sequence))
|
|
431
|
+
throw new ReviewEventVerificationError("payload");
|
|
432
|
+
return { ...page, events };
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
|
|
31
436
|
// src/sdk/errors.ts
|
|
32
437
|
var DocmanaError = class extends Error {
|
|
33
438
|
status;
|
|
34
439
|
requestId;
|
|
35
440
|
code;
|
|
441
|
+
/** Public API business code; `code` retains the SDK's existing error category. */
|
|
442
|
+
apiCode;
|
|
443
|
+
reviewConflict;
|
|
36
444
|
constructor(message, opts = {}) {
|
|
37
445
|
super(message);
|
|
38
446
|
this.name = new.target.name;
|
|
@@ -158,15 +566,28 @@ var HttpClient = class {
|
|
|
158
566
|
if (res.status === 401 && this.opts.getAccessToken) {
|
|
159
567
|
res = await this.send(method, path, options, true);
|
|
160
568
|
}
|
|
161
|
-
if (!res.ok) {
|
|
569
|
+
if (!res.ok && !options.acceptStatuses?.includes(res.status)) {
|
|
162
570
|
const requestId = res.headers.get("x-request-id") ?? void 0;
|
|
163
571
|
const message = await this.extractMessage(res);
|
|
164
|
-
|
|
572
|
+
const error = errorFromResponse(
|
|
165
573
|
res.status,
|
|
166
574
|
message,
|
|
167
575
|
requestId,
|
|
168
576
|
parseRetryAfterMs(res.headers.get("retry-after"))
|
|
169
577
|
);
|
|
578
|
+
const data = await res.clone().json().catch(() => null);
|
|
579
|
+
if (typeof data?.code === "string" && /^[A-Za-z][A-Za-z0-9_]{0,99}$/.test(data.code))
|
|
580
|
+
Object.defineProperty(error, "apiCode", { value: data.code, enumerable: true });
|
|
581
|
+
if (res.status === 409 && data?.details)
|
|
582
|
+
Object.defineProperty(error, "reviewConflict", {
|
|
583
|
+
value: {
|
|
584
|
+
version: Number.isInteger(data.details.version) ? data.details.version : null,
|
|
585
|
+
submittedBy: typeof data.details.submittedBy === "string" ? data.details.submittedBy.slice(0, 200) : null,
|
|
586
|
+
submittedAt: typeof data.details.submittedAt === "string" ? data.details.submittedAt.slice(0, 40) : null
|
|
587
|
+
},
|
|
588
|
+
enumerable: true
|
|
589
|
+
});
|
|
590
|
+
throw error;
|
|
170
591
|
}
|
|
171
592
|
return res;
|
|
172
593
|
}
|
|
@@ -666,6 +1087,9 @@ function fullJitterDelay(intervalMs, maxIntervalMs, attempt, random) {
|
|
|
666
1087
|
|
|
667
1088
|
// src/sdk/client.ts
|
|
668
1089
|
var Docmana = class {
|
|
1090
|
+
authoring;
|
|
1091
|
+
reviews;
|
|
1092
|
+
executionEvents;
|
|
669
1093
|
config;
|
|
670
1094
|
http;
|
|
671
1095
|
constructor(config) {
|
|
@@ -677,6 +1101,9 @@ var Docmana = class {
|
|
|
677
1101
|
getAccessToken: this.config.getAccessToken,
|
|
678
1102
|
headers: this.config.headers
|
|
679
1103
|
});
|
|
1104
|
+
this.authoring = new FormulaAuthoring(this.http);
|
|
1105
|
+
this.reviews = new Reviews(this.http);
|
|
1106
|
+
this.executionEvents = new ExecutionEvents(this.http);
|
|
680
1107
|
}
|
|
681
1108
|
async runFlowAsync(flowId, params, options = {}) {
|
|
682
1109
|
const parts = await resolveInputs(params);
|
|
@@ -861,6 +1288,16 @@ export {
|
|
|
861
1288
|
DocmanaPermissionError,
|
|
862
1289
|
DocmanaRequestError,
|
|
863
1290
|
DocmanaServiceUnavailableError,
|
|
864
|
-
DocmanaTimeoutError
|
|
1291
|
+
DocmanaTimeoutError,
|
|
1292
|
+
EXECUTION_NODE_EVENT_TYPES,
|
|
1293
|
+
ExecutionEvents,
|
|
1294
|
+
FormulaAuthoring,
|
|
1295
|
+
REVIEW_EVENT_TYPES,
|
|
1296
|
+
ReviewEventVerificationError,
|
|
1297
|
+
Reviews,
|
|
1298
|
+
parseExecutionEventCallback,
|
|
1299
|
+
parseReviewEventCallback,
|
|
1300
|
+
verifyExecutionEventCallback,
|
|
1301
|
+
verifyReviewEventCallback
|
|
865
1302
|
};
|
|
866
1303
|
//# sourceMappingURL=index.mjs.map
|