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

@voltade/wess-sdk

v1.4.2

Published

A comprehensive TypeScript SDK for the WESS Open API with built-in error handling and resource-based architecture

Readme

@voltade/wess-sdk

A comprehensive, type-safe TypeScript SDK for the WESS Open API with built-in error handling and resource-based architecture.

License: MIT GitHub Package

Features

  • Type-safe: Full TypeScript support with exported types and Zod schemas
  • Resource-based architecture: Organized by API domain (user, branches, customers)
  • Error handling: Specific error classes for different failure scenarios
  • Zero dependencies: Uses native fetch API (Node.js 18+)
  • Configurable: Environment variables or programmatic configuration

Installation

Note: This package is published to the public npm registry (registry.npmjs.org) as a public scoped package.

npm install @voltade/wess-sdk
# or
yarn add @voltade/wess-sdk
# or
pnpm add @voltade/wess-sdk

Quick Start

import { WessClient } from "@voltade/wess-sdk";

const client = new WessClient({
  baseUrl: "https://your-wess-api.com/api",
  bearerToken: "your-bearer-token",
});

// Get current user
const user = await client.user.get();

// List all branches
const branches = await client.branches.list();

// Create an appointment
const appointment = await client.branches.createOnlineAppointment(branchId, {
  date: "2024-12-15 10:00:00",
  items: [
    { product_id: 1718, unit: 1 },
    { product_id: 5523, unit: 1 },
  ],
  customer_id: 123,
});

Configuration

Environment Variables

WESS_BASE_URL=https://your-wess-api.com/api
WESS_BEARER_TOKEN=your-bearer-token

Client Options

interface WessClientConfig {
  baseUrl: string; // Base URL for the WESS API
  bearerToken: string; // Bearer token for authentication
  timeout?: number; // Request timeout in milliseconds (default: 30000)
  headers?: Record<string, string>; // Custom headers for all requests
}

Method Reference

Quick lookup table for all SDK methods.

UserResource

| Method | HTTP | Endpoint | Returns | | ------- | ---- | ---------- | -------------- | | get() | GET | /v1/user | UserResponse |

BranchesResource

| Method | HTTP | Endpoint | Returns | | --------------------------------------------------------------- | ----- | ----------------------------------------------------------------------------- | ------------------------------- | | list() | GET | /v1/branches | Branch[] | | get(branchId) | GET | /v1/branches/:branch | Branch | | getCustomer(branchId, customerId) | GET | /v1/branches/:branch/customers/:customer | Customer | | getOnlineAppointmentServices(branchId) | GET | /v1/online/branches/:branch/appointments/services | OnlineService[] | | getOnlineAppointmentEmployees(branchId, params) | GET | /v1/online/branches/:branch/appointments/employees | OnlineEmployee[] | | getOnlineAppointmentTimeSlots(branchId, params) | GET | /v1/online/branches/:branch/appointments/time-slots | OnlineTimeSlot[] | | createOnlineAppointment(branchId, params, options?) | POST | /v1/online/branches/:branch/appointments | OnlineSaleTicket | | cancelOnlineAppointment(branchId, saleTicketId, params) | PATCH | /v1/online/branches/:branch/appointments/:saleTicketId/cancel | OnlineSaleTicket | | createCustomer(branchId, params) | POST | /v1/online/branches/:branch/customers | OnlineCustomer | | getCustomerUpcomingAppointments(branchId, customerId, params) | GET | /v1/online/branches/:branch/customers/:customer/appointments/upcoming-appointments | OnlineSaleTicket[] |

CustomersResource

| Method | HTTP | Endpoint | Returns | | ---------------------------------- | ---- | ----------------------------------------- | ------------ | | searchByPhoneNumber(phoneNumber) | GET | /v1/online/customers/lookup/phone-number/:phoneNumber | OnlineCustomer[] |

OnlineResource

| Method | HTTP | Endpoint | Returns | | ----------------------------------------------------------------- | ----- | ------------------------------------------------------------------------------------ | ----------------------------- | | listBranches(params?) | GET | /v1/online/branches | { data: OnlineBranch[] } | | getBranch(branchId) | GET | /v1/online/branches/:branch | OnlineBranch | | getServices(branchId) | GET | /v1/online/branches/:branch/appointments/services | OnlineService[] | | getEmployees(branchId, params) | GET | /v1/online/branches/:branch/appointments/employees | OnlineEmployee[] | | getTimeSlots(branchId, params) | GET | /v1/online/branches/:branch/appointments/time-slots | OnlineTimeSlot[] | | listAppointments(branchId, params?) | GET | /v1/online/branches/:branch/appointments | { data: ... } | | createAppointment(branchId, params, options?) | POST | /v1/online/branches/:branch/appointments | OnlineSaleTicket | | cancelAppointment(branchId, saleTicketId, params) | PATCH | /v1/online/branches/:branch/appointments/:saleTicketId/cancel | OnlineSaleTicket | | lookupCustomerByPhone(phone) | GET | /v1/online/customers/lookup/phone-number/:phone | OnlineCustomer[] | | listCustomers(branchId, params?) | GET | /v1/online/branches/:branch/customers | { data: OnlineCustomer[] } | | createCustomer(branchId, params) | POST | /v1/online/branches/:branch/customers | OnlineCustomer | | getCustomer(branchId, customerId) | GET | /v1/online/branches/:branch/customers/:customer | OnlineCustomer | | getCustomerUpcomingAppointments(branchId, customerId, params) | GET | /v1/online/branches/:branch/customers/:customer/appointments/upcoming-appointments | OnlineSaleTicket[] |


API Reference

User Resource

client.user.get()

Get the current authenticated user.

const response = await client.user.get();
// Returns: { code: number, data: User }

Returns: UserResponse


Branches Resource

client.branches.list()

List all branches.

const branches = await client.branches.list();

Returns: Branch[]


client.branches.get(branchId)

Get a single branch by ID.

const branch = await client.branches.get(4630);

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | branchId | number | Yes | The branch ID |

Returns: Branch


client.branches.getCustomer(branchId, customerId)

Get a customer from a specific branch.

const customer = await client.branches.getCustomer(4630, 123);
// or by customer code
const customer = await client.branches.getCustomer(4630, "CUST001");

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | branchId | number | Yes | The branch ID | | customerId | number \| string | Yes | The customer ID or customer code |

Returns: Customer


client.branches.getOnlineAppointmentServices(branchId)

Get services available for online appointments.

const services = await client.branches.getOnlineAppointmentServices(4630);

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | branchId | number | Yes | The branch ID |

Returns: OnlineService[]


client.branches.getOnlineAppointmentEmployees(branchId, params)

Get employees available for online appointments, filtered by product IDs.

const employees = await client.branches.getOnlineAppointmentEmployees(4630, {
  product_ids: [1718, 5523],
});

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | branchId | number | Yes | The branch ID | | params.product_ids | number[] | Yes | Array of product IDs to filter employees |

Returns: OnlineEmployee[]


client.branches.getOnlineAppointmentTimeSlots(branchId, params)

Get available time slots for online appointments.

const timeSlots = await client.branches.getOnlineAppointmentTimeSlots(4630, {
  product_ids: [1718],
  date: "2024-12-15",
});

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | branchId | number | Yes | The branch ID | | params.product_ids | number[] | Yes | Array of product IDs | | params.date | string | Yes | Date in YYYY-MM-DD format |

Returns: OnlineTimeSlot[]


client.branches.createOnlineAppointment(branchId, params, options?)

Create an online appointment.

const appointment = await client.branches.createOnlineAppointment(
  4630,
  {
    date: "2024-12-15 10:00:00",
    items: [
      { product_id: 1718, unit: 1 },
      { product_id: 5523, unit: 2 },
    ],
    customer_id: 123,
    employee_id: 456, // optional
    remark: "Notes here", // optional
  },
  {
    idempotencyKey: "unique-request-key", // optional, prevents duplicate submissions
  }
);

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | branchId | number | Yes | The branch ID | | params.date | string | Yes | Appointment date (ISO8601 or Y-m-d H:i:s format) | | params.items | { product_id: number, unit: number }[] | Yes | Array of items with product ID and quantity | | params.customer_id | number | Yes | The customer ID | | params.employee_id | number \| null | No | The employee ID (optional) | | params.remark | string | No | Appointment notes | | options.idempotencyKey | string | No | Idempotency key to prevent duplicates |

Returns: OnlineSaleTicket


client.branches.cancelOnlineAppointment(branchId, saleTicketId, params)

Cancel an online appointment.

const cancelled = await client.branches.cancelOnlineAppointment(4630, 789, {
  customer_id: 123,
});

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | branchId | number | Yes | The branch ID | | saleTicketId | number | Yes | The sale ticket ID to cancel | | params.customer_id | number | Yes | The customer ID |

Returns: OnlineSaleTicket


client.branches.getCustomerUpcomingAppointments(branchId, customerId, params)

Get upcoming appointments for a customer within a date range.

const appointments = await client.branches.getCustomerUpcomingAppointments(
  4630,
  123,
  {
    from: "2024-12-01 00:00:00",
    to: "2024-12-31 23:59:59",
  }
);

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | branchId | number | Yes | The branch ID | | customerId | number | Yes | The customer ID | | params.from | string | Yes | Start date (ISO8601 or Y-m-d H:i:s format) | | params.to | string | Yes | End date (ISO8601 or Y-m-d H:i:s format) |

Returns: OnlineSaleTicket[]

Note: Only returns appointments with statuses: OPEN, CONFIRMED, REQUEST, BOOKING_CONFIRMED.


Customers Resource

client.customers.searchByPhoneNumber(phoneNumber)

Search customers by phone number.

const customers = await client.customers.searchByPhoneNumber("+60123456789");

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | phoneNumber | string | Yes | The phone number to search for |

Returns: OnlineCustomer[]


Online Resource

Endpoints for the /v1/online/... namespace (public online booking surface). Online branches are implicitly online-enabled — the online branch shape has no published field (unlike the management Branch type).

client.online.listBranches(params?)

List online branches.

const { data } = await client.online.listBranches();

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | params.page | number | No | Page number | | params.per_page | number | No | Results per page |

Returns: { data: OnlineBranch[] }


client.online.getBranch(branchId)

Get a single online branch by ID.

const branch = await client.online.getBranch(4630);

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | branchId | number | Yes | The branch ID |

Returns: OnlineBranch


client.online.getServices(branchId)

Get services available for online appointments.

const services = await client.online.getServices(4630);

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | branchId | number | Yes | The branch ID |

Returns: OnlineService[]


client.online.getEmployees(branchId, params)

Get employees available for online appointments, filtered by product IDs.

const employees = await client.online.getEmployees(4630, {
  product_ids: [1718, 5523],
});

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | branchId | number | Yes | The branch ID | | params.product_ids | number[] | Yes | Array of product IDs to filter employees |

Returns: OnlineEmployee[]


client.online.getTimeSlots(branchId, params)

Get available time slots (per employee) for online appointments.

const timeSlots = await client.online.getTimeSlots(4630, {
  product_ids: [1718],
  date: "2024-12-15",
});

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | branchId | number | Yes | The branch ID | | params.product_ids | number[] | Yes | Array of product IDs | | params.date | string | Yes | Date in YYYY-MM-DD format |

Returns: OnlineTimeSlot[]

Note: Slot times are returned as UTC ISO8601 strings — convert to branch-local time before passing to createAppointment.


client.online.listAppointments(branchId, params?)

List online appointments for a branch.

const { data } = await client.online.listAppointments(4630);

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | branchId | number | Yes | The branch ID | | params.page | number | No | Page number | | params.per_page | number | No | Results per page |

Returns: { data: ... } (lenient shape)


client.online.createAppointment(branchId, params, options?)

Create an online appointment.

const appointment = await client.online.createAppointment(
  4630,
  {
    date: "2024-12-15 10:00:00",
    items: [
      { product_id: 1718, unit: 1 },
      { product_id: 5523, unit: 2 },
    ],
    customer_id: 123,
    employee_id: 456, // optional
    remark: "Notes here", // optional
  },
  {
    idempotencyKey: "unique-request-key", // optional, prevents duplicate submissions
  }
);

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | branchId | number | Yes | The branch ID | | params.date | string | Yes | Branch-local appointment date in YYYY-MM-DD HH:mm:ss format | | params.items | { product_id: number, unit: number }[] | Yes | Array of items with product ID and quantity | | params.customer_id | number | Yes | The customer ID | | params.employee_id | number \| null | No | The employee ID (optional) | | params.remark | string | No | Appointment notes | | options.idempotencyKey | string | No | Idempotency key to prevent duplicates |

Returns: OnlineSaleTicket

Note: date must be branch-local YYYY-MM-DD HH:mm:ss. Since getTimeSlots returns slot times as UTC ISO8601, convert them to branch-local time before booking.


client.online.cancelAppointment(branchId, saleTicketId, params)

Cancel an online appointment.

const cancelled = await client.online.cancelAppointment(4630, 789, {
  customer_id: 123,
});

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | branchId | number | Yes | The branch ID | | saleTicketId | number | Yes | The sale ticket ID to cancel | | params.customer_id | number | Yes | The customer ID |

Returns: OnlineSaleTicket


client.online.lookupCustomerByPhone(phone)

Look up customers by phone number.

const customers = await client.online.lookupCustomerByPhone("+6590029446");

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | phone | string | Yes | Full E.164 phone number including + and country code |

Returns: OnlineCustomer[] (without relation_branch)

Note: Requires the full E.164 number including the + and country code (e.g. +6590029446). A national-only number returns an empty array.


client.online.listCustomers(branchId, params?)

List customers for an online branch.

const { data } = await client.online.listCustomers(4630);

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | branchId | number | Yes | The branch ID | | params.page | number | No | Page number | | params.per_page | number | No | Results per page |

Returns: { data: OnlineCustomer[] }


client.online.createCustomer(branchId, params)

Create a customer for an online branch.

const customer = await client.online.createCustomer(4630, {
  first_name: "Jane",
  phone_mobile_country_code: "65",
  phone_mobile: "90029446",
});

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | branchId | number | Yes | The branch ID | | params.first_name | string | Yes | Customer first name | | params.phone_mobile_country_code | string | Yes | Mobile country code | | params.phone_mobile | string | Yes | Mobile number | | params.ic_no | string | No | IC / identification number | | params.last_name | string \| null | No | Customer last name | | params.salutation | string | No | Salutation | | params.detail | object | No | Additional customer details |

Returns: OnlineCustomer


client.online.getCustomer(branchId, customerId)

Get a single customer from an online branch.

const customer = await client.online.getCustomer(4630, 123);

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | branchId | number | Yes | The branch ID | | customerId | number | Yes | The customer ID |

Returns: OnlineCustomer (with relation_branch)


client.online.getCustomerUpcomingAppointments(branchId, customerId, params)

Get upcoming appointments for a customer within a date range.

const appointments = await client.online.getCustomerUpcomingAppointments(
  4630,
  123,
  {
    from: "2024-12-01 00:00:00",
    to: "2024-12-31 23:59:59",
  }
);

Parameters: | Name | Type | Required | Description | |------|------|----------|-------------| | branchId | number | Yes | The branch ID | | customerId | number | Yes | The customer ID | | params.from | string | Yes | Start of range (see note) | | params.to | string | Yes | End of range (see note) |

Returns: OnlineSaleTicket[]

Note: from/to must be branch-local YYYY-MM-DD HH:mm:ss or ISO8601-with-timezone, and from must be ≥ now.


Error Handling

The SDK provides specific error classes for different failure scenarios:

import {
  WessError,
  WessAuthenticationError,
  WessNotFoundError,
  WessValidationError,
  WessRateLimitError,
  WessNetworkError,
  WessTimeoutError,
} from "@voltade/wess-sdk";

try {
  const branch = await client.branches.get(99999);
} catch (error) {
  if (error instanceof WessAuthenticationError) {
    // 401 - Invalid or expired token
  } else if (error instanceof WessNotFoundError) {
    // 404 - Resource not found
  } else if (error instanceof WessValidationError) {
    // 422 - Validation failed
    console.error("Errors:", error.errors);
  } else if (error instanceof WessRateLimitError) {
    // 429 - Too many requests
  } else if (error instanceof WessNetworkError) {
    // Network connectivity issues
  } else if (error instanceof WessTimeoutError) {
    // Request timeout
  } else if (error instanceof WessError) {
    // Generic API error
    console.error(`API error (${error.statusCode}):`, error.message);
  }
}

Error Classes

| Error Class | Status Code | Description | | ------------------------- | ----------- | ------------------------------ | | WessError | Any | Base error class | | WessAuthenticationError | 401 | Invalid or missing credentials | | WessNotFoundError | 404 | Resource not found | | WessValidationError | 422 | Request validation failed | | WessRateLimitError | 429 | Too many requests | | WessNetworkError | - | Network connectivity issues | | WessTimeoutError | - | Request timeout |


TypeScript Types

All types are exported with Zod schemas for runtime validation.

Import Types

import type {
  // Config
  WessClientConfig,
  RequestOptions,

  // User
  User,
  UserResponse,

  // Branch
  Branch,

  // Customer
  Customer,

  // Online Appointments - Services
  OnlineAppointmentService,
  ServiceDetails,

  // Online Appointments - Employees
  OnlineAppointmentEmployee,
  EmployeeProduct,

  // Online Appointments - Time Slots
  OnlineAppointmentTimeSlot,

  // Online Appointments - Sale Ticket (Create/Cancel/Upcoming)
  OnlineAppointmentSaleTicket,
  SaleTicketCustomer,
  SaleTicketItem,

  // Online Resource (/v1/online/...)
  OnlineBranch,
  OnlineService,
  OnlineEmployee,
  OnlineTimeSlot,
  OnlineCustomer,
  OnlineSaleTicket,

  // Request Parameters
  GetEmployeesParams,
  GetTimeSlotsParams,
  CreateAppointmentParams,
  CreateAppointmentOptions,
  CancelAppointmentParams,
  GetUpcomingAppointmentsParams,

  // Error Responses
  ApiErrorResponse,
  ValidationErrorResponse,
} from "@voltade/wess-sdk";

Import Zod Schemas

import {
  // User
  UserSchema,
  UserResponseSchema,

  // Branch
  BranchSchema,

  // Customer
  CustomerSchema,

  // Online Appointments
  OnlineAppointmentServiceSchema,
  ServiceDetailsSchema,
  OnlineAppointmentEmployeeSchema,
  EmployeeProductSchema,
  OnlineAppointmentTimeSlotSchema,
  OnlineAppointmentSaleTicketSchema,
  SaleTicketCustomerSchema,
  SaleTicketItemSchema,

  // Request Parameters
  GetEmployeesParamsSchema,
  GetTimeSlotsParamsSchema,
  CreateAppointmentParamsSchema,
  CancelAppointmentParamsSchema,
  GetUpcomingAppointmentsParamsSchema,

  // Error Responses
  ApiErrorResponseSchema,
  ValidationErrorResponseSchema,
} from "@voltade/wess-sdk";

Advanced Usage

Direct Resource Access

import { WessClient, BranchesResource } from "@voltade/wess-sdk";

const client = new WessClient({ baseUrl: "...", bearerToken: "..." });

const branches: BranchesResource = client.branches;
const allBranches = await branches.list();

Custom HTTP Client

const httpClient = client.getHttpClient();

// Make custom requests
const response = await httpClient.get("/custom-endpoint", {
  params: { key: "value" },
});

// Available methods: get, post, put, patch, delete

Requirements

  • Node.js >= 18.0.0
  • TypeScript >= 5.0.0

Architecture

@voltade/wess-sdk/
├── index.ts              # Main entry point & WessClient class
├── client.ts             # HTTP client wrapper
├── types.ts              # Re-exports from types/
├── errors.ts             # Error classes
├── resources/
│   ├── index.ts          # Resource exports
│   ├── user.ts           # User resource (1 method)
│   ├── branches.ts       # Branches resource (9 methods)
│   └── customers.ts      # Customers resource (1 method)
└── types/
    ├── index.ts          # Type exports
    ├── config.ts         # Config types
    ├── user.ts           # User types
    ├── branch.ts         # Branch types
    ├── customer.ts       # Customer types
    ├── appointment.ts    # Appointment types
    └── error.ts          # Error response types

Publishing (Maintainers Only)

This package is published to the public npm registry (registry.npmjs.org) as a public scoped package (@voltade/wess-sdk).

1. Authenticate

npm login

(must be a user with publish access to the @voltade org/scope on npmjs.org)

2. Version + publish

The version in package.json is already set for the release. Then:

npm publish --access public
  • prepublishOnly runs npm run clean && npm run build automatically, so dist/ is rebuilt from source before publishing.
  • For future releases, bump with npm version patch|minor|major first.

3. Verify

npm view @voltade/wess-sdk version    # should show the new version

License

MIT (c) Voltade

Support

For issues and questions, please file an issue on GitHub.