npm package: @jts-web/web-ble-lite
Description: A lightweight, cross-browser wrapper for the Web Bluetooth API (BLE/GATT)
Latest version: 0.0.0

# @jts-web/web-ble-lite

A lightweight, cross-browser wrapper for the Web Bluetooth API (BLE/GATT) designed for modern web applications.

## Features

- 🎯 **Simple API** - Easy-to-use functions for Bluetooth Low Energy operations
- 🔍 **Browser Detection** - Automatic detection and helpful error messages
- 📦 **Lightweight** - Minimal dependencies, small bundle size
- 🛡️ **Type Safe** - Full TypeScript support with comprehensive type definitions
- 🔌 **Cross-Browser** - Works with Chrome and Edge (with graceful degradation for others)

## Installation

```bash
npm install @jts-web/web-ble-lite
```

## Browser Support

| Browser     | Support          | Notes                                     |
| ----------- | ---------------- | ----------------------------------------- |
| **Chrome**  | ✅ Full          | Version 56+ (Desktop, Android, Chrome OS) |
| **Edge**    | ✅ Full          | Version 79+ (Chromium-based)              |
| **Safari**  | ❌ Not Supported | Web Bluetooth API is not available        |
| **Firefox** | ❌ Not Supported | Web Bluetooth API is not available        |

### Important Notes

- **HTTPS Required**: Web Bluetooth requires a secure context (HTTPS) or `localhost`
- **User Gesture**: Device requests must be triggered by a user action (click, touch, etc.)
- **Safari/Firefox**: These browsers do not support the Web Bluetooth API. The library will provide clear error messages when used in unsupported browsers.

## Quick Start

```typescript
import {
  isAvailable,
  requestDevice,
  connect,
  readCharacteristic,
  writeCharacteristic,
  startNotifications,
  disconnect,
} from "@jts-web/web-ble-lite";

// Check if Web Bluetooth is available
const available = await isAvailable();
if (!available) {
  console.error("Web Bluetooth is not available");
  return;
}

// Request a device
const device = await requestDevice({
  filters: [{ services: ["battery_service"] }],
});

// Connect to the device
const { gatt } = await connect(device);

// Read a characteristic
const value = await readCharacteristic(
  device,
  "battery_service",
  "battery_level"
);

// Write to a characteristic
await writeCharacteristic(
  device,
  "heart_rate_service",
  "heart_rate_control_point",
  new Uint8Array([1])
);

// Start receiving notifications
await startNotifications(
  device,
  "heart_rate_service",
  "heart_rate_measurement",
  (data) => {
    console.log("Received data:", data);
  }
);

// Disconnect when done
disconnect(device);
```

## API Reference

### Browser Detection

#### `detectBrowser(): BrowserInfo`

Detects the current browser and Web Bluetooth support.

```typescript
import { detectBrowser } from "@jts-web/web-ble-lite";

const browser = detectBrowser();
console.log(browser.name); // "Chrome", "Edge", "Safari", "Firefox", or "Unknown"
console.log(browser.supportsWebBluetooth); // true or false
```

### Availability

#### `isAvailable(): Promise<boolean>`

Checks if Web Bluetooth is available in the current browser and environment.

```typescript
const available = await isAvailable();
```

### Device Management

#### `requestDevice(opts: RequestDeviceOptions): Promise<DeviceHandle>`

Requests a Bluetooth device from the user.

```typescript
const device = await requestDevice({
  filters: [{ services: ["battery_service"] }, { name: "My Device" }],
  optionalServices: ["heart_rate_service"],
  // OR
  acceptAllDevices: true,
});
```

**Options:**

- `filters`: Array of filters to match devices
- `optionalServices`: Array of service UUIDs to request
- `acceptAllDevices`: If true, shows all nearby devices

**Throws:**

- `NotSupportedError`: If Web Bluetooth is not available
- `PermissionDeniedError`: If user denies permission

#### `connect(handle: DeviceHandle): Promise<{ device: BluetoothDevice; gatt: BluetoothRemoteGATTServer }>`

Connects to a Bluetooth device.

```typescript
const { device, gatt } = await connect(deviceHandle);
```

#### `disconnect(handle: DeviceHandle): void`

Disconnects from a Bluetooth device.

```typescript
disconnect(deviceHandle);
```

### Characteristics

#### `readCharacteristic(handle: DeviceHandle, service: UUID, characteristic: UUID): Promise<DataView>`

Reads a characteristic value.

```typescript
const value = await readCharacteristic(
  deviceHandle,
  "battery_service",
  "battery_level"
);
// value is a DataView
const batteryLevel = value.getUint8(0);
```

#### `writeCharacteristic(handle: DeviceHandle, service: UUID, characteristic: UUID, data: BufferSource): Promise<void>`

Writes a value to a characteristic.

```typescript
await writeCharacteristic(
  deviceHandle,
  "heart_rate_service",
  "heart_rate_control_point",
  new Uint8Array([1])
);
```

#### `startNotifications(handle: DeviceHandle, service: UUID, characteristic: UUID, onData: (v: DataView) => void): Promise<void>`

Starts receiving notifications from a characteristic.

```typescript
await startNotifications(
  deviceHandle,
  "heart_rate_service",
  "heart_rate_measurement",
  (data) => {
    const heartRate = data.getUint8(1);
    console.log("Heart rate:", heartRate);
  }
);
```

#### `stopNotifications(handle: DeviceHandle, service: UUID, characteristic: UUID): Promise<void>`

Stops receiving notifications from a characteristic.

```typescript
await stopNotifications(
  deviceHandle,
  "heart_rate_service",
  "heart_rate_measurement"
);
```

## Error Handling

The library provides specific error classes for different scenarios:

```typescript
import {
  NotSupportedError,
  PermissionDeniedError,
  DeviceDisconnectedError,
} from "@jts-web/web-ble-lite";

try {
  const device = await requestDevice({ acceptAllDevices: true });
} catch (error) {
  if (error instanceof NotSupportedError) {
    console.error("Web Bluetooth not supported:", error.browser);
    // Error message includes browser-specific guidance
  } else if (error instanceof PermissionDeniedError) {
    console.error("User denied permission");
  } else {
    console.error("Other error:", error);
  }
}
```

## Type Definitions

All types are exported for use in your TypeScript projects:

```typescript
import type {
  DeviceHandle,
  RequestDeviceOptions,
  BrowserInfo,
} from "@jts-web/web-ble-lite";
```

## Examples

### Battery Level Monitor

```typescript
import {
  requestDevice,
  connect,
  readCharacteristic,
} from "@jts-web/web-ble-lite";

async function monitorBattery() {
  const device = await requestDevice({
    filters: [{ services: ["battery_service"] }],
  });

  await connect(device);

  // Read battery level every second
  setInterval(async () => {
    const value = await readCharacteristic(
      device,
      "battery_service",
      "battery_level"
    );
    const level = value.getUint8(0);
    console.log(`Battery: ${level}%`);
  }, 1000);
}
```

### Heart Rate Monitor

```typescript
import {
  requestDevice,
  connect,
  startNotifications,
  disconnect,
} from "@jts-web/web-ble-lite";

async function monitorHeartRate() {
  const device = await requestDevice({
    filters: [{ services: ["heart_rate"] }],
  });

  await connect(device);

  await startNotifications(
    device,
    "heart_rate",
    "heart_rate_measurement",
    (data) => {
      const flags = data.getUint8(0);
      const rate16 = flags & 0x1;
      let heartRate;

      if (rate16) {
        heartRate = data.getUint16(1, true);
      } else {
        heartRate = data.getUint8(1);
      }

      console.log(`Heart rate: ${heartRate} bpm`);
    }
  );

  // Stop after 30 seconds
  setTimeout(() => {
    disconnect(device);
  }, 30000);
}
```

## Development

```bash
# Install dependencies
npm install

# Build
npm run build

# Lint
npm run lint

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Run tests with UI
npm run test:ui

# Run tests with coverage
npm run test:coverage
```

## Testing

The library includes comprehensive tests using [Vitest](https://vitest.dev/). Tests cover:

- ✅ Error classes (NotSupportedError, PermissionDeniedError, DeviceDisconnectedError)
- ✅ Browser detection (Chrome, Edge, Safari, Firefox, Unknown)
- ✅ Web Bluetooth availability checks
- ✅ Device request and connection handling
- ✅ Characteristic read/write operations
- ✅ Notification start/stop functionality
- ✅ Error handling for unsupported browsers

### Running Tests

```bash
# Run all tests once
npm test

# Run tests in watch mode (re-runs on file changes)
npm run test:watch

# Open Vitest UI for interactive testing
npm run test:ui

# Generate coverage report
npm run test:coverage
```

### Test Structure

- **`src/index.test.ts`** - Main test file with unit tests for all exported functions
- **`src/test/setup.ts`** - Test setup file with mocks and helpers for browser environment simulation

Tests use `jsdom` to simulate a browser environment and mock the Web Bluetooth API for testing without requiring actual Bluetooth hardware.

## License

MIT

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.