@ritas-inc/hanaqueryapi-client
Version:
TypeScript client for HANA Query API with full type safety and error handling
786 lines (693 loc) • 21.6 kB
text/typescript
/**
* HANA Query API Client - Type Definitions
*
* Complete TypeScript interfaces matching the current API response structures.
* These types are based on the actual API implementation and ensure type safety.
*/
// ============================================================================
// Base Response Types
// ============================================================================
/**
* Base API response structure
*/
export interface BaseAPIResponse {
success: boolean;
}
/**
* Successful API response
*/
export interface SuccessResponse<TData = any, TMetadata = any> extends BaseAPIResponse {
success: true;
data: TData;
metadata?: TMetadata;
}
/**
* Error API response
*/
export interface ErrorResponse extends BaseAPIResponse {
success: false;
problem: ProblemDetails;
}
/**
* Generic API response (success or error)
*/
export type APIResponse<TData = any, TMetadata = any> =
| SuccessResponse<TData, TMetadata>
| ErrorResponse;
/**
* Problem details for error responses (RFC 7807)
*/
export interface ProblemDetails {
status: number;
type: string;
title: string;
detail: string;
instance: string;
context: {
request: string;
responseText: string;
};
issues: string[];
}
// ============================================================================
// Request Parameter Types
// ============================================================================
/**
* Date range parameters for sales endpoint
*/
export interface SalesParams {
from: string; // YYYY-MM-DD format (required)
to: string; // YYYY-MM-DD format (required)
}
/**
* Generic request options
*/
export interface RequestOptions {
timeout?: number;
retries?: number;
signal?: AbortSignal;
}
// ============================================================================
// HTTP Headers
// ============================================================================
/**
* API response headers
*/
export interface APIResponseHeaders {
'x-response-time'?: string;
'x-authorization-response'?: 'ok' | 'unauthorized';
'content-type'?: string;
}
// ============================================================================
// Health Endpoint Types
// ============================================================================
/**
* Health check response data
*/
export interface HealthData {
status: 'ok';
timestamp: string; // ISO 8601 format
uptime: number; // Server uptime in seconds
}
/**
* Health endpoint metadata containing system information
*
* @example
* ```typescript
* {
* systemInfo: true,
* serverTime: "2025-06-30T12:00:00.000Z",
* nodeVersion: "v24.0.2",
* platform: "linux",
* arch: "x64"
* }
* ```
*/
export interface HealthMetadata {
/** Indicates that system information is included in the metadata */
systemInfo: boolean;
/** Server current time in ISO 8601 format */
serverTime: string;
/** Node.js version (e.g., "v24.0.2") */
nodeVersion: string;
/** Operating system platform (e.g., "linux", "darwin", "win32") */
platform: string;
/** System architecture (e.g., "x64", "arm64") */
arch: string;
}
/**
* Health endpoint response
*/
export type HealthResponse = SuccessResponse<HealthData, HealthMetadata>;
// ============================================================================
// Documentation Endpoint Types
// ============================================================================
/**
* API documentation response data
*/
export interface DocsData {
name: string;
version: string;
endpoints: Record<string, string>;
}
/**
* Documentation endpoint metadata containing API information
*
* @example
* ```typescript
* {
* endpointCount: 9,
* apiVersion: "v1",
* generatedAt: "2025-06-30T12:00:00.000Z",
* documentation: true
* }
* ```
*/
export interface DocsMetadata {
/** Total number of available API endpoints */
endpointCount: number;
/** API version identifier (e.g., "v1") */
apiVersion: string;
/** Documentation generation timestamp in ISO 8601 format */
generatedAt: string;
/** Indicates this is a documentation endpoint response */
documentation: boolean;
}
/**
* Documentation endpoint response
*/
export type DocsResponse = SuccessResponse<DocsData, DocsMetadata>;
// ============================================================================
// Items Endpoint Types
// ============================================================================
/**
* Individual item status
*/
export interface ItemStatus {
itemgroup: string; // Item group code
itemcode: string; // Unique item identifier
description: string; // Item name/description
onhand: number; // Current stock quantity
onorder: number; // Quantity on purchase orders
onassembly: number; // Quantity in assembly/production
min: number; // Minimum stock level
max: number; // Maximum stock level
}
/**
* Individual sales order item
*/
export interface SalesItem {
orderEntry: number; // Sales order entry number
orderNum: number; // Sales order number
cardName: string; // Customer name
dueDate: string; // Due date in ISO format
itemcode: string; // Item code
openqty: number; // Open quantity
}
/**
* Items response data
*/
export interface ItemsStatusData {
items: ItemStatus[];
}
/**
* Sales response data
*/
export interface SalesData {
sales: SalesItem[];
}
/**
* Individual item group
*/
export interface ItemGroup {
code: string; // Item group code
name: string; // Item group name/description
}
/**
* Item groups response data
*/
export interface ItemGroupsData {
groups: ItemGroup[];
}
/**
* Items metadata
*/
export interface ItemsStatusMetadata {
count: number;
}
/**
* Sales metadata
*/
export interface SalesMetadata {
count: number;
from: string; // ISO 8601 format
to: string; // ISO 8601 format
}
/**
* Item groups metadata
*/
export interface ItemGroupsMetadata {
count: number;
}
/**
* Items endpoint response
*/
export type ItemsStatusResponse = SuccessResponse<ItemsStatusData, ItemsStatusMetadata>;
/**
* Sales endpoint response
*/
export type SalesResponse = SuccessResponse<SalesData, SalesMetadata>;
/**
* Item groups endpoint response
*/
export type ItemGroupsResponse = SuccessResponse<ItemGroupsData, ItemGroupsMetadata>;
/**
* Individual item hierarchy
*/
export interface Hierarchy {
rank: string; // Hierarchy level/rank (string)
root: string; // Root node identifier (string)
parent: string | null; // Parent item code or null for root items
node: string; // Child item code
quantity: number; // Required quantity of child per parent
injections: number; // Number of injection processes required
}
/**
* Item hierarchies response data
*/
export interface HierarchiesData {
hierarchies: Hierarchy[];
}
/**
* Item hierarchies metadata
*/
export interface HierarchiesMetadata {
count: number;
}
/**
* Item hierarchies endpoint response
*/
export type HierarchiesResponse = SuccessResponse<HierarchiesData, HierarchiesMetadata>;
/**
* Individual tree relationship
*/
export interface Tree {
parent: string; // Parent item code
itemcode: string; // Child item code
quantity: number; // Quantity relationship
injPerUn?: number; // Injection per unit (optional)
parentSector?: string; // Parent item's production sector (optional)
itemSector?: string; // Child item's production sector (optional)
parentMaxPerOrder?: number; // Parent item's maximum per order (optional)
itemMaxPerOrder?: number; // Child item's maximum per order (optional)
}
/**
* Trees response data
*/
export interface TreesData {
trees: Tree[];
}
/**
* Trees metadata
*/
export interface TreesMetadata {
count: number;
}
/**
* Trees endpoint response
*/
export type TreesResponse = SuccessResponse<TreesData, TreesMetadata>;
// ============================================================================
// Production Sectors Endpoint Types
// ============================================================================
/**
* Individual production sector
*/
export interface ProductionSector {
code: string; // Unique sector identifier
name: string; // Human-readable sector name
order: number; // Display order for consistent presentation
}
/**
* Production sectors response data
*/
export interface ProductionSectorsData {
sectors: ProductionSector[];
}
/**
* Production sectors metadata
*/
export interface ProductionSectorsMetadata {
count: number;
lastUpdated: string; // ISO 8601 timestamp
}
/**
* Production sectors endpoint response
*/
export type ProductionSectorsResponse = SuccessResponse<ProductionSectorsData, ProductionSectorsMetadata>;
// ============================================================================
// Plans Endpoint Types
// ============================================================================
/**
* Production plan
*/
export interface Plan {
plan_id: number; // Unique plan identifier
plan_createdate: string; // Plan creation date (ISO 8601)
plan_username: string; // User who created the plan
plan_sapstatus: string; // SAP system status
plan_status: string; // Human-readable plan status
plan_releasedate: string | null; // Plan release date or null
products_total: number; // Total products in plan
products_generated: number; // Products generated
products_canceled: number; // Products canceled
products_released: number; // Products released to production
products_closed: number; // Products completed/closed
injections_generated: number; // Total injection processes generated
injections_canceled: number; // Injection processes canceled
injections_released: number; // Injection processes released
injections_closed: number; // Injection processes completed
}
/**
* Plans list response data
*/
export interface PlansData {
plans: Plan[];
}
/**
* Plans list metadata
*/
export interface PlansMetadata {
count: number;
}
/**
* Plans list endpoint response
*/
export type PlansResponse = SuccessResponse<PlansData, PlansMetadata>;
/**
* Single plan response data
*/
export interface SinglePlanData {
plan: Plan;
}
/**
* Single plan metadata
*/
export interface SinglePlanMetadata {
planId: number;
}
/**
* Single plan endpoint response
*/
export type SinglePlanResponse = SuccessResponse<SinglePlanData, SinglePlanMetadata>;
// ============================================================================
// Plan Products Endpoint Types
// ============================================================================
/**
* Plan product
*/
export interface PlanProduct {
itemcode: string; // Product item code
quantity: number; // Planned production quantity
group: string; // Product group name for categorization
}
/**
* Plan products response data
*
* @remarks
* The products array can be empty when a plan exists but has no products.
* This is a normal, successful response (HTTP 200), not an error condition.
*/
export interface PlanProductsData {
products: PlanProduct[];
}
/**
* Plan products metadata
*/
export interface PlanProductsMetadata {
count: number;
planId: number;
}
/**
* Plan products endpoint response
*
* @remarks
* API Behavior:
* - HTTP 200: Plan exists (products array may be empty or populated)
* - HTTP 404: Plan with the specified ID does not exist
* - Empty products array indicates the plan exists but has no products
*/
export type PlanProductsResponse = SuccessResponse<PlanProductsData, PlanProductsMetadata>;
// ============================================================================
// Plan Work Orders Endpoint Types
// ============================================================================
/**
* Work order
*/
export interface WorkOrder {
order_id: number; // Work order unique identifier
order_num: number; // Work order number
order_itemcode: string; // Item being produced
order_plannedqty: number; // Planned production quantity
order_status: string; // Current work order status
order_completedqty: number; // Quantity completed
order_rejectqty: number; // Quantity rejected/scrapped
order_createdate: string; // Creation timestamp (ISO 8601)
order_originabs: number | null; // Origin document reference
order_originnum: number | null; // Origin line number
order_releasedate: string | null; // Release timestamp or null
}
/**
* Plan work orders response data
*
* @remarks
* The workOrders array can be empty when a plan exists but has no work orders.
* This is a normal, successful response (HTTP 200), not an error condition.
*/
export interface PlanWorkOrdersData {
workOrders: WorkOrder[];
}
/**
* Plan work orders metadata
*/
export interface PlanWorkOrdersMetadata {
count: number;
planId: number;
}
/**
* Plan work orders endpoint response
*
* @remarks
* API Behavior:
* - HTTP 200: Plan exists (workOrders array may be empty or populated)
* - HTTP 404: Plan with the specified ID does not exist
* - Empty workOrders array indicates the plan exists but has no work orders
*/
export type PlanWorkOrdersResponse = SuccessResponse<PlanWorkOrdersData, PlanWorkOrdersMetadata>;
// ============================================================================
// Plan Sectors Summary Endpoint Types
// ============================================================================
/**
* Plan sector summary
*/
export interface PlanSectorSummary {
plan_entry: number; // Plan document entry ID
sector_name: string; // Name of the production sector
sector_planned_qtty: number; // Total planned quantity for the sector
sector_open_qtty: number; // Quantity still to be completed
sector_completed_qtty: number; // Total completed quantity
sector_abandoned_qtty: number; // Quantity abandoned (closed/cancelled)
}
/**
* Single plan sectors summary response data
*/
export interface PlanSectorsSummaryData {
sectors: PlanSectorSummary[];
}
/**
* Single plan sectors summary metadata
*/
export interface PlanSectorsSummaryMetadata {
plan_id: number;
sector_count: number;
total_planned: number;
total_completed: number;
completion_rate: number;
}
/**
* Single plan sectors summary endpoint response
*
* @remarks
* API Behavior:
* - HTTP 200: Plan exists (sectors array may be empty or populated)
* - HTTP 404: Plan with the specified ID does not exist
* - Empty sectors array indicates the plan exists but has no sectors
*/
export type PlanSectorsSummaryResponse = SuccessResponse<PlanSectorsSummaryData, PlanSectorsSummaryMetadata>;
/**
* All plans sectors summary response data
*/
export interface AllPlansSectorsSummaryData {
sectors: PlanSectorSummary[];
}
/**
* All plans sectors summary metadata
*/
export interface AllPlansSectorsSummaryMetadata {
total_sectors: number;
unique_plans: number;
unique_sector_names: string[];
total_planned: number;
total_completed: number;
overall_completion_rate: number;
}
/**
* All plans sectors summary endpoint response
*/
export type AllPlansSectorsSummaryResponse = SuccessResponse<AllPlansSectorsSummaryData, AllPlansSectorsSummaryMetadata>;
// ============================================================================
// User Endpoint Types
// ============================================================================
/**
* User lookup response data
*/
export interface UserData {
userId: number;
}
/**
* User lookup metadata
*/
export interface UserMetadata {
username: string;
}
/**
* User lookup endpoint response
*/
export type UserResponse = SuccessResponse<UserData, UserMetadata>;
// ============================================================================
// Client Configuration Types
// ============================================================================
/**
* Client configuration options
*/
export interface ClientConfig {
baseUrl: string; // Required field
timeout?: number;
retries?: number;
retryDelay?: number;
enableLogging?: boolean;
logLevel?: 'debug' | 'info' | 'warn' | 'error';
headers?: Record<string, string>;
}
/**
* Request context for logging/debugging
*/
export interface RequestContext {
method: string;
url: string;
startTime: number;
endTime?: number;
duration?: number;
attempt?: number;
maxAttempts?: number;
}
// ============================================================================
// Error Types
// ============================================================================
/**
* Client error types
*/
export type ClientErrorType =
| 'network_error'
| 'timeout_error'
| 'validation_error'
| 'authorization_error'
| 'not_found_error'
| 'server_error'
| 'unknown_error';
/**
* Client error details
*/
export interface ClientErrorDetails {
type: ClientErrorType;
message: string;
statusCode?: number;
originalError?: Error;
context?: RequestContext;
problemDetails?: ProblemDetails;
}
// ============================================================================
// Utility Types
// ============================================================================
/**
* Extract data type from API response
*/
export type ExtractData<T> = T extends SuccessResponse<infer TData, any> ? TData : never;
/**
* Extract metadata type from API response
*/
export type ExtractMetadata<T> = T extends SuccessResponse<any, infer TMetadata> ? TMetadata : never;
/**
* Type guard for success responses
*/
export function isSuccessResponse<T, M>(response: APIResponse<T, M>): response is SuccessResponse<T, M> {
return response.success === true;
}
/**
* Type guard for error responses
*/
export function isErrorResponse(response: APIResponse): response is ErrorResponse {
return response.success === false;
}
// ============================================================================
// Client Return Types (Data + Metadata)
// ============================================================================
/**
* Client method return types - all methods return consistent { data, metadata } format
*
* @example
* ```typescript
* // All client methods return the same structure:
* const healthResult: ClientHealthResult = await client.getHealth();
* const { data, metadata } = healthResult;
*
* // Consistent destructuring pattern for all methods:
* const { data: healthData, metadata: healthMeta } = await client.getHealth();
* const { data: docsData, metadata: docsMeta } = await client.getDocs();
* const { data: itemsData, metadata: itemsMeta } = await client.getItemsStatus();
* ```
*/
export type ClientHealthResult = { data: HealthData; metadata: HealthMetadata };
export type ClientDocsResult = { data: DocsData; metadata: DocsMetadata };
export type ClientItemsStatusResult = { data: ItemsStatusData; metadata: ItemsStatusMetadata };
export type ClientHierarchiesResult = { data: HierarchiesData; metadata: HierarchiesMetadata };
export type ClientTreesResult = { data: TreesData; metadata: TreesMetadata };
export type ClientProductionSectorsResult = { data: ProductionSectorsData; metadata: ProductionSectorsMetadata };
export type ClientPlansResult = { data: PlansData; metadata: PlansMetadata };
export type ClientSinglePlanResult = { data: SinglePlanData; metadata: SinglePlanMetadata };
export type ClientPlanProductsResult = { data: PlanProductsData; metadata: PlanProductsMetadata };
export type ClientPlanWorkOrdersResult = { data: PlanWorkOrdersData; metadata: PlanWorkOrdersMetadata };
export type ClientUserResult = { data: UserData; metadata: UserMetadata };
// ============================================================================
// Endpoint Map Types
// ============================================================================
/**
* Map of all available endpoints and their response types
*/
export interface EndpointMap {
'GET /health': HealthResponse;
'GET /docs': DocsResponse;
'GET /items/status': ItemsStatusResponse;
'GET /items/hierarchies': HierarchiesResponse;
'GET /items/trees': TreesResponse;
'GET /production-sectors': ProductionSectorsResponse;
'GET /plans': PlansResponse;
'GET /plans/{planId}': SinglePlanResponse;
'GET /plans/{planId}/products': PlanProductsResponse;
'GET /plans/{planId}/work-orders': PlanWorkOrdersResponse;
'GET /users/{username}': UserResponse;
}
/**
* Map of client method return types
*/
export interface ClientEndpointMap {
'getHealth': ClientHealthResult;
'getDocs': ClientDocsResult;
'getItemsStatus': ClientItemsStatusResult;
'getItemHierarchies': ClientHierarchiesResult;
'getItemTrees': ClientTreesResult;
'getProductionSectors': ClientProductionSectorsResult;
'getPlans': ClientPlansResult;
'getPlan': ClientSinglePlanResult;
'getPlanProducts': ClientPlanProductsResult;
'getPlanWorkOrders': ClientPlanWorkOrdersResult;
'getUser': ClientUserResult;
}
/**
* Union of all possible API responses
*/
export type AnyAPIResponse = EndpointMap[keyof EndpointMap];
/**
* Union of all possible client method results
*/
export type AnyClientResult = ClientEndpointMap[keyof ClientEndpointMap];