Skip to content

Access & Utils

Authentication management and utility functions for the De. SDK.

Access & Utils Overview

Access provides workspace authentication and API request management.
Utils offers helper functions for common operations.

Together they provide the foundation for all SDK operations.

Access - Authentication

The Access class handles workspace authentication and HTTP requests to De. APIs.

Initialization

1

Basic Setup

Initialize with workspace credentials

typescript
import De from '@de./sdk'

const access = new De.Access({
  workspace: 'your-workspace-id',
  accessToken: 'your-access-token',
  env: 'prod'  // 'dev', 'staging', or 'prod'
})

Configuration Options:

typescript
{
  workspace: string           // Workspace ID (required)
  accessToken?: string        // Access token (optional for public endpoints)
  env?: 'dev' | 'staging' | 'prod'  // Environment
  apiUrl?: string            // Custom API URL
  timeout?: number           // Request timeout (ms)
  retries?: number           // Auto-retry count
  headers?: Record<string, string>  // Custom headers
}

Making Requests

1

GET Request

Fetch data from API

typescript
// Get user profile
const user = await access.request({
  url: '/user',
  method: 'GET'
})

console.log('User:', user.data)

// Get with query parameters
const orders = await access.request({
  url: '/orders',
  method: 'GET',
  query: {
    status: 'in_transit',
    limit: 20
  }
})

console.log('Orders:', orders.data)
2

POST Request

Create or submit data

typescript
// Create order
const order = await access.request({
  url: '/orders',
  method: 'POST',
  body: {
    type: 'delivery',
    customer: {
      name: 'John Doe',
      phone: '+1234567890'
    },
    pickup: {
      address: '123 Main St',
      coordinates: { lng: -74.0060, lat: 40.7128 }
    },
    delivery: {
      address: '456 Oak Ave',
      coordinates: { lng: -73.9855, lat: 40.7580 }
    }
  }
})

console.log('Order created:', order.data.id)
3

PATCH Request

Update existing data

typescript
// Update order
const updated = await access.request({
  url: `/orders/${orderId}`,
  method: 'PATCH',
  body: {
    status: 'in_transit',
    metadata: {
      priority: 'urgent'
    }
  }
})

console.log('Order updated:', updated.data)
4

DELETE Request

Remove data

typescript
// Cancel order
const result = await access.request({
  url: `/orders/${orderId}`,
  method: 'DELETE'
})

console.log('Order cancelled:', result.success)

Request Options

typescript
interface RequestOptions {
  url: string                          // API endpoint
  method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'
  query?: Record<string, any>          // Query parameters
  body?: any                           // Request body
  headers?: Record<string, string>     // Custom headers
  timeout?: number                     // Request timeout
  retries?: number                     // Retry attempts
  validateStatus?: (status: number) => boolean  // Custom validation
}

Response Format

typescript
interface APIResponse<T = any> {
  success: boolean
  data?: T
  error?: {
    code: string
    message: string
    details?: any
  }
  meta?: {
    timestamp: string
    requestId: string
  }
}

Token Management

Refreshing Tokens

1

Token Refresh

Refresh expired access token

typescript
// Store refresh token
const refreshToken = localStorage.getItem('refresh_token')

// Refresh access token
const result = await access.request({
  url: '/auth/refresh',
  method: 'POST',
  body: { refreshToken }
})

// Update access token
access.setAccessToken(result.data.token)
localStorage.setItem('access_token', result.data.token)

Auto Token Refresh

2

Automatic Refresh

Auto-refresh before expiration

typescript
class TokenManager {
  private access: any
  private refreshInterval: any
  
  constructor(access: any) {
    this.access = access
  }
  
  startAutoRefresh(tokenExpiresIn: number) {
    // Refresh 5 minutes before expiration
    const refreshTime = (tokenExpiresIn - 300) * 1000
    
    this.refreshInterval = setInterval(async () => {
      try {
        await this.refreshToken()
      } catch (error) {
        console.error('Token refresh failed:', error)
        this.handleRefreshFailure()
      }
    }, refreshTime)
  }
  
  async refreshToken() {
    const refreshToken = localStorage.getItem('refresh_token')
    
    const result = await this.access.request({
      url: '/auth/refresh',
      method: 'POST',
      body: { refreshToken }
    })
    
    this.access.setAccessToken(result.data.token)
    localStorage.setItem('access_token', result.data.token)
  }
  
  stopAutoRefresh() {
    clearInterval(this.refreshInterval)
  }
  
  private handleRefreshFailure() {
    // Redirect to login
    window.location.href = '/login'
  }
}

// Usage
const tokenManager = new TokenManager(access)
tokenManager.startAutoRefresh(3600) // Token expires in 1 hour

Error Handling

Handling Errors

typescript
try {
  const result = await access.request({
    url: '/orders',
    method: 'POST',
    body: orderData
  })
} catch (error: any) {
  switch (error.code) {
    case 'UNAUTHORIZED':
      // Token expired or invalid
      redirectToLogin()
      break
      
    case 'VALIDATION_ERROR':
      // Invalid request data
      showValidationErrors(error.details)
      break
      
    case 'RATE_LIMIT':
      // Too many requests
      const retryAfter = error.retryAfter || 60
      showRetryMessage(`Please wait ${retryAfter} seconds`)
      break
      
    case 'SERVER_ERROR':
      // Server issue
      showErrorMessage('Server error. Please try again later.')
      break
      
    case 'NETWORK_ERROR':
      // No internet connection
      showErrorMessage('No internet connection')
      break
      
    default:
      showErrorMessage(error.message)
  }
}

Retry Logic

typescript
async function requestWithRetry<T>(
  access: any,
  options: any,
  maxRetries = 3
): Promise<T> {
  let lastError: any
  
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await access.request(options)
    } catch (error: any) {
      lastError = error
      
      // Don't retry client errors (4xx)
      if (error.status >= 400 && error.status < 500) {
        throw error
      }
      
      // Wait before retry (exponential backoff)
      if (i < maxRetries - 1) {
        const delay = Math.pow(2, i) * 1000
        await new Promise(resolve => setTimeout(resolve, delay))
      }
    }
  }
  
  throw lastError
}

// Usage
const order = await requestWithRetry(access, {
  url: '/orders',
  method: 'POST',
  body: orderData
})

Utils - Helper Functions

Utility functions for common operations.

Distance Calculations

1

Calculate Distance

Distance between two coordinates

typescript
import { utils } from '@de./sdk'

const point1 = { lng: -74.0060, lat: 40.7128 }
const point2 = { lng: -73.9855, lat: 40.7580 }

// Calculate distance in meters
const distance = utils.calculateDistance(point1, point2)
console.log('Distance:', distance, 'meters')

// Calculate distance in kilometers
const distanceKm = utils.calculateDistance(point1, point2, 'km')
console.log('Distance:', distanceKm, 'km')

// Calculate distance in miles
const distanceMi = utils.calculateDistance(point1, point2, 'mi')
console.log('Distance:', distanceMi, 'miles')

Coordinate Formatting

2

Format Coordinates

Convert coordinate formats

typescript
// Decimal to DMS (Degrees, Minutes, Seconds)
const dms = utils.formatCoordinates({ lng: -74.0060, lat: 40.7128 }, 'dms')
console.log('DMS:', dms)
// "40°42'46.1"N 74°00'21.6"W"

// Decimal to human-readable
const readable = utils.formatCoordinates({ lng: -74.0060, lat: 40.7128 })
console.log('Readable:', readable)
// "40.7128, -74.0060"

// Parse from string
const coords = utils.parseCoordinates('40.7128, -74.0060')
console.log('Parsed:', coords)
// { lng: -74.0060, lat: 40.7128 }

Bounds Calculations

3

Calculate Bounds

Get bounding box for coordinates

typescript
const points = [
  { lng: -74.0060, lat: 40.7128 },
  { lng: -73.9855, lat: 40.7580 },
  { lng: -73.9951, lat: 40.7489 }
]

const bounds = utils.calculateBounds(points)
console.log('Bounds:', bounds)
// {
//   southwest: { lng: -74.0060, lat: 40.7128 },
//   northeast: { lng: -73.9855, lat: 40.7580 }
// }

// With padding
const paddedBounds = utils.calculateBounds(points, 0.01)

Distance Formatting

typescript
// Format distance
const formatted = utils.formatDistance(5420)
console.log(formatted)
// "5.42 km"

// With units
const metric = utils.formatDistance(5420, 'metric')
console.log(metric)
// "5.42 km"

const imperial = utils.formatDistance(5420, 'imperial')
console.log(imperial)
// "3.37 mi"

// Custom precision
const precise = utils.formatDistance(5420, 'metric', 1)
console.log(precise)
// "5.4 km"

Duration Formatting

typescript
// Format duration in seconds
const duration = utils.formatDuration(3665)
console.log(duration)
// "1h 1m 5s"

// Short format
const short = utils.formatDuration(3665, 'short')
console.log(short)
// "1:01:05"

// Human readable
const readable = utils.formatDuration(3665, 'readable')
console.log(readable)
// "1 hour, 1 minute"

Coordinate Validation

typescript
// Validate coordinates
const valid = utils.validateCoordinates({ lng: -74.0060, lat: 40.7128 })
console.log('Valid:', valid)
// true

const invalid = utils.validateCoordinates({ lng: 200, lat: 100 })
console.log('Valid:', invalid)
// false

// Validate bounds
const validBounds = utils.validateBounds({
  southwest: { lng: -74.1, lat: 40.6 },
  northeast: { lng: -73.9, lat: 40.8 }
})

Geocoding Utilities

typescript
// Extract coordinates from various formats
const coords1 = utils.extractCoordinates('40.7128, -74.0060')
const coords2 = utils.extractCoordinates('40.7128,-74.0060')
const coords3 = utils.extractCoordinates({ lat: 40.7128, lng: -74.0060 })

// All return: { lng: -74.0060, lat: 40.7128 }

// Format address
const formatted = utils.formatAddress({
  street: '123 Main St',
  city: 'New York',
  state: 'NY',
  postalCode: '10001',
  country: 'USA'
})
console.log(formatted)
// "123 Main St, New York, NY 10001, USA"

Array Utilities

typescript
// Chunk array
const items = [1, 2, 3, 4, 5, 6, 7, 8, 9]
const chunks = utils.chunk(items, 3)
console.log(chunks)
// [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

// Unique values
const unique = utils.unique([1, 2, 2, 3, 3, 3, 4])
console.log(unique)
// [1, 2, 3, 4]

// Group by property
const orders = [
  { id: 1, status: 'pending' },
  { id: 2, status: 'delivered' },
  { id: 3, status: 'pending' }
]
const grouped = utils.groupBy(orders, 'status')
console.log(grouped)
// {
//   pending: [{ id: 1, ... }, { id: 3, ... }],
//   delivered: [{ id: 2, ... }]
// }

Date Utilities

typescript
// Format timestamp
const formatted = utils.formatTimestamp(Date.now())
console.log(formatted)
// "2024-03-15 14:30:45"

// Relative time
const relative = utils.relativeTime(Date.now() - 3600000)
console.log(relative)
// "1 hour ago"

// Parse ISO date
const date = utils.parseDate('2024-03-15T14:30:00Z')
console.log(date)
// Date object

// Time difference
const diff = utils.timeDifference(start, end)
console.log(diff)
// { hours: 2, minutes: 30, seconds: 45 }

Complete Examples

Authenticated API Client

typescript
class APIClient {
  private access: any
  
  constructor(workspace: string, token: string) {
    this.access = new De.Access({
      workspace,
      accessToken: token,
      env: 'prod',
      timeout: 30000,
      retries: 3
    })
  }
  
  async getOrders(filters?: any) {
    return this.access.request({
      url: '/orders',
      method: 'GET',
      query: filters
    })
  }
  
  async createOrder(data: any) {
    return this.access.request({
      url: '/orders',
      method: 'POST',
      body: data
    })
  }
  
  async updateOrder(id: string, updates: any) {
    return this.access.request({
      url: `/orders/${id}`,
      method: 'PATCH',
      body: updates
    })
  }
  
  async cancelOrder(id: string, reason?: string) {
    return this.access.request({
      url: `/orders/${id}/cancel`,
      method: 'POST',
      body: { reason }
    })
  }
}

// Usage
const api = new APIClient(workspaceId, accessToken)

const orders = await api.getOrders({ status: 'in_transit' })
const newOrder = await api.createOrder(orderData)

Distance Calculator

typescript
class DistanceCalculator {
  calculateRouteDistance(waypoints: Location[]): number {
    let totalDistance = 0
    
    for (let i = 0; i < waypoints.length - 1; i++) {
      const distance = utils.calculateDistance(
        waypoints[i],
        waypoints[i + 1]
      )
      totalDistance += distance
    }
    
    return totalDistance
  }
  
  findNearestLocation(
    origin: Location,
    locations: Location[]
  ): Location & { distance: number } {
    return locations
      .map(loc => ({
        ...loc,
        distance: utils.calculateDistance(origin, loc)
      }))
      .sort((a, b) => a.distance - b.distance)[0]
  }
  
  isWithinRadius(
    center: Location,
    point: Location,
    radius: number
  ): boolean {
    const distance = utils.calculateDistance(center, point)
    return distance <= radius
  }
  
  formatDistanceForDisplay(meters: number, unit: 'metric' | 'imperial' = 'metric'): string {
    if (unit === 'imperial') {
      const miles = meters * 0.000621371
      return miles < 0.1 
        ? `${Math.round(meters * 3.28084)} ft`
        : `${miles.toFixed(2)} mi`
    }
    
    return meters < 1000
      ? `${Math.round(meters)} m`
      : `${(meters / 1000).toFixed(2)} km`
  }
}

// Usage
const calculator = new DistanceCalculator()

const routeDistance = calculator.calculateRouteDistance(waypoints)
const nearest = calculator.findNearestLocation(userLocation, warehouses)
const isNear = calculator.isWithinRadius(warehouse, delivery, 5000)

Type Definitions

typescript
interface AccessConfig {
  workspace: string
  accessToken?: string
  env?: 'dev' | 'staging' | 'prod'
  apiUrl?: string
  timeout?: number
  retries?: number
  headers?: Record<string, string>
}

interface Location {
  lng: number
  lat: number
}

interface Bounds {
  southwest: Location
  northeast: Location
}

interface Utils {
  calculateDistance(p1: Location, p2: Location, unit?: 'm' | 'km' | 'mi'): number
  formatCoordinates(coords: Location, format?: 'decimal' | 'dms'): string
  parseCoordinates(str: string): Location
  calculateBounds(points: Location[], padding?: number): Bounds
  validateCoordinates(coords: Location): boolean
  formatDistance(meters: number, unit?: 'metric' | 'imperial', precision?: number): string
  formatDuration(seconds: number, format?: 'long' | 'short' | 'readable'): string
}

Best Practices

Do

  • Store tokens securely (never in code)
  • Implement token refresh logic
  • Handle all error cases
  • Use appropriate timeout values
  • Validate data before requests
  • Cache frequently used data
  • Use utils for calculations

Avoid

  • Hardcoding credentials
  • Ignoring error responses
  • Making excessive API calls
  • Storing tokens in localStorage in production
  • Skipping input validation
  • Reinventing utility functions
  • Exposing tokens in client code

Environment Configuration

typescript
// config.ts
const config = {
  development: {
    workspace: process.env.DEV_WORKSPACE_ID,
    accessToken: process.env.DEV_ACCESS_TOKEN,
    apiUrl: 'https://dev-api.dedot.io'
  },
  staging: {
    workspace: process.env.STAGING_WORKSPACE_ID,
    accessToken: process.env.STAGING_ACCESS_TOKEN,
    apiUrl: 'https://staging-api.dedot.io'
  },
  production: {
    workspace: process.env.PROD_WORKSPACE_ID,
    accessToken: process.env.PROD_ACCESS_TOKEN,
    apiUrl: 'https://api.dedot.io'
  }
}

const env = process.env.NODE_ENV || 'development'
export default config[env]

// Usage
import config from './config'

const access = new De.Access(config)

Next Steps