generated from coulomb/repo-seed
Add Binect SDK implementation, Explorer, and test suite
SDK (@binect/js): - BinectClient with domain sub-clients (documents, sendings, accounts, attachments, invoices) - HTTP Basic Auth, native fetch only (no runtime dependencies) - TypeScript types matching Binect API vocabulary - Status predicates and polling helpers in helpers.ts - Structured error handling (BinectApiError, BinectAuthError) Explorer: - Standalone browser-based API explorer (explorer/index.html) - Interactive testing without code Tests: - Unit tests for client, types, errors, helpers, http - E2E tests for upload/delete and send/cancel workflows Also includes: - Architecture Decision Records (ADRs) - Example DIN 5008 letter PDFs for testing - API specification research notes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
446
src/types.ts
Normal file
446
src/types.ts
Normal file
@@ -0,0 +1,446 @@
|
||||
/**
|
||||
* Binect API Type Definitions
|
||||
* Based on API specification v0.9.9
|
||||
*/
|
||||
|
||||
// ============================================================================
|
||||
// Enums
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Document status codes as defined by the Binect API
|
||||
*/
|
||||
export enum DocumentStatus {
|
||||
/** Document is being prepared/validated */
|
||||
IN_PREPARATION = 1,
|
||||
/** Document is ready to be shipped */
|
||||
SHIPPABLE = 2,
|
||||
/** Document is in production queue */
|
||||
PRODUCTION_QUEUE = 3,
|
||||
/** Document is being printed */
|
||||
PRINTING = 4,
|
||||
/** Document has been sent */
|
||||
SENT = 5,
|
||||
/** Document was canceled */
|
||||
CANCELED = 6,
|
||||
/** Document has errors */
|
||||
ERRONEOUS = 7,
|
||||
}
|
||||
|
||||
/**
|
||||
* Envelope type options
|
||||
*/
|
||||
export enum EnvelopeType {
|
||||
DINLANG = 'DINLANG',
|
||||
C4 = 'C4',
|
||||
}
|
||||
|
||||
/**
|
||||
* Franking type options
|
||||
*/
|
||||
export enum FrankingType {
|
||||
UNSPECIFIED = 'UNSPECIFIED',
|
||||
STANDARD_FRANKING = 'STANDARD_FRANKING',
|
||||
DV_FRANKING = 'DV_FRANKING',
|
||||
}
|
||||
|
||||
/**
|
||||
* Production country options
|
||||
*/
|
||||
export enum ProductionCountry {
|
||||
UNSPECIFIED = 'UNSPECIFIED',
|
||||
DE = 'DE',
|
||||
AT = 'AT',
|
||||
}
|
||||
|
||||
/**
|
||||
* Response format options for document upload
|
||||
*/
|
||||
export enum ResponseFormat {
|
||||
/** Complete validation results (default) */
|
||||
FULL = 'FULL',
|
||||
/** Minimal response; validation runs asynchronously */
|
||||
SHORT = 'SHORT',
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Request Types
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Options for uploading a document
|
||||
*/
|
||||
export interface DocumentUploadOptions {
|
||||
/** Base64-encoded PDF content */
|
||||
content: string;
|
||||
/** Filename for the document (optional) */
|
||||
filename?: string;
|
||||
/** Whether to print in color (default: false) */
|
||||
color?: boolean;
|
||||
/** Whether to print simplex/single-sided (default: false, meaning duplex) */
|
||||
simplex?: boolean;
|
||||
/** Envelope type */
|
||||
envelope?: EnvelopeType;
|
||||
/** Franking type */
|
||||
franking?: FrankingType;
|
||||
/** Production country */
|
||||
productionCountry?: ProductionCountry;
|
||||
/** Response format */
|
||||
responseFormat?: ResponseFormat;
|
||||
/** Number of pages per letter for serial letter splitting */
|
||||
pagesPerLetter?: number;
|
||||
/** Token for serial letter splitting */
|
||||
splitToken?: string;
|
||||
/** Custom attributes as key-value pairs */
|
||||
attributes?: DocumentAttribute[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal API request body for document upload
|
||||
* @internal
|
||||
*/
|
||||
export interface DocumentUploadRequestBody {
|
||||
content: {
|
||||
filename?: string;
|
||||
content: string;
|
||||
};
|
||||
options?: {
|
||||
simplex?: boolean;
|
||||
color?: boolean;
|
||||
envelope?: EnvelopeType;
|
||||
franking?: FrankingType;
|
||||
productionCountry?: ProductionCountry;
|
||||
};
|
||||
attributes?: DocumentAttribute[];
|
||||
splitParams?: {
|
||||
splitToken?: string;
|
||||
splitAfterNumberOfPages?: number;
|
||||
};
|
||||
responseFormat?: ResponseFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for uploading and immediately sending a document
|
||||
*/
|
||||
export interface DocumentUploadAndSendOptions extends DocumentUploadOptions {
|
||||
/** Send immediately after upload */
|
||||
send?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transformation parameters for document scaling/offset
|
||||
*/
|
||||
export interface DocumentTransformation {
|
||||
/** Horizontal offset in mm */
|
||||
offsetX?: number;
|
||||
/** Vertical offset in mm */
|
||||
offsetY?: number;
|
||||
/** Scale factor (1.0 = 100%) */
|
||||
scale?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cover page parameters
|
||||
*/
|
||||
export interface CoverPageOptions {
|
||||
/** Base64-encoded PDF content for cover page */
|
||||
content: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Key-value attribute
|
||||
*/
|
||||
export interface DocumentAttribute {
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pagination options for list endpoints
|
||||
*/
|
||||
export interface PaginationOptions {
|
||||
/** Maximum number of results to return */
|
||||
limit?: number;
|
||||
/** Number of results to skip */
|
||||
offset?: number;
|
||||
/** Index signature for compatibility with query parameters */
|
||||
[key: string]: number | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for announcing documents for sending
|
||||
*/
|
||||
export interface SendingAnnounceOptions {
|
||||
/** Document IDs to announce */
|
||||
documentIds: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for canceling sendings
|
||||
*/
|
||||
export interface SendingCancelOptions {
|
||||
/** Document IDs to cancel */
|
||||
documentIds: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Personal data update options
|
||||
*/
|
||||
export interface PersonalDataUpdate {
|
||||
company?: string;
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
street?: string;
|
||||
houseNumber?: string;
|
||||
zipCode?: string;
|
||||
city?: string;
|
||||
country?: string;
|
||||
phone?: string;
|
||||
email?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Account print options
|
||||
*/
|
||||
export interface AccountPrintOptions {
|
||||
color?: boolean;
|
||||
duplex?: boolean;
|
||||
envelope?: EnvelopeType;
|
||||
franking?: FrankingType;
|
||||
productionCountry?: ProductionCountry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attachment upload options
|
||||
*/
|
||||
export interface AttachmentUploadOptions {
|
||||
/** Base64-encoded PDF content */
|
||||
content: string;
|
||||
/** Name for the attachment */
|
||||
name?: string;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Response Types
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Validation message from document processing
|
||||
*/
|
||||
export interface ValidationMessage {
|
||||
type: 'INFO' | 'WARNING' | 'ERROR';
|
||||
code: string;
|
||||
message: string;
|
||||
page?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address extracted from document
|
||||
*/
|
||||
export interface ExtractedAddress {
|
||||
name?: string;
|
||||
company?: string;
|
||||
street?: string;
|
||||
houseNumber?: string;
|
||||
zipCode?: string;
|
||||
city?: string;
|
||||
country?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Price information from API
|
||||
*/
|
||||
export interface PriceInfo {
|
||||
priceBeforeTax: number;
|
||||
priceAfterTax: number;
|
||||
unit: 'EUROCENT' | string;
|
||||
taxInPercent: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Document status from API
|
||||
*/
|
||||
export interface DocumentStatusInfo {
|
||||
code: DocumentStatus;
|
||||
text: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Letter data from API response
|
||||
*/
|
||||
export interface LetterData {
|
||||
recipientAddress?: string;
|
||||
price?: PriceInfo;
|
||||
international?: boolean;
|
||||
options?: {
|
||||
simplex?: boolean;
|
||||
color?: boolean;
|
||||
franking?: FrankingType;
|
||||
productionCountry?: ProductionCountry;
|
||||
envelope?: EnvelopeType;
|
||||
};
|
||||
attributes?: DocumentAttribute[];
|
||||
attachments?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Letter from API response
|
||||
*/
|
||||
export interface Letter {
|
||||
letterType?: string;
|
||||
letterData?: LetterData;
|
||||
errors?: ValidationMessage[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Document response from API
|
||||
*/
|
||||
export interface Document {
|
||||
/** Document ID (numeric) */
|
||||
id: number;
|
||||
/** Filename of uploaded document */
|
||||
filename?: string;
|
||||
/** Number of pages in document */
|
||||
numberOfPages: number;
|
||||
/** Document status */
|
||||
status: DocumentStatusInfo;
|
||||
/** Type of document */
|
||||
documentType?: 'LETTER' | 'SERIALLETTER' | string;
|
||||
/** Letter details (for single letters) */
|
||||
letter?: Letter;
|
||||
/** Array of letters (for serial letters) */
|
||||
letters?: Letter[];
|
||||
}
|
||||
|
||||
/**
|
||||
* List response wrapper
|
||||
*/
|
||||
export interface ListResponse<T> {
|
||||
items: T[];
|
||||
total: number;
|
||||
limit: number;
|
||||
offset: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attachment response from API
|
||||
*/
|
||||
export interface Attachment {
|
||||
attachmentId: string;
|
||||
name: string;
|
||||
pageCount: number;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sending/shipment response from API
|
||||
*/
|
||||
export interface Sending {
|
||||
documentId: string;
|
||||
status: DocumentStatus;
|
||||
price?: number;
|
||||
trackingId?: string;
|
||||
shippedAt?: string;
|
||||
deliveredAt?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Account balance/credit information
|
||||
*/
|
||||
export interface AccountInfo {
|
||||
credit: number;
|
||||
currency: string;
|
||||
debitornumber: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Personal data response
|
||||
*/
|
||||
export interface PersonalData {
|
||||
company?: string;
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
street?: string;
|
||||
houseNumber?: string;
|
||||
zipCode?: string;
|
||||
city?: string;
|
||||
country?: string;
|
||||
phone?: string;
|
||||
email?: string;
|
||||
debitornumber: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Coworker information
|
||||
*/
|
||||
export interface Coworker {
|
||||
debitornumber: string;
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
email?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Journal/transaction entry
|
||||
*/
|
||||
export interface JournalEntry {
|
||||
date: string;
|
||||
description: string;
|
||||
amount: number;
|
||||
balance: number;
|
||||
documentId?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoice summary
|
||||
*/
|
||||
export interface Invoice {
|
||||
invoiceNumber: string;
|
||||
date: string;
|
||||
amount: number;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoice detail with transactions
|
||||
*/
|
||||
export interface InvoiceDetail extends Invoice {
|
||||
entries: JournalEntry[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch status check response
|
||||
*/
|
||||
export interface BatchStatusResponse {
|
||||
statuses: Record<string, DocumentStatus>;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Error Types
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* API error response structure
|
||||
*/
|
||||
export interface ApiErrorResponse {
|
||||
error?: string;
|
||||
message?: string;
|
||||
details?: string[];
|
||||
validationErrors?: ValidationMessage[];
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Client Configuration
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Configuration options for BinectClient
|
||||
*/
|
||||
export interface BinectClientConfig {
|
||||
/** Binect username (email) */
|
||||
username: string;
|
||||
/** Binect password */
|
||||
password: string;
|
||||
/** Base URL override (default: https://app.binect.de/binectapi/v1) */
|
||||
baseUrl?: string;
|
||||
}
|
||||
Reference in New Issue
Block a user