@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
Markdown
# 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;
}
```