@docmana/sdk 0.9.1 → 0.11.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/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.10.0
4
+ - Add an optional `organization` to flow selection, emitted as a
5
+ `?organization=<org>` query param on the request to
6
+ `docmana-consumer-edge-api`. Purely additive — existing calls are unchanged.
7
+ - `listFlows({ organization })`, `getFlowMetadata(flowId, { organization })`,
8
+ and `getFlowDefinition(flowId, { organization })` accept the option.
9
+ - `RunFlowParams` (and therefore `runFlow` / `runFlowAsync`) gains
10
+ `organization`, threaded onto the `execute-async` request URL.
11
+ - Expose `organization` on `FlowListItem`: when the consumer-edge tags a flow
12
+ with its organization, `listFlows()` now carries it through on each item.
13
+
3
14
  ## 0.8.1
4
15
  - Rename the multipart wire fields sent to `docmana-consumer-edge-api` from
5
16
  `json_context` / `callback_url` to `jsonContext` / `callbackUrl`, matching the
package/README.md CHANGED
@@ -121,7 +121,7 @@ use `RunFlowParams` for request data:
121
121
  `GET /v1/executions/:executionResultId/result`.
122
122
  - `runFlow(flowId, params, options?)` starts async execution, polls status, fetches the
123
123
  result, respects `X-Poll-After` and `429 Retry-After` while polling, and throws
124
- `DocmanaExecutionError` if the result status is `Failed`.
124
+ `DocmanaExecutionError` if the result status is `FAILED`.
125
125
 
126
126
  Consumer is the polling authority. When `GET /status` returns `X-Poll-After`,
127
127
  the SDK waits that many milliseconds before the next status call. If the header
@@ -159,8 +159,8 @@ const { executionResultId } = await docmana.runFlowAsync("<flow-id>", {
159
159
  files: ["./contract.pdf"],
160
160
  });
161
161
 
162
- let status = "Pending";
163
- while (status !== "Completed" && status !== "Failed") {
162
+ let status = "PENDING";
163
+ while (status !== "COMPLETED" && status !== "FAILED") {
164
164
  await new Promise((r) => setTimeout(r, 2000));
165
165
  ({ status } = await docmana.getStatus(executionResultId));
166
166
  }
@@ -264,7 +264,7 @@ optional `.requestId` when available.
264
264
  | `DocmanaAuthError` | `401` rejected or expired Bearer token. |
265
265
  | `DocmanaPermissionError` | `403` missing permission. |
266
266
  | `DocmanaNotFoundError` | `404` flow or execution not found. |
267
- | `DocmanaExecutionError` | The flow finished with status `"Failed"`. Carries `.errors` and `.result`. |
267
+ | `DocmanaExecutionError` | The flow finished with status `"FAILED"`. Carries `.errors` and `.result`. |
268
268
  | `DocmanaTimeoutError` | Polling exceeded `timeoutMs`. |
269
269
  | `DocmanaAbortError` | The provided `AbortSignal` fired. |
270
270
 
@@ -1,3 +1,3 @@
1
1
  import type { HttpClient } from "../http/http-client.js";
2
2
  import type { FlowDefinition } from "../types.js";
3
- export declare function getFlowDefinition(http: HttpClient, flowId: string): Promise<FlowDefinition>;
3
+ export declare function getFlowDefinition(http: HttpClient, flowId: string, organization?: string): Promise<FlowDefinition>;
@@ -1,3 +1,3 @@
1
1
  import type { HttpClient } from "../http/http-client.js";
2
2
  import type { FlowMetadata } from "../types.js";
3
- export declare function getFlowMetadata(http: HttpClient, flowId: string): Promise<FlowMetadata>;
3
+ export declare function getFlowMetadata(http: HttpClient, flowId: string, organization?: string): Promise<FlowMetadata>;
@@ -1,3 +1,3 @@
1
1
  import type { HttpClient } from "../http/http-client.js";
2
2
  import type { FlowListItem } from "../types.js";
3
- export declare function listFlows(http: HttpClient): Promise<FlowListItem[]>;
3
+ export declare function listFlows(http: HttpClient, organization?: string): Promise<FlowListItem[]>;
@@ -1,6 +1,6 @@
1
1
  import type { ResolvedPart } from "../files/resolve-input.js";
2
2
  import type { HttpClient } from "../http/http-client.js";
3
- export declare function runFlow(http: HttpClient, flowId: string, parts: ResolvedPart[], signal?: AbortSignal, useDraftVersion?: boolean, context?: Record<string, unknown>, callbackUrl?: string, language?: string): Promise<{
3
+ export declare function runFlow(http: HttpClient, flowId: string, parts: ResolvedPart[], signal?: AbortSignal, useDraftVersion?: boolean, context?: Record<string, unknown>, callbackUrl?: string, language?: string, organization?: string): Promise<{
4
4
  executionResultId: string;
5
5
  fileIds: string[];
6
6
  }>;
package/dist/cli.mjs CHANGED
@@ -265,7 +265,7 @@ async function resolveInputs(input) {
265
265
  }
266
266
 
267
267
  // src/sdk/api/run-flow.ts
268
- async function runFlow(http, flowId, parts, signal, useDraftVersion = false, context, callbackUrl, language) {
268
+ async function runFlow(http, flowId, parts, signal, useDraftVersion = false, context, callbackUrl, language, organization) {
269
269
  const form = new FormData();
270
270
  for (const part of parts) {
271
271
  form.append("files", new File([part.data], part.filename, { type: part.contentType }));
@@ -274,20 +274,37 @@ async function runFlow(http, flowId, parts, signal, useDraftVersion = false, con
274
274
  if (callbackUrl !== void 0) form.append("callbackUrl", callbackUrl);
275
275
  if (language !== void 0) form.append("language", language);
276
276
  if (useDraftVersion) form.append("useDraftVersion", "true");
277
+ const path = `/flows/${flowId}/execute-async`;
277
278
  return http.requestJson(
278
279
  "POST",
279
- `/flows/${flowId}/execute-async`,
280
+ organization ? `${path}?organization=${encodeURIComponent(organization)}` : path,
280
281
  { body: form, signal }
281
282
  );
282
283
  }
283
284
 
285
+ // src/sdk/status.ts
286
+ function normalizeStatus(status, fallback = "UNKNOWN") {
287
+ if (typeof status !== "string") return fallback;
288
+ const trimmed = status.trim();
289
+ if (!trimmed) return fallback;
290
+ return trimmed.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[\s-]+/g, "_").toUpperCase();
291
+ }
292
+ function isFailedStatus(status) {
293
+ return normalizeStatus(status) === "FAILED";
294
+ }
295
+ function isTerminalStatus(status) {
296
+ const normalized = normalizeStatus(status);
297
+ return normalized === "COMPLETED" || normalized === "FAILED";
298
+ }
299
+
284
300
  // src/sdk/api/execution-status.ts
285
301
  async function getStatus(http, executionResultId, signal) {
286
302
  const res = await http.requestRaw("GET", `/executions/${executionResultId}/status`, { signal });
287
303
  const text = await res.text();
288
304
  const body = text ? JSON.parse(text) : { status: "" };
305
+ const normalizedBody = { ...body, status: normalizeStatus(body.status) };
289
306
  const pollAfterMs = parsePositiveInt(res.headers.get("x-poll-after"));
290
- return pollAfterMs === void 0 ? body : { ...body, pollAfterMs };
307
+ return pollAfterMs === void 0 ? normalizedBody : { ...normalizedBody, pollAfterMs };
291
308
  }
292
309
  function parsePositiveInt(value) {
293
310
  if (!value) return void 0;
@@ -304,17 +321,22 @@ async function getResult(http, executionResultId, signal, language) {
304
321
  }
305
322
 
306
323
  // src/sdk/api/list-flows.ts
307
- async function listFlows(http) {
308
- const flows = await http.requestJson("GET", "/flows");
324
+ async function listFlows(http, organization) {
325
+ const path = organization ? `/flows?organization=${encodeURIComponent(organization)}` : "/flows";
326
+ const flows = await http.requestJson("GET", path);
309
327
  return Array.isArray(flows) ? flows.map(toFlowListItem) : [];
310
328
  }
311
329
  function toFlowListItem(flow) {
312
330
  const value = flow && typeof flow === "object" ? flow : {};
313
- return {
331
+ const item = {
314
332
  id: toStringValue(value.id),
315
333
  name: toStringValue(value.name),
316
334
  state: toStateValue(value.state)
317
335
  };
336
+ if (typeof value.organization === "string") {
337
+ item.organization = value.organization;
338
+ }
339
+ return item;
318
340
  }
319
341
  function toStringValue(value) {
320
342
  return typeof value === "string" ? value : "";
@@ -346,13 +368,21 @@ function toStringValue2(value) {
346
368
  }
347
369
 
348
370
  // src/sdk/api/flow-metadata.ts
349
- async function getFlowMetadata(http, flowId) {
350
- return http.requestJson("GET", `/flows/${encodeURIComponent(flowId)}/metadata`);
371
+ async function getFlowMetadata(http, flowId, organization) {
372
+ const path = `/flows/${encodeURIComponent(flowId)}/metadata`;
373
+ return http.requestJson(
374
+ "GET",
375
+ organization ? `${path}?organization=${encodeURIComponent(organization)}` : path
376
+ );
351
377
  }
352
378
 
353
379
  // src/sdk/api/flow-definition.ts
354
- async function getFlowDefinition(http, flowId) {
355
- return http.requestJson("GET", `/flows/${encodeURIComponent(flowId)}/definition`);
380
+ async function getFlowDefinition(http, flowId, organization) {
381
+ const path = `/flows/${encodeURIComponent(flowId)}/definition`;
382
+ return http.requestJson(
383
+ "GET",
384
+ organization ? `${path}?organization=${encodeURIComponent(organization)}` : path
385
+ );
356
386
  }
357
387
 
358
388
  // src/sdk/api/organization-documents.ts
@@ -416,7 +446,6 @@ function toNumberValue(value) {
416
446
  }
417
447
 
418
448
  // src/sdk/polling/poll.ts
419
- var TERMINAL = /* @__PURE__ */ new Set(["Completed", "Failed"]);
420
449
  var defaultSleep = (ms) => new Promise((r) => setTimeout(r, ms));
421
450
  async function pollUntilTerminal(opts) {
422
451
  const sleep = opts.sleep ?? defaultSleep;
@@ -437,8 +466,8 @@ async function pollUntilTerminal(opts) {
437
466
  await sleep(err.retryAfterMs ?? opts.intervalMs);
438
467
  continue;
439
468
  }
440
- const { status } = result;
441
- if (TERMINAL.has(status)) return status;
469
+ const status = normalizeStatus(result.status);
470
+ if (isTerminalStatus(status)) return status;
442
471
  if (elapsed() >= opts.timeoutMs) {
443
472
  throw new DocmanaTimeoutError(`Execution did not finish within ${opts.timeoutMs}ms`);
444
473
  }
@@ -484,7 +513,8 @@ var Docmana = class {
484
513
  params.useDraftVersion ?? false,
485
514
  params.context,
486
515
  params.callbackUrl,
487
- params.language
516
+ params.language,
517
+ params.organization
488
518
  );
489
519
  }
490
520
  async getStatus(executionResultId, signal) {
@@ -532,7 +562,7 @@ var Docmana = class {
532
562
  signal: options.signal
533
563
  });
534
564
  const result = await this.getResult(executionResultId, options.signal, params.language);
535
- if (result.status === "Failed") {
565
+ if (isFailedStatus(result.status)) {
536
566
  throw new DocmanaExecutionError(
537
567
  `Flow ${flowId} execution failed`,
538
568
  result.errors ?? [],
@@ -541,17 +571,17 @@ var Docmana = class {
541
571
  }
542
572
  return result;
543
573
  }
544
- async listFlows() {
545
- return listFlows(this.http);
574
+ async listFlows(options = {}) {
575
+ return listFlows(this.http, options.organization);
546
576
  }
547
577
  async listOrganizations() {
548
578
  return listOrganizations(this.http);
549
579
  }
550
- async getFlowMetadata(flowId) {
551
- return getFlowMetadata(this.http, flowId);
580
+ async getFlowMetadata(flowId, options = {}) {
581
+ return getFlowMetadata(this.http, flowId, options.organization);
552
582
  }
553
- async getFlowDefinition(flowId) {
554
- return getFlowDefinition(this.http, flowId);
583
+ async getFlowDefinition(flowId, options = {}) {
584
+ return getFlowDefinition(this.http, flowId, options.organization);
555
585
  }
556
586
  async listOrganizationDocuments(options = {}) {
557
587
  return listOrganizationDocuments(this.http, options);
@@ -563,7 +593,7 @@ var Docmana = class {
563
593
  return downloadOrganizationDocuments(this.http, paths);
564
594
  }
565
595
  isTerminalStatus(status) {
566
- return status === "Completed" || status === "Failed";
596
+ return isTerminalStatus(status);
567
597
  }
568
598
  };
569
599
 
@@ -671,10 +701,10 @@ function formatHumanError(err) {
671
701
  if (docResult.extractions) nodes.push(...Object.values(docResult.extractions));
672
702
  if (docResult.validations) nodes.push(...Object.values(docResult.validations));
673
703
  const hasNodeFailures = nodes.some(
674
- (n) => n.status === "Failed" || n.errors && n.errors.length > 0
704
+ (n) => isFailedStatus(n.status) || n.errors && n.errors.length > 0
675
705
  );
676
706
  lines.push(` - Document: ${docName} (Status: ${status})`);
677
- if (docResult.status !== "Failed" && !hasNodeFailures) continue;
707
+ if (!isFailedStatus(docResult.status) && !hasNodeFailures) continue;
678
708
  if (docResult.classifications) {
679
709
  for (const [nodeName, node] of Object.entries(docResult.classifications)) {
680
710
  if (node.errors && node.errors.length > 0) {
@@ -691,7 +721,7 @@ function formatHumanError(err) {
691
721
  }
692
722
  if (docResult.extractions) {
693
723
  for (const [nodeName, node] of Object.entries(docResult.extractions)) {
694
- if (node.status === "Failed" || node.errors && node.errors.length > 0) {
724
+ if (isFailedStatus(node.status) || node.errors && node.errors.length > 0) {
695
725
  lines.push(` Extraction: ${nodeName} (Status: ${node.status})`);
696
726
  if (node.errors) {
697
727
  for (const nodeErr of node.errors) lines.push(` - ${nodeErr}`);
@@ -701,7 +731,7 @@ function formatHumanError(err) {
701
731
  }
702
732
  if (docResult.validations) {
703
733
  for (const [nodeName, node] of Object.entries(docResult.validations)) {
704
- if (node.status === "Failed" || node.errors && node.errors.length > 0) {
734
+ if (isFailedStatus(node.status) || node.errors && node.errors.length > 0) {
705
735
  lines.push(` Validation: ${nodeName} (Status: ${node.status})`);
706
736
  if (node.errors) {
707
737
  for (const nodeErr of node.errors) lines.push(` - ${nodeErr}`);