Add convenience helpers and improve documentation

- Add isInProduction() helper for checking status 3 or 4
- Add getErrorSummary() helper for extracting error messages
- Add fetchAllPages() pagination helper for auto-pagination
- Add comprehensive JSDoc to ListResponse interface
- Create ADR-001 documenting decision not to add listAll() method

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-16 22:30:36 +01:00
parent 6b2b26f3ea
commit 397cd10a09
4 changed files with 241 additions and 2 deletions

View File

@@ -5,7 +5,7 @@
* They provide convenient predicates and utilities for common operations.
*/
import { DocumentStatus, type Document, type Sending, type ValidationMessage } from './types.js';
import { DocumentStatus, type Document, type ListResponse, type Sending, type ValidationMessage } from './types.js';
/**
* Helper to get status code from document or sending
@@ -71,6 +71,18 @@ export function isCanceled(doc: Document | Sending): boolean {
return getStatusCode(doc) === DocumentStatus.CANCELED;
}
/**
* Check if a document is in production (status 3 or 4).
* This includes documents in the production queue and those currently printing.
*/
export function isInProduction(doc: Document | Sending): boolean {
const status = getStatusCode(doc);
return (
status === DocumentStatus.PRODUCTION_QUEUE ||
status === DocumentStatus.PRINTING
);
}
/**
* Check if a document is in a terminal state (sent, canceled, or erroneous).
*/
@@ -140,6 +152,30 @@ export function hasWarnings(doc: Document): boolean {
return getWarnings(doc).length > 0;
}
/**
* Get a summary of all error messages from a document.
* Returns undefined if the document has no errors.
*
* @param doc - The document to extract error messages from
* @param separator - Separator between messages (default: '; ')
* @returns Concatenated error messages or undefined if no errors
*
* @example
* ```typescript
* const doc = await client.documents.get(id);
* if (isErroneous(doc)) {
* console.error('Upload failed:', getErrorSummary(doc));
* }
* ```
*/
export function getErrorSummary(doc: Document, separator: string = '; '): string | undefined {
const errors = getErrors(doc);
if (errors.length === 0) {
return undefined;
}
return errors.map((e) => e.message).join(separator);
}
// ============================================================================
// Status Description
// ============================================================================
@@ -272,3 +308,66 @@ export async function waitForShippable(
options
);
}
// ============================================================================
// Pagination Utilities
// ============================================================================
/**
* Options for fetchAllPages helper.
*/
export interface FetchAllPagesOptions {
/** Number of items per page (default: 100) */
pageSize?: number;
/** Abort signal for cancellation */
signal?: AbortSignal;
}
/**
* Fetch all pages from a paginated list endpoint.
* This is an opt-in convenience helper for retrieving complete result sets.
*
* @param fetchPage - Function that fetches a single page given limit and offset
* @param options - Pagination options
* @returns Array of all items from all pages
*
* @example
* ```typescript
* // Fetch all shippable documents
* const allDocs = await fetchAllPages(
* (limit, offset) => client.documents.list({ limit, offset })
* );
*
* // Fetch all erroneous documents with custom page size
* const allErrors = await fetchAllPages(
* (limit, offset) => client.documents.listErrors({ limit, offset }),
* { pageSize: 50 }
* );
* ```
*/
export async function fetchAllPages<T>(
fetchPage: (limit: number, offset: number) => Promise<ListResponse<T>>,
options: FetchAllPagesOptions = {}
): Promise<T[]> {
const pageSize = options.pageSize ?? 100;
const allItems: T[] = [];
let offset = 0;
while (true) {
if (options.signal?.aborted) {
throw new Error('Fetch aborted');
}
const response = await fetchPage(pageSize, offset);
allItems.push(...response.items);
// Check if we've fetched all items
if (response.items.length < pageSize || allItems.length >= response.total) {
break;
}
offset += pageSize;
}
return allItems;
}