UNPKG

@ritas-inc/sapb1commandapi-client

Version:

A stateless TypeScript client for SAP B1 Service Layer Command API with comprehensive error handling, type safety, and batch operations

604 lines (484 loc) 13.1 kB
# API Reference Complete API documentation for the SAP B1 Command API Client. ## Table of Contents - [Client Configuration](#client-configuration) - [Authentication](#authentication) - [Plans Management](#plans-management) - [Work Orders Management](#work-orders-management) - [Batch Operations](#batch-operations) - [Error Handling](#error-handling) - [Type Definitions](#type-definitions) ## Client Configuration ### Constructor ```typescript new SAPB1CommandClient(config: ClientConfig) ``` ### ClientConfig ```typescript interface ClientConfig { baseUrl: string; // Base URL of the API endpoint timeout?: number; // Request timeout in milliseconds (default: 30000) headers?: Record<string, string>; // Additional headers to include in all requests retryConfig?: { retries?: number; // Number of retry attempts (default: 3) retryDelay?: (retryCount: number) => number; // Custom retry delay function retryCondition?: (error: any) => boolean; // Custom retry condition }; } ``` ### Example ```typescript const client = new SAPB1CommandClient({ baseUrl: 'https://api.example.com', timeout: 60000, headers: { 'X-API-Version': '1.0' }, retryConfig: { retries: 5, retryDelay: (retryCount) => retryCount * 1000, retryCondition: (error) => error.response?.status >= 500 } }); ``` ## Authentication ### Login Authenticate with SAP B1 Service Layer. ```typescript client.auth.login(credentials: AuthRequest): Promise<AuthResponse> ``` #### Parameters | Name | Type | Required | Description | |------|------|----------|-------------| | credentials | `AuthRequest` | Yes | Authentication credentials | #### AuthRequest ```typescript interface AuthRequest { dbName: string; // SAP B1 database name user: string; // SAP B1 username password: string; // SAP B1 password } ``` #### Response ```typescript type AuthResponse = { success: true; data: { userId: string; // Session ID to use in subsequent requests }; metadata?: { CompanyDB: string; // Company database name UserName: string; // Authenticated username }; } | { success: false; problem: ProblemDetails; } ``` #### Example ```typescript const response = await client.auth.login({ dbName: 'PROD_DB', user: 'manager', password: 'secure123' }); if (response.success) { const { userId } = response.data; console.log(`Logged in with session: ${userId}`); console.log(`Company: ${response.metadata?.CompanyDB}`); } ``` ## Plans Management ### Create Plan Create a new production plan. ```typescript client.plans.create( userId: string, user: number, products: PlanProduct[] ): Promise<CreatePlanResponse> ``` #### Parameters | Name | Type | Required | Description | |------|------|----------|-------------| | userId | `string` | Yes | Session ID from login | | user | `number` | Yes | SAP B1 user ID for the planner | | products | `PlanProduct[]` | Yes | Array of products to include | #### PlanProduct ```typescript interface PlanProduct { itemCode: string; // SAP B1 item code quantity: number; // Quantity (must be positive) } ``` #### Response ```typescript type CreatePlanResponse = { success: true; data: { planId: number; // Created plan ID }; } | { success: false; problem: ProblemDetails; } ``` ### Update Plan Status Update the status of an existing plan. ```typescript client.plans.updateStatus( userId: string, planId: number, status: PlanStatus ): Promise<UpdatePlanStatusResponse> ``` #### Parameters | Name | Type | Required | Description | |------|------|----------|-------------| | userId | `string` | Yes | Session ID from login | | planId | `number` | Yes | Plan ID to update | | status | `PlanStatus` | Yes | New status | #### PlanStatus ```typescript type PlanStatus = | 'Draft' | 'Generating' | 'Generated' | 'Releasing' | 'Released' | 'Completed' | 'Canceling' | 'Canceled'; ``` ### Update Plan Products Replace the products in an existing plan. ```typescript client.plans.updateProducts( userId: string, planId: number, products: PlanProduct[] ): Promise<UpdatePlanProductsResponse> ``` ### Cancel Plan Cancel an existing plan. ```typescript client.plans.cancel( userId: string, planId: number ): Promise<CancelPlanResponse> ``` ## Work Orders Management ### Create Work Order Create a single work order. ```typescript client.workOrders.create( userId: string, planId: number, workOrder: WorkOrder, origin?: WorkOrderOriginType ): Promise<CreateWorkOrderResponse> ``` #### Parameters | Name | Type | Required | Description | |------|------|----------|-------------| | userId | `string` | Yes | Session ID from login | | planId | `number` | Yes | Associated plan ID | | workOrder | `WorkOrder` | Yes | Work order details | | origin | `WorkOrderOriginType` | No | Origin type (default: 'manual') | #### WorkOrder ```typescript interface WorkOrder { itemCode: string; // SAP B1 item code quantity: number; // Production quantity injections?: number; // Number of injections (for injection molding) } ``` #### WorkOrderOriginType ```typescript type WorkOrderOriginType = 'manual' | 'workorder'; ``` #### Response ```typescript type CreateWorkOrderResponse = { success: true; data: { absoluteEntry: number; // Work order absolute entry documentEntry: number; // Work order document entry createDate: string; // Creation date (ISO format) }; } | { success: false; problem: ProblemDetails; } ``` ### Release Work Order Release a work order for production. ```typescript client.workOrders.release( userId: string, workOrderId: number ): Promise<ReleaseWorkOrderResponse> ``` ### Cancel Work Order Cancel an existing work order. ```typescript client.workOrders.cancel( userId: string, workOrderId: number ): Promise<CancelWorkOrderResponse> ``` ## Batch Operations ### Batch Create Work Orders Create multiple work orders in a single request. ```typescript client.workOrders.batch.create( userId: string, workOrders: Array<{ planId: number; workOrder: WorkOrder; origin?: WorkOrderOriginType; }> ): Promise<CreateWorkOrderBatchResponse> ``` #### Example ```typescript const response = await client.workOrders.batch.create(userId, [ { planId: 1, workOrder: { itemCode: 'PROD001', quantity: 100, injections: 10 }, origin: 'manual' }, { planId: 1, workOrder: { itemCode: 'PROD002', quantity: 50 } } ]); if (response.success) { console.log(`Created ${response.data.length} work orders`); } ``` ### Batch Release Work Orders Release multiple work orders. ```typescript client.workOrders.batch.release( userId: string, workOrderIds: number[] ): Promise<ReleaseWorkOrderBatchResponse> ``` ### Batch Cancel Work Orders Cancel multiple work orders. ```typescript client.workOrders.batch.cancel( userId: string, workOrderIds: number[] ): Promise<CancelWorkOrderBatchResponse> ``` ## Error Handling ### ProblemDetails All error responses follow the RFC 7807 Problem Details format: ```typescript interface ProblemDetails { status: number; // HTTP status code type: string; // Error type identifier title: string; // Error title detail: string; // Detailed error message instance: string; // Request path context: { request: string; // Request method and path responseText: string; // Raw response text }; issues: string[]; // List of specific issues } ``` ### Error Classes The client throws specific error types that can be caught and handled: ```typescript import { SAPB1APIError, // General API errors AuthError, // Authentication failures NetworkError, // Network/connection issues ValidationError // Request validation errors } from '@ritas-inc/sapb1commandapi-client'; ``` ### Error Handling Example ```typescript try { const response = await client.plans.create(userId, user, products); if (!response.success) { // Handle API error response console.error(`API Error: ${response.problem.detail}`); console.error(`Issues: ${response.problem.issues.join(', ')}`); switch (response.problem.status) { case 400: console.error('Bad request - check your input'); break; case 401: console.error('Unauthorized - session may have expired'); break; case 404: console.error('Resource not found'); break; default: console.error('Unexpected error'); } } } catch (error) { // Handle thrown errors if (error instanceof ValidationError) { console.error('Validation failed:', error.issues); } else if (error instanceof NetworkError) { console.error('Network error:', error.message); if (error.code === 'ECONNREFUSED') { console.error('Cannot connect to API server'); } } } ``` ## Type Definitions ### Response Types All API methods return a discriminated union type: ```typescript type APIResponse<T> = SuccessResponse<T> | ErrorResponse; interface SuccessResponse<T> { success: true; data: T; metadata?: any; } interface ErrorResponse { success: false; problem: ProblemDetails; } ``` ### Using Type Guards ```typescript import { isErrorResponse } from '@ritas-inc/sapb1commandapi-client'; const response = await client.plans.create(userId, user, products); if (isErrorResponse(response)) { // TypeScript knows this is an ErrorResponse handleError(response.problem); } else { // TypeScript knows this is a SuccessResponse console.log(`Plan created: ${response.data.planId}`); } ``` ### Exported Types The client exports all necessary types for TypeScript users: ```typescript // Request types export type AuthRequest export type CreatePlanRequest export type UpdatePlanStatusRequest export type UpdatePlanProductsRequest export type CreateWorkOrderItem export type ReleaseWorkOrderItemRequest export type CancelWorkOrderItem // Response types export type AuthResponse export type CreatePlanResponse export type UpdatePlanStatusResponse export type UpdatePlanProductsResponse export type CancelPlanResponse export type CreateWorkOrderResponse export type ReleaseWorkOrderResponse export type CancelWorkOrderResponse export type CreateWorkOrderBatchResponse export type ReleaseWorkOrderBatchResponse export type CancelWorkOrderBatchResponse // Entity types export type PlanProduct export type PlanProductsArray export type WorkOrder export type ClientConfig // Enum types export type PlanStatus export type WorkOrderOriginType ``` ## Best Practices ### Session Management ```typescript class SessionManager { private userId?: string; private lastLogin?: Date; async ensureAuthenticated(client: SAPB1CommandClient): Promise<string> { // Re-authenticate if session is older than 25 minutes if (!this.userId || !this.lastLogin || Date.now() - this.lastLogin.getTime() > 25 * 60 * 1000) { const response = await client.auth.login({ dbName: process.env.SAP_DB!, user: process.env.SAP_USER!, password: process.env.SAP_PASSWORD! }); if (!response.success) { throw new Error(`Login failed: ${response.problem.detail}`); } this.userId = response.data.userId; this.lastLogin = new Date(); } return this.userId; } } ``` ### Retry Strategy ```typescript const client = new SAPB1CommandClient({ baseUrl: 'https://api.example.com', retryConfig: { retries: 5, retryDelay: (retryCount) => { // Exponential backoff with jitter const delay = Math.min(1000 * Math.pow(2, retryCount), 30000); const jitter = delay * 0.1 * Math.random(); return delay + jitter; }, retryCondition: (error) => { // Retry on network errors and 5xx status codes if (!error.response) return true; return error.response.status >= 500; } } }); ``` ### Error Recovery ```typescript async function createWorkOrdersWithRecovery( client: SAPB1CommandClient, userId: string, workOrders: Array<{ planId: number; workOrder: WorkOrder }> ) { const results = { successful: [] as number[], failed: [] as Array<{ workOrder: any; error: string }> }; // Try batch operation first const batchResponse = await client.workOrders.batch.create(userId, workOrders); if (batchResponse.success) { // All succeeded results.successful = batchResponse.data.map(d => d.absoluteEntry); } else { // Batch failed - try individual creates for (const wo of workOrders) { const response = await client.workOrders.create( userId, wo.planId, wo.workOrder ); if (response.success) { results.successful.push(response.data.absoluteEntry); } else { results.failed.push({ workOrder: wo, error: response.problem.detail }); } } } return results; } ```