npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ritas-inc/prodplan-app

v1.0.44

Published

TypeScript client for Rita's Production Plan API

Readme

@ritas-inc/prodplan-app

TypeScript client for Rita's Production Plan API. This package provides a clean, type-safe interface for interacting with the Production Plan API, abstracting away HTTP complexity and providing comprehensive error handling.

Installation

npm install @ritas-inc/prodplan-app

Quick Start

import { ProdPlanClient } from '@ritas-inc/prodplan-app'

const client = new ProdPlanClient({
  apiUrl: 'https://api.ritas.com/prodplan/api/v1'
})

// Login
await client.login({
  CompanyDB: 'RITA_TEST',
  UserName: 'admin',
  Password: 'password123'
})

// Create a production plan
const plan = await client.createPlan({
  user: 'production_user',
  products: [
    { itemCode: 'ITEM001', quantity: 100 },
    { itemCode: 'ITEM002', quantity: 50 }
  ]
})

console.log('Plan created:', plan)

Configuration

Constructor Options

const client = new ProdPlanClient({
  apiUrl: 'https://api.ritas.com/prodplan/api/v1', // Required
  timeout: 30000,        // Optional: Request timeout in ms (default: 30000)
  retryAttempts: 3,      // Optional: Number of retry attempts (default: 3)
  xUserId: 'user-123'    // Optional: Initialize with existing xUserId for pre-authenticated client
})

Environment Variables

You can also configure the client using environment variables:

  • PRODPLAN_API_URL - API base URL
  • PRODPLAN_TIMEOUT - Request timeout in milliseconds
  • PRODPLAN_RETRY_ATTEMPTS - Number of retry attempts
// Uses environment variables for configuration
const client = new ProdPlanClient({
  apiUrl: process.env.PRODPLAN_API_URL! // Required if not provided in constructor
})

API Reference

Authentication

login(credentials: LoginCredentials): Promise<AuthResponse>

Authenticate with the Production Plan API using SAP B1 credentials.

const auth = await client.login({
  CompanyDB: 'RITA_TEST',
  UserName: 'admin', 
  Password: 'password123'
})

console.log('User ID:', auth.xUserId)

logout(): void

Clear authentication state.

client.logout()

isAuthenticated(): boolean

Check if the client is currently authenticated.

if (client.isAuthenticated()) {
  console.log('Client is authenticated')
}

setUserId(userId: string): void

Set the xUserId for authentication. Useful for creating multiple client instances with the same authentication.

client.setUserId('user-123')
console.log('Client is now authenticated:', client.isAuthenticated())

getUserId(): string | null

Get the current xUserId. Returns null if not authenticated.

const userId = client.getUserId()
if (userId) {
  console.log('Current user ID:', userId)
}

Production Plans

createPlan(planData: CreatePlanRequest): Promise<Plan>

Create a new production plan.

const plan = await client.createPlan({
  user: 'production_user',
  products: [
    { itemCode: 'ITEM001', quantity: 100 },
    { itemCode: 'ITEM002', quantity: 50 },
    { itemCode: 'ITEM003', quantity: 25 }
  ]
})

updatePlanProducts(planId: number, request: UpdatePlanProductsRequest): Promise<void>

Update the products in an existing production plan.

await client.updatePlanProducts(123, {
  products: [
    { itemCode: 'ITEM001', quantity: 150 }, // Updated quantity
    { itemCode: 'ITEM004', quantity: 75 }   // New product
  ]
})

generateWorkOrders(planId: number, dateRange: DateRange): Promise<WorkOrderGenerationResponse>

Generate work orders for a production plan within a specified date range.

const result = await client.generateWorkOrders(123, {
  from: '2025-08-01',
  to: '2025-08-31'
})

console.log('Work orders generated:', result.workOrdersGenerated)

releasePlan(planId: number): Promise<PlanReleaseResponse>

Release a production plan, moving it to the next status in the workflow.

const result = await client.releasePlan(123)
console.log('Plan status:', result.status)

cancelPlan(planId: number): Promise<void>

Cancel a production plan and clean up associated work orders.

await client.cancelPlan(123)
console.log('Plan cancelled successfully')

Session Management

checkSession(): Promise<SessionStatus>

Check if the current SAP B1 session is still valid. Useful for long-running applications or when you need to verify session status before performing operations.

const sessionStatus = await client.checkSession()

if (sessionStatus.valid) {
  console.log('Session is active')
  console.log('Session checked at:', sessionStatus.checkedAt)
} else {
  console.log('Session is invalid - need to re-authenticate')
}

isSessionValid(): Promise<boolean>

Simplified boolean check for session validity. Automatically handles authentication errors and returns false for invalid sessions, while re-throwing other types of errors (network issues, service problems).

const isValid = await client.isSessionValid()

if (!isValid) {
  // Re-authenticate
  await client.login(credentials)
}

// Proceed with operations
await client.createPlan(planData)

Health Check

healthCheck(): Promise<HealthStatus>

Check the health status of the Production Plan API.

const health = await client.healthCheck()

console.log('API Status:', health.status)
console.log('Uptime:', health.uptime, 'seconds')
console.log('Memory Usage:', health.memory.used, 'MB')

Error Handling

The client provides comprehensive error handling with specific error types for different scenarios:

import { 
  ProdPlanClient, 
  AuthenticationError, 
  ValidationError,
  NotFoundError,
  ServerError,
  NetworkError,
  TimeoutError
} from '@ritas-inc/prodplan-app'

try {
  await client.createPlan(planData)
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.log('Authentication failed, need to login again')
    await client.login(credentials)
  } else if (error instanceof ValidationError) {
    console.log('Invalid plan data:', error.problem.issues)
  } else if (error instanceof NotFoundError) {
    console.log('Resource not found:', error.problem.detail)
  } else if (error instanceof ServerError) {
    console.log('Server error occurred:', error.problem.title)
  } else if (error instanceof NetworkError) {
    console.log('Network error:', error.message)
  } else if (error instanceof TimeoutError) {
    console.log('Request timed out:', error.message)
  } else {
    console.log('Unexpected error:', error.message)
  }
}

Error Properties

All API errors extend ProdPlanApiError and include detailed information:

try {
  await client.createPlan(invalidData)
} catch (error) {
  if (error instanceof ProdPlanApiError) {
    console.log('Status:', error.status)
    console.log('Type:', error.problem.type)
    console.log('Title:', error.problem.title)
    console.log('Detail:', error.problem.detail)
    console.log('Issues:', error.problem.issues)
    
    // Check error category
    console.log('Is client error?', error.isClientError)
    console.log('Is server error?', error.isServerError)
  }
}

TypeScript Support

The package is built with TypeScript and provides comprehensive type definitions:

import type { 
  LoginCredentials,
  CreatePlanRequest,
  PlanProduct,
  DateRange,
  Plan,
  WorkOrderGenerationResponse,
  HealthStatus,
  SessionStatus,
  ApiResponse
} from '@ritas-inc/prodplan-app'

// Type-safe plan creation
const planData: CreatePlanRequest = {
  user: 'production_user',
  products: [
    { itemCode: 'ITEM001', quantity: 100 }
  ]
}

// Type-safe date range
const dateRange: DateRange = {
  from: '2025-08-01',
  to: '2025-08-31'
}

Advanced Usage

Sharing Authentication Between Client Instances

When working with multiple client instances in the same application, you can share the same authentication session to avoid multiple logins:

// Method 1: Using constructor with xUserId
const mainClient = new ProdPlanClient({
  apiUrl: 'https://api.ritas.com/prodplan/api/v1'
})

await mainClient.login({
  CompanyDB: 'RITA_PROD',
  UserName: 'user',
  Password: 'password'
})

// Create second client with the same xUserId
const secondClient = new ProdPlanClient({
  apiUrl: 'https://api.ritas.com/prodplan/api/v1',
  xUserId: mainClient.getUserId()! // Share the xUserId
})

console.log('Both clients authenticated:', 
  mainClient.isAuthenticated(), 
  secondClient.isAuthenticated()
) // Both return true
// Method 2: Using setUserId method
const client1 = new ProdPlanClient({
  apiUrl: 'https://api.ritas.com/prodplan/api/v1'
})

const client2 = new ProdPlanClient({
  apiUrl: 'https://api.ritas.com/prodplan/api/v1'
})

// Login with first client
await client1.login(credentials)

// Share authentication with second client
client2.setUserId(client1.getUserId()!)

// Both clients can now make authenticated requests
await Promise.all([
  client1.createPlan(plan1),
  client2.createPlan(plan2)
])
// Method 3: Managing authentication in a service class
class ProdPlanService {
  private mainClient: ProdPlanClient
  private workers: ProdPlanClient[] = []

  constructor() {
    this.mainClient = new ProdPlanClient({
      apiUrl: process.env.PRODPLAN_API_URL!
    })
  }

  async authenticate(credentials: LoginCredentials) {
    await this.mainClient.login(credentials)
    
    // Share authentication with all worker clients
    this.workers.forEach(worker => {
      worker.setUserId(this.mainClient.getUserId()!)
    })
  }

  createWorkerClient(): ProdPlanClient {
    const worker = new ProdPlanClient({
      apiUrl: process.env.PRODPLAN_API_URL!,
      xUserId: this.mainClient.getUserId() || undefined
    })
    
    this.workers.push(worker)
    return worker
  }

  async processPlansInParallel(plans: CreatePlanRequest[]) {
    // Create a worker client for each plan
    const workers = plans.map(() => this.createWorkerClient())
    
    // Process all plans in parallel
    const results = await Promise.allSettled(
      plans.map((plan, index) => workers[index].createPlan(plan))
    )
    
    return results
  }
}

Custom HTTP Configuration

const client = new ProdPlanClient({
  apiUrl: 'https://api.ritas.com/prodplan/api/v1',
  timeout: 60000,        // 60 second timeout
  retryAttempts: 5       // Retry failed requests 5 times
})

Batch Operations

// Process multiple plans efficiently
const plans = [plan1, plan2, plan3]

const results = await Promise.allSettled(
  plans.map(plan => client.createPlan(plan))
)

results.forEach((result, index) => {
  if (result.status === 'fulfilled') {
    console.log(`Plan ${index + 1} created:`, result.value)
  } else {
    console.log(`Plan ${index + 1} failed:`, result.reason.message)
  }
})

Advanced Session Management

class ProductionPlanService {
  private client: ProdPlanClient

  constructor() {
    this.client = new ProdPlanClient({
      apiUrl: process.env.PRODPLAN_API_URL!
    })
  }

  async ensureValidSession() {
    // First check if client has local authentication
    if (!this.client.isAuthenticated()) {
      await this.login()
      return
    }

    // Check if SAP B1 session is still valid
    const isValid = await this.client.isSessionValid()
    if (!isValid) {
      console.log('Session expired, re-authenticating...')
      await this.login()
    }
  }

  private async login() {
    await this.client.login({
      CompanyDB: process.env.SAP_COMPANY_DB!,
      UserName: process.env.SAP_USERNAME!,
      Password: process.env.SAP_PASSWORD!
    })
  }

  async createPlan(planData: CreatePlanRequest) {
    await this.ensureValidSession()
    return await this.client.createPlan(planData)
  }

  async performBatchOperations(plans: CreatePlanRequest[]) {
    // Validate session once before batch operations
    await this.ensureValidSession()

    const results = []
    for (const plan of plans) {
      try {
        const result = await this.client.createPlan(plan)
        results.push({ success: true, data: result })
      } catch (error) {
        if (error instanceof AuthenticationError) {
          // Session expired during batch, re-authenticate and retry once
          await this.login()
          try {
            const result = await this.client.createPlan(plan)
            results.push({ success: true, data: result })
          } catch (retryError) {
            results.push({ success: false, error: retryError })
          }
        } else {
          results.push({ success: false, error })
        }
      }
    }
    return results
  }
}

Examples

Complete Production Planning Workflow

import { ProdPlanClient } from '@ritas-inc/prodplan-app'

async function completeWorkflow() {
  const client = new ProdPlanClient({
    apiUrl: process.env.PRODPLAN_API_URL!
  })

  try {
    // 1. Login
    await client.login({
      CompanyDB: 'RITA_PROD',
      UserName: 'planner',
      Password: 'secure_password'
    })

    // 2. Check API health
    const health = await client.healthCheck()
    console.log('API is healthy:', health.status === 'healthy')

    // 3. Create production plan
    const plan = await client.createPlan({
      user: 'production_planner',
      products: [
        { itemCode: 'WIDGET_A', quantity: 500 },
        { itemCode: 'WIDGET_B', quantity: 300 }
      ]
    })
    console.log('Created plan:', plan.id)

    // 4. Update plan if needed
    await client.updatePlanProducts(plan.id, {
      products: [
        { itemCode: 'WIDGET_A', quantity: 600 }, // Increased quantity
        { itemCode: 'WIDGET_B', quantity: 300 },
        { itemCode: 'WIDGET_C', quantity: 100 }  // Added new product
      ]
    })

    // 5. Generate work orders
    const workOrders = await client.generateWorkOrders(plan.id, {
      from: '2025-08-01',
      to: '2025-08-31'
    })
    console.log('Generated work orders:', workOrders.workOrdersGenerated)

    // 6. Release the plan
    const release = await client.releasePlan(plan.id)
    console.log('Plan released with status:', release.status)

  } catch (error) {
    console.error('Workflow failed:', error)
    
    // Clean up on error
    if (error instanceof ValidationError) {
      console.log('Fix these validation issues:', error.problem.issues)
    }
  }
}

completeWorkflow()

Development

Building the Package

cd client
npm install
npm run build

Publishing

The package is automatically published to NPM when changes are pushed to the master branch. Version numbers are automatically incremented.

License

ISC

Support

For issues and support, please visit the GitHub repository.