npm package: @permas/calendar-sdk
Description: TypeScript SDK for the Permas Calendar Service API
Author: Permas Team
Latest version: 1.0.0

# Permas Calendar SDK

A TypeScript SDK for the Permas Calendar Service, designed to simplify integration with the Calendar API.

## Installation

```bash
npm install @permas/calendar-sdk
```

## Usage

### Basic Usage
```javascript
const { CalendarSDK } = require('@permas/calendar-sdk');

// Initialize the SDK with your API endpoint
const calendarSDK = new CalendarSDK({
  baseUrl: 'https://calendar-service.wittyisland-1f2e1c07.eastus2.azurecontainerapps.io',
  timeout: 30000 // Optional: default is 10000 (10 seconds)
});

// Use the SDK methods
async function fetchEvents() {
  try {
    const events = await calendarSDK.getEvents();
    console.log(events.data);
  } catch (error) {
    console.error('Error fetching events:', error);
  }
}
```

### API Notes

- **Update Operations**: The API does not return the updated object in response to update operations. To verify changes, fetch the object again after updating.
- **PATCH Operations**: The current API implementation does not support PATCH operations for partial updates. Use the full update methods instead.
- **Complex Nested Objects**: The API may not handle all nested objects correctly. In particular, arrays of nested objects (like sessions) may require special handling.

### API Methods

- `getHealth()` - Get the health status of the API
- `getEvents(filter?)` - Get all events with optional filtering
- `getEvent(id)` - Get a single event by ID
- `createEvent(event)` - Create a new event
- `updateEvent(id, data)` - Update an existing event
- `updateEventField(id, field, value)` - Update a specific field in an event (not supported in current API)
- `updateArrayItem(id, field, index, item)` - Update or add an item in an array field
- `deleteEvent(id)` - Delete an event

### Full Example: Creating and Managing Events

```javascript
const { CalendarSDK } = require('@permas/calendar-sdk');

async function manageTechConference() {
  try {
    // Initialize SDK
    const sdk = new CalendarSDK({
      baseUrl: 'https://calendar-service.wittyisland-1f2e1c07.eastus2.azurecontainerapps.io'
    });

    // 1. Create a new event
    const newConference = {
      title: "Annual Tech Conference 2025",
      date: new Date("2025-09-15T09:00:00Z"),
      type: "conference",
      description: "Our annual technology conference featuring the latest innovations",
      location: {
        name: "Tech Convention Center",
        address: {
          street: "123 Innovation Blvd",
          city: "San Francisco",
          state: "CA",
          zipCode: "94105",
          country: "USA"
        },
        room: "Main Hall",
        amenities: ["WiFi", "AV Equipment", "Catering"]
      },
      organizer: {
        name: "Tech Events Inc.",
        email: "events@techevents.example.com",
        phone: "555-123-4567"
      },
      sessions: [
        {
          title: "Keynote Address",
          speaker: "Jane Smith, CEO",
          time: "2025-09-15T09:30:00Z",
          duration: 60,
          description: "Opening keynote on industry trends"
        }
      ],
      attendees: [
        {
          name: "John Doe",
          email: "john@example.com",
          role: "attendee",
          confirmed: true
        }
      ],
      tags: ["technology", "innovation", "conference", "annual"],
      maxCapacity: 500,
      isVirtual: false
    };

    // Create the event
    const createdConference = await sdk.createEvent(newConference);
    console.log(`Conference created with ID: ${createdConference._id}`);

    // 2. Add a session to the conference
    const updatedConference = await sdk.updateArrayItem(
      createdConference._id,
      'sessions',
      -1,
      {
        title: "Networking Lunch",
        time: "2025-09-15T12:30:00Z",
        duration: 90,
        description: "Lunch and networking opportunity"
      }
    );

    console.log(`Conference now has ${updatedConference?.sessions?.length || 0} sessions`);

    // 3. Update the conference details
    await sdk.updateEvent(createdConference._id, {
      title: "Annual Tech Conference 2025 - SOLD OUT",
      status: "full"
    });

    // 4. Fetch the updated conference
    const updatedConferenceData = await sdk.getEvent(createdConference._id);
    console.log(`Updated conference title: ${updatedConferenceData.title}`);

    // 5. Find all conferences
    const allConferences = await sdk.getEvents({ type: "conference" });
    console.log(`Found ${allConferences.data.length} conferences`);

    // 6. Delete the conference (for cleanup)
    await sdk.deleteEvent(createdConference._id);
    console.log('Conference deleted successfully');

  } catch (error) {
    console.error('Error managing conference:', error.message);
    if (error.status) {
      console.error(`Status: ${error.status}, Response: ${JSON.stringify(error.data)}`);
    }
  }
}
```

## Error Handling

The SDK wraps all API errors with detailed information:

```javascript
try {
  await sdk.getEvent('invalid-id');
} catch (error) {
  console.log(error.message);  // Human-readable message
  console.log(error.status);   // HTTP status code (e.g., 404)
  console.log(error.data);     // Response data from the API
}
```

## Testing

The SDK includes several test scripts to verify functionality:

```bash
# Basic API connectivity test
node test-api.js

# CRUD operations test
node test-crud.js

# Advanced comprehensive test
node test-advanced.js
```

## Backend Implementation

This SDK works with the Permas Calendar Service backend, which:

- Uses Node.js and Express
- Provides a RESTful API for calendar event management
- Supports MongoDB/CosmosDB via the permas-database-adapter
- Uses TypeScript for type safety

## License

MIT

## Environment-Based Integration

The SDK supports automatic configuration through environment variables:

```bash
# Google Calendar Integration
GOOGLE_CALENDAR_CLIENT_ID=your-client-id
GOOGLE_CALENDAR_CLIENT_SECRET=your-client-secret
GOOGLE_CALENDAR_REDIRECT_URI=http://localhost:3000/auth/google/callback

# iCal Feed Integration - comma-separated list of URLs
ICAL_FEEDS=https://calendar.google.com/calendar/ical/sample@example.com/public/basic.ics,https://example.com/events.ics
```

### Using Environment Configuration

Use the `useCalendarSyncWithConfig` hook to automatically sync with configured calendar sources:

```tsx
import { useCalendarSyncWithConfig } from 'calendar-service-sdk';

function CalendarApp() {
  const {
    events,            // All events from all sources
    loading,           // Loading state
    error,             // Error state
    config,            // Current environment configuration
    icalFeeds,         // iCal feed operations and status
    googleAuth,        // Google auth status and operations
    deleteEvent,       // Function to delete events
  } = useCalendarSyncWithConfig({
    autoSyncIcal: true,  // Auto-sync iCal feeds on load
    onIcalSyncComplete: (results) => {
      console.log('iCal sync complete', results);
    },
    onGoogleSyncComplete: (result, error) => {
      console.log('Google sync complete', result, error);
    }
  });

  // Example: Manually trigger iCal sync
  const handleSyncIcal = () => {
    icalFeeds.syncAll();
  };

  // Example: Initiate Google auth flow
  const handleGoogleLogin = () => {
    googleAuth.initiateAuth();
  };

  return (
    <div>
      <h1>Calendar Events ({events.length})</h1>
      {/* Your UI components */}
    </div>
  );
}
```

See the `examples/ConfiguredSyncExample.tsx` for a complete implementation.