npm package: @route-optimization/core
Description: Core package for route optimization map visualization
Latest version: 1.0.4

# @route-optimization/core

Core package for route optimization and map visualization. Framework-agnostic TypeScript library providing route optimization via Google Cloud, map adapters, types, and utilities.

**🚛 Route Optimization** • **🗺️ Map Visualization** • **🎯 TypeScript** • **🎭 Mock Mode**

## ⚠️ Important: Client-Side vs Server-Side

**This package has two entry points:**

### 📦 Main Export (Client-Safe)
```typescript
import { GoogleMapsAdapter, type Route } from '@route-optimization/core';
```
**✅ Safe for:** React, Vue, Next.js client components, browsers  
**Includes:** Map adapters, types, utilities  
**Excludes:** RouteCalculator (uses Node.js gRPC)

### 🖥️ Server Export (Node.js Only)
```typescript
import { RouteCalculator } from '@route-optimization/core/server';
```
**✅ Safe for:** Node.js, API routes, Next.js server components  
**❌ Don't use in:** React components, browser code  
**Causes error:** `Module not found: Can't resolve 'fs'`

**📖 [Read the Client vs Server Guide](../../docs/guide/client-vs-server.md)**

## Table of Contents

- [Features](#features)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Client-Side vs Server-Side](#client-side-vs-server-side)
- [Setup Guide](#setup-guide)
  - [Google Cloud Setup](#google-cloud-setup-for-production)
  - [Development Without Google Cloud](#development-without-google-cloud)
- [Usage](#usage)
  - [Route Optimization with RouteCalculator](#route-optimization-with-routecalculator)
  - [Basic Usage with Google Maps](#basic-usage-with-google-maps)
  - [Using Utilities](#using-utilities)
  - [Advanced Examples](#advanced-examples)
- [API Reference](#api-reference)
- [Troubleshooting](#troubleshooting)
- [Development](#development)
- [Related Packages](#related-packages)

## Features

- 🎯 **TypeScript-first**: Full type safety with comprehensive type definitions
- 🚛 **Route Optimization**: Integrated Google Route Optimization API with mock mode
- 🗺️ **Map Adapters**: Pluggable adapter pattern supporting multiple map providers
- 📦 **Zero Dependencies**: Pure TypeScript core with no framework dependencies
- 🧪 **Fully Tested**: 80%+ test coverage with unit tests
- 📐 **Coordinate Utilities**: Distance calculation, bounds calculation, formatting
- ✅ **Validation**: Built-in validation for routes, stops, and coordinates
- 🎭 **Mock Mode**: Test optimization without API calls or credentials

## Installation

```bash
npm install @route-optimization/core
# or
pnpm add @route-optimization/core
# or
yarn add @route-optimization/core
```

## Quick Start

### Route Optimization (5 minutes setup)

> ⚠️ **Server-Side Only**: RouteCalculator uses Node.js and cannot run in browsers.  
> Use this in: API routes, server components, backend services.  
> [Learn more about client vs server usage](../../docs/guide/client-vs-server.md)

```typescript
// ✅ Server-side code only (Node.js, API routes, etc.)
import { RouteCalculator } from '@route-optimization/core/server';

// 1. Start with mock mode (no credentials needed)
const calculator = new RouteCalculator({ useMockMode: true });
await calculator.initialize();

// 2. Define your optimization problem
const response = await calculator.optimizeRoutes({
  shipments: [
    {
      id: 'delivery-1',
      deliveries: [{ location: { latitude: 13.7467, longitude: 100.5342 } }],
      label: 'Customer A',
    },
    {
      id: 'delivery-2',
      deliveries: [{ location: { latitude: 13.7363, longitude: 100.4918 } }],
      label: 'Customer B',
    },
  ],
  vehicles: [
    {
      id: 'van-1',
      startLocation: { latitude: 13.7563, longitude: 100.5018 },
    },
  ],
});

// 3. Use the optimized routes
if (response.success) {
  console.log('Optimized routes:', response.routes);
  console.log('Total cost:', response.metrics?.totalCost);
}
```

**Ready for production?** Replace `useMockMode: true` with your Google Cloud credentials:

```typescript
// Using API Key (simpler)
const calculator = new RouteCalculator({
  projectId: 'your-project-id',
  apiKey: 'YOUR_API_KEY',
});

// OR using Service Account (more secure)
const calculator = new RouteCalculator({
  projectId: 'your-project-id',
  credentialsPath: './service-account-key.json',
});
```

### Map Visualization (Client-Safe)

```typescript
// ✅ Safe for client-side (React, Vue, browsers)
import { GoogleMapsAdapter } from '@route-optimization/core';

const adapter = new GoogleMapsAdapter();
await adapter.initialize({
  apiKey: 'YOUR_GOOGLE_MAPS_API_KEY',
  container: document.getElementById('map'),
});

// Render a route
adapter.renderRoute({
  id: 'route-1',
  vehicleId: 'vehicle-1',
  stops: [
    {
      id: 'depot',
      location: { lat: 13.7563, lng: 100.5018 },
      type: 'START',
      sequence: 0,
    },
  ],
});
```

### When to Use What?

| Scenario                           | Recommendation               | Why                         |
| ---------------------------------- | ---------------------------- | --------------------------- |
| Local development                  | Mock mode                    | Free, fast, no setup        |
| Unit testing                       | Mock mode                    | Deterministic, no API calls |
| Integration testing                | Mock mode or staging project | Controlled environment      |
| Production (< 1000 requests/month) | Real API with free tier      | Cost-effective              |
| Production (high volume)           | Real API with optimization   | Better routes, traffic data |
| Prototyping/demos                  | Mock mode                    | Quick to set up             |

## Setup Guide

### Google Cloud Setup (for Production)

To use the Route Optimization API with real data, you need to set up Google Cloud:

#### 1. Create a Google Cloud Project

1. Go to [Google Cloud Console](https://console.cloud.google.com)
2. Create a new project or select existing one
3. Note your Project ID

#### 2. Enable Required APIs

Enable these APIs in your project:

- [Cloud Optimization API](https://console.cloud.google.com/apis/library/cloudoptimization.googleapis.com)
- [Routes API](https://console.cloud.google.com/apis/library/routes.googleapis.com) (optional, for directions)

#### 3. Set Up Billing

Route Optimization API requires billing to be enabled:

1. Go to [Billing](https://console.cloud.google.com/billing)
2. Link a billing account to your project

#### 4. Choose Authentication Method

You have two options for authentication:

##### Option A: API Key (Simpler, Recommended for Getting Started)

1. Go to [Credentials](https://console.cloud.google.com/apis/credentials)
2. Click "Create Credentials" > "API Key"
3. Copy the API key
4. (Optional but recommended) Click "Restrict Key" to:
   - Add application restrictions
   - Restrict to Cloud Optimization API

**Pros:**

- ✅ Simpler setup
- ✅ No file management
- ✅ Easy to rotate

**Cons:**

- ⚠️ Less granular permissions
- ⚠️ Should be restricted properly

##### Option B: Service Account (More Secure for Production)

1. Go to [IAM & Admin > Service Accounts](https://console.cloud.google.com/iam-admin/serviceaccounts)
2. Click "Create Service Account"
3. Name it (e.g., "route-optimizer")
4. Grant role: "Cloud Optimization API User"
5. Click "Create Key" and download JSON file
6. Save as `service-account-key.json` in your project

**Pros:**

- ✅ More secure
- ✅ Granular IAM permissions
- ✅ Better audit trail

**Cons:**

- ⚠️ More complex setup
- ⚠️ File management required

#### 5. Initialize RouteCalculator

##### Using API Key (Recommended for Quick Start)

```typescript
import { RouteCalculator } from '@route-optimization/core';

const calculator = new RouteCalculator({
  projectId: 'your-project-id',
  apiKey: 'YOUR_API_KEY',
  debug: true, // Enable logging during setup
});

await calculator.initialize();
```

##### Using Service Account (File Path)

```typescript
import { RouteCalculator } from '@route-optimization/core';

const calculator = new RouteCalculator({
  projectId: 'your-project-id',
  credentialsPath: './service-account-key.json',
  debug: true,
});

await calculator.initialize();
```

##### Using Service Account (Credentials Object)

Instead of a file path, you can pass credentials directly:

```typescript
import serviceAccountKey from './service-account-key.json';

const calculator = new RouteCalculator({
  projectId: 'your-project-id',
  credentials: serviceAccountKey,
});
```

### Development Without Google Cloud

Use mock mode for development and testing:

```typescript
const calculator = new RouteCalculator({
  useMockMode: true,
  debug: true,
});

await calculator.initialize(); // No credentials needed
```

Mock mode:

- ✅ No API key or credentials required
- ✅ No billing charges
- ✅ Instant responses
- ✅ Deterministic results for testing
- ❌ Simplified optimization algorithm
- ❌ No real-world traffic data

### Cost Estimation

Google Route Optimization API pricing (as of 2024):

| Request Size        | Price per Request           |
| ------------------- | --------------------------- |
| 0-10 shipments      | Free (1,000 requests/month) |
| 11-100 shipments    | $0.50                       |
| 101-1,000 shipments | $5.00                       |
| 1,001+ shipments    | Contact sales               |

**Tips to reduce costs:**

- Use mock mode during development
- Batch multiple requests together
- Cache optimization results when possible
- Set reasonable timeouts to avoid long-running requests
- Use `searchMode: 'RETURN_FAST'` for quicker, cheaper results

## Usage

### Basic Usage with Google Maps

```typescript
import { GoogleMapsAdapter, StopType } from '@route-optimization/core';
import type { Route } from '@route-optimization/core';

// Initialize the adapter
const mapAdapter = new GoogleMapsAdapter();

await mapAdapter.initialize({
  apiKey: 'YOUR_GOOGLE_MAPS_API_KEY',
  container: 'map-container',
  center: { lat: 13.7563, lng: 100.5018 },
  zoom: 12,
});

// Create a route
const route: Route = {
  id: 'route-1',
  vehicle: {
    id: 'truck-1',
    type: VehicleType.LIGHT_TRUCK,
    startLocation: { lat: 13.7563, lng: 100.5018 },
  },
  stops: [
    {
      id: 'stop-1',
      location: { lat: 13.7467, lng: 100.5342 },
      type: StopType.PICKUP,
      label: 'Pickup Point',
    },
    {
      id: 'stop-2',
      location: { lat: 13.7363, lng: 100.4918 },
      type: StopType.DELIVERY,
      label: 'Delivery Point',
    },
  ],
  totalDistance: 5000,
  totalDuration: 900,
};

// Render the route
mapAdapter.renderRoute(route);
```

### Using Utilities

```typescript
import {
  calculateBounds,
  calculateDistance,
  formatDistance,
  formatDuration,
  validateRoute,
} from '@route-optimization/core';

// Calculate bounds for multiple points
const bounds = calculateBounds([
  { lat: 13.7563, lng: 100.5018 },
  { lat: 13.7467, lng: 100.5342 },
]);

// Calculate distance between two points
const distance = calculateDistance(
  { lat: 13.7563, lng: 100.5018 },
  { lat: 13.7467, lng: 100.5342 }
);
console.log(formatDistance(distance)); // "3.2 km"

// Validate a route
validateRoute(route); // Throws error if invalid
```

### Route Optimization with RouteCalculator

The `RouteCalculator` service provides route optimization using Google Route Optimization API with support for mock mode.

```typescript
import { RouteCalculator } from '@route-optimization/core';
import type { OptimizationRequest, OptimizationResponse } from '@route-optimization/core';

// Initialize with API Key (simplest)
const calculator = new RouteCalculator({
  projectId: 'your-google-cloud-project',
  apiKey: 'YOUR_API_KEY',
  debug: true,
});

// OR initialize with Service Account
const calculatorWithSA = new RouteCalculator({
  projectId: 'your-google-cloud-project',
  credentialsPath: './service-account-key.json',
  debug: true,
});

// OR use mock mode for testing
const mockCalculator = new RouteCalculator({
  useMockMode: true,
  debug: true,
});

// Initialize the calculator
await calculator.initialize();

// Create an optimization request
const request: OptimizationRequest = {
  shipments: [
    {
      id: 'shipment-1',
      pickups: [
        {
          location: { latitude: 13.7563, longitude: 100.5018 },
          duration: '300s',
        },
      ],
      deliveries: [
        {
          location: { latitude: 13.7467, longitude: 100.5342 },
          duration: '300s',
        },
      ],
      label: 'Package A',
      demands: [{ type: 'weight', value: 10 }],
    },
    {
      id: 'shipment-2',
      deliveries: [
        {
          location: { latitude: 13.7363, longitude: 100.4918 },
          duration: '300s',
        },
      ],
      label: 'Package B',
    },
  ],
  vehicles: [
    {
      id: 'vehicle-1',
      startLocation: { latitude: 13.7563, longitude: 100.5018 },
      endLocation: { latitude: 13.7563, longitude: 100.5018 },
      loadLimits: {
        weight: { hardMaxLoad: 50 },
      },
      costPerKilometer: 0.5,
      costPerHour: 10,
    },
  ],
  globalDurationCostPerHour: 20,
  searchMode: 'RETURN_FAST',
  timeout: '30s',
};

// Optimize routes
const response: OptimizationResponse = await calculator.optimizeRoutes(request);

if (response.success) {
  console.log('Optimization successful!');
  console.log('Routes:', response.routes);
  console.log('Metrics:', response.metrics);
  console.log('Statistics:', response.statistics);
} else {
  console.error('Optimization failed:', response.error);
}
```

#### RouteCalculator Configuration

```typescript
interface RouteCalculatorConfig {
  projectId?: string; // Google Cloud project ID
  apiKey?: string; // API Key for authentication (alternative to service account)
  credentialsPath?: string; // Path to service account key file
  credentials?: object; // Service account key JSON object
  useMockMode?: boolean; // Use mock mode (no API calls)
  defaultSearchMode?: 'RETURN_FAST' | 'CONSUME_ALL_AVAILABLE_TIME';
  defaultTimeout?: string; // e.g., "30s"
  debug?: boolean; // Enable debug logging
}
```

**Authentication Options (choose one):**

- `apiKey`: Simple API key authentication (recommended for getting started)
- `credentialsPath`: Path to service account JSON file (more secure)
- `credentials`: Service account credentials object (for dynamic loading)
- `useMockMode: true`: No authentication needed (for testing)

````

#### Optimization Request

```typescript
interface OptimizationRequest {
  shipments: Shipment[];
  vehicles: OptimizationVehicle[];
  globalDurationCostPerHour?: number;
  searchMode?: 'RETURN_FAST' | 'CONSUME_ALL_AVAILABLE_TIME';
  timeout?: string;
  considerTraffic?: boolean;
}

interface Shipment {
  id?: string;
  pickups?: PickupDelivery[];
  deliveries?: PickupDelivery[];
  demands?: Array<{ type: string; value: number }>;
  label?: string;
  penaltyCost?: number;
}

interface OptimizationVehicle {
  id?: string;
  startLocation: OptimizationLocation;
  endLocation?: OptimizationLocation;
  loadLimits?: { [resourceType: string]: LoadLimit };
  fixedCost?: number;
  costPerKilometer?: number;
  costPerHour?: number;
  travelMode?: 'DRIVING' | 'WALKING' | 'BICYCLING' | 'TRANSIT';
  maxRouteDuration?: string;
}
````

#### Optimization Response

```typescript
interface OptimizationResponse {
  success: boolean;
  routes?: OptimizedRouteInfo[];
  metrics?: OptimizationMetrics;
  statistics?: RouteStatistics;
  skippedShipments?: SkippedShipment[];
  error?: string;
}

interface OptimizedRouteInfo {
  vehicleId: string;
  shipmentIds: string[];
  totalDistance?: number; // meters
  totalDuration?: string; // e.g., "3600s"
  stops: number;
  cost?: number;
}

interface OptimizationMetrics {
  totalCost: number;
  totalDistance?: number; // meters
  usedVehicles: number;
  skippedShipments: number;
  optimizationDuration?: string;
}

interface RouteStatistics {
  averageStopsPerVehicle: number;
  maxStopsInRoute: number;
  minStopsInRoute: number;
  utilizationRate: number; // 0-1
}
```

#### RouteCalculator Methods

- **`initialize(): Promise<void>`** - Initialize the Google Route Optimization client
- **`optimizeRoutes(request: OptimizationRequest): Promise<OptimizationResponse>`** - Optimize routes
- **`updateConfig(config: Partial<RouteCalculatorConfig>): void`** - Update configuration
- **`getConfig(): RouteCalculatorConfig`** - Get current configuration

#### Mock Mode

Mock mode allows you to test optimization without making actual API calls or setting up Google Cloud credentials:

```typescript
const calculator = new RouteCalculator({
  useMockMode: true,
  debug: true,
});

await calculator.initialize(); // No API setup needed

const response = await calculator.optimizeRoutes(request);
// Returns simulated optimization results
```

#### Error Handling

The calculator provides detailed error messages with helpful tips:

```typescript
const response = await calculator.optimizeRoutes(request);

if (!response.success) {
  console.error('Error:', response.error);
  // Error messages include troubleshooting tips
  // Example: "API not enabled. Enable it at: https://..."
}
```

### Advanced Examples

#### Multi-Vehicle Optimization

```typescript
const request: OptimizationRequest = {
  shipments: [
    { id: 'pkg-1', deliveries: [{ location: { latitude: 13.7467, longitude: 100.5342 } }] },
    { id: 'pkg-2', deliveries: [{ location: { latitude: 13.7363, longitude: 100.4918 } }] },
    { id: 'pkg-3', deliveries: [{ location: { latitude: 13.7263, longitude: 100.5218 } }] },
  ],
  vehicles: [
    {
      id: 'truck-1',
      startLocation: { latitude: 13.7563, longitude: 100.5018 },
      costPerKilometer: 0.8,
      loadLimits: { weight: { hardMaxLoad: 100 } },
    },
    {
      id: 'truck-2',
      startLocation: { latitude: 13.7563, longitude: 100.5018 },
      costPerKilometer: 0.5,
      loadLimits: { weight: { hardMaxLoad: 50 } },
    },
  ],
};

const response = await calculator.optimizeRoutes(request);
response.routes?.forEach((route) => {
  console.log(`${route.vehicleId}: ${route.stops} stops, ${route.totalDistance}m`);
});
```

#### With Time Windows

```typescript
const request: OptimizationRequest = {
  shipments: [
    {
      id: 'urgent-delivery',
      deliveries: [
        {
          location: { latitude: 13.7467, longitude: 100.5342 },
          duration: '300s',
          timeWindows: [
            {
              startTime: '2024-01-15T08:00:00Z',
              endTime: '2024-01-15T10:00:00Z',
            },
          ],
        },
      ],
      penaltyCost: 1000, // High penalty if skipped
    },
  ],
  vehicles: [
    {
      id: 'express-van',
      startLocation: { latitude: 13.7563, longitude: 100.5018 },
      maxRouteDuration: '14400s', // 4 hours max
    },
  ],
};
```

#### With Load Capacity

```typescript
const request: OptimizationRequest = {
  shipments: [
    {
      id: 'heavy-pkg',
      deliveries: [{ location: { latitude: 13.7467, longitude: 100.5342 } }],
      demands: [
        { type: 'weight', value: 30 },
        { type: 'volume', value: 5 },
      ],
    },
  ],
  vehicles: [
    {
      id: 'cargo-truck',
      startLocation: { latitude: 13.7563, longitude: 100.5018 },
      loadLimits: {
        weight: {
          softMaxLoad: 80,
          hardMaxLoad: 100,
          costPerUnitAboveSoftMax: 2,
        },
        volume: {
          hardMaxLoad: 10,
        },
      },
    },
  ],
};
```

#### Analyzing Results

```typescript
const response = await calculator.optimizeRoutes(request);

if (response.success && response.metrics && response.statistics) {
  console.log('=== Optimization Results ===');
  console.log(`Total Cost: $${response.metrics.totalCost.toFixed(2)}`);
  console.log(`Total Distance: ${(response.metrics.totalDistance! / 1000).toFixed(1)} km`);
  console.log(`Vehicles Used: ${response.metrics.usedVehicles}`);
  console.log(`Avg Stops/Vehicle: ${response.statistics.averageStopsPerVehicle.toFixed(1)}`);
  console.log(`Utilization: ${(response.statistics.utilizationRate * 100).toFixed(1)}%`);

  if (response.skippedShipments && response.skippedShipments.length > 0) {
    console.log(`\nSkipped Shipments: ${response.skippedShipments.length}`);
    response.skippedShipments.forEach((s) => {
      console.log(`  - ${s.id}: ${s.reason}`);
    });
  }
}
```

## API Reference

### Types

#### `LatLng`

```typescript
interface LatLng {
  lat: number; // -90 to 90
  lng: number; // -180 to 180
}
```

#### `Stop`

```typescript
interface Stop {
  id: string;
  location: LatLng;
  type: StopType;
  label?: string;
  address?: string;
  sequence?: number;
  timeWindow?: TimeWindow;
  serviceDuration?: number;
  demand?: number;
  metadata?: Record<string, unknown>;
}
```

#### `Route`

```typescript
interface Route {
  id: string;
  vehicle: Vehicle;
  stops: Stop[];
  segments?: RouteSegment[];
  totalDistance: number;
  totalDuration: number;
  totalCost?: number;
  metrics?: RouteMetrics;
  metadata?: Record<string, unknown>;
}
```

### Map Adapters

#### `IMapAdapter`

Interface for map provider adapters.

```typescript
interface IMapAdapter {
  initialize(config: MapConfig): Promise<void>;
  renderRoute(route: Route, options?: RouteRenderOptions): void;
  renderRoutes(routes: Route[], options?: RouteRenderOptions): void;
  addMarker(stop: Stop, config?: MarkerConfig): string;
  removeMarker(markerId: string): void;
  clearMarkers(): void;
  fitBounds(bounds?: MapBounds): void;
  setCenter(center: LatLng): void;
  setZoom(zoom: number): void;
  clearRoutes(): void;
  getBounds(): MapBounds | null;
  destroy(): void;
  getMapInstance(): unknown;
}
```

#### `GoogleMapsAdapter`

Google Maps implementation of `IMapAdapter`.

```typescript
const adapter = new GoogleMapsAdapter({
  events: {
    onClick: (latLng) => console.log('Map clicked:', latLng),
    onMarkerClick: (stop) => console.log('Marker clicked:', stop),
  },
  clustering: true,
});
```

### Utilities

#### Coordinate Utilities

- `calculateBounds(points: LatLng[]): MapBounds`
- `calculateDistance(from: LatLng, to: LatLng): number`
- `formatDistance(meters: number, locale?: string): string`
- `formatDuration(seconds: number): string`
- `isValidCoordinate(coord: LatLng): boolean`
- `getBoundsCenter(bounds: MapBounds): LatLng`
- `decodePolyline(encoded: string): LatLng[]`

#### Validation Utilities

- `validateRoute(route: Route): void`
- `validateStop(stop: Stop): void`
- `validateApiKey(apiKey: string): void`
- `validateRoutes(routes: Route[]): void`

## Troubleshooting

### RouteCalculator Issues

#### API Not Enabled Error

```
Route Optimization API is not enabled.
```

**Solution**: Enable the API in Google Cloud Console:

1. Go to [Cloud Optimization API](https://console.cloud.google.com/apis/library/cloudoptimization.googleapis.com)
2. Select your project
3. Click "Enable"

**Alternative**: Use mock mode for testing:

```typescript
const calculator = new RouteCalculator({ useMockMode: true });
```

#### Authentication Failed

```
Authentication failed. Please check your credentials.
```

**Solutions**:

- Verify your service account key file path is correct
- Ensure the service account has the "Cloud Optimization API User" role
- Check that the key file has valid JSON format
- Try using mock mode to isolate the issue

#### Billing Error

```
Billing issue: PERMISSION_DENIED
```

**Solutions**:

- Enable billing for your Google Cloud project
- Ensure the service account has billing permissions
- Use mock mode for development without billing

#### No Routes Returned

If optimization succeeds but no routes are returned:

```typescript
const response = await calculator.optimizeRoutes(request);
console.log('Skipped shipments:', response.skippedShipments);
```

**Common causes**:

- Vehicle capacity too low for shipment demands
- Time windows too restrictive
- Start/end locations too far from shipments
- Insufficient vehicles for number of shipments

**Solutions**:

- Increase vehicle `loadLimits`
- Adjust or remove time windows
- Add `penaltyCost` to shipments to allow skipping
- Add more vehicles or reduce shipments

#### Debug Mode

Enable debug logging to troubleshoot issues:

```typescript
const calculator = new RouteCalculator({
  debug: true,
  useMockMode: false,
  projectId: 'your-project',
});

await calculator.initialize();
const response = await calculator.optimizeRoutes(request);

// Console will show detailed information:
// 🚀 RouteCalculator initialized
// 🚀 Sending optimization request to Google API...
// 📦 Shipments: 5
// 🚛 Vehicles: 2
// ✅ Received response in 1234ms
```

### Map Adapter Issues

#### Google Maps Not Loading

Ensure you:

1. Have a valid Google Maps API key
2. Enabled "Maps JavaScript API" in Google Cloud Console
3. Set up billing for your project
4. Added API key restrictions if needed

#### Markers Not Appearing

Check that:

- Stop coordinates are valid (lat: -90 to 90, lng: -180 to 180)
- Map is fully initialized before adding markers
- Container element exists in DOM

## Development

```bash
# Install dependencies
pnpm install

# Build
pnpm build

# Test
pnpm test

# Test with coverage
pnpm test -- --coverage

# Lint
pnpm lint
```

## Bundle Size

- **Core**: < 5KB (gzipped)
- **Zero runtime dependencies**
- **Tree-shakeable**: Only import what you need

## Browser Support

- Chrome >= 90
- Firefox >= 88
- Safari >= 14
- Edge >= 90

## License

MIT

## Related Packages

- [@route-optimization/react](../react) - React hooks and components
- [@route-optimization/vue](../vue) - Vue composables and components
- [@route-optimization/vanilla](../vanilla) - Vanilla JavaScript API